From 363fb7bd7f59712fb01cd424ac4f46f89491995b Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Sun, 16 Dec 2018 16:38:19 -0600 Subject: [PATCH] Resave session history on passcode change --- .../app/directives/views/accountMenu.js | 3 +- .../directives/views/revisionPreviewModal.js | 4 +- .../app/services/passcodeManager.js | 156 ++++++++++-------- .../app/services/sessionHistory.js | 7 + 4 files changed, 100 insertions(+), 70 deletions(-) diff --git a/app/assets/javascripts/app/directives/views/accountMenu.js b/app/assets/javascripts/app/directives/views/accountMenu.js index f163892ce..6407cc2f3 100644 --- a/app/assets/javascripts/app/directives/views/accountMenu.js +++ b/app/assets/javascripts/app/directives/views/accountMenu.js @@ -440,6 +440,8 @@ class AccountMenu { fn(passcode, () => { $timeout(() => { + $scope.formData.passcode = null; + $scope.formData.confirmPasscode = null; $scope.formData.showPasscodeForm = false; var offline = authManager.offline(); @@ -457,7 +459,6 @@ class AccountMenu { $timeout(() => { $scope.formData.changingPasscode = true; $scope.addPasscodeClicked(); - $scope.formData.changingPasscode = false; }) } diff --git a/app/assets/javascripts/app/directives/views/revisionPreviewModal.js b/app/assets/javascripts/app/directives/views/revisionPreviewModal.js index 03fde5113..534189f8c 100644 --- a/app/assets/javascripts/app/directives/views/revisionPreviewModal.js +++ b/app/assets/javascripts/app/directives/views/revisionPreviewModal.js @@ -22,7 +22,9 @@ class RevisionPreviewModal { } $scope.$on("$destroy", function() { - componentManager.deregisterHandler($scope.identifier); + if($scope.identifier) { + componentManager.deregisterHandler($scope.identifier); + } }); $scope.note = new SFItem({content: $scope.content, content_type: "Note"}); diff --git a/app/assets/javascripts/app/services/passcodeManager.js b/app/assets/javascripts/app/services/passcodeManager.js index 55948953d..765ac7345 100644 --- a/app/assets/javascripts/app/services/passcodeManager.js +++ b/app/assets/javascripts/app/services/passcodeManager.js @@ -1,83 +1,20 @@ class PasscodeManager { constructor($rootScope, authManager, storageManager) { - if(isDesktopApplication()) { - // desktop only - $rootScope.$on("window-lost-focus", () => { - let visible = false; - this.documentVisibilityChanged(visible); - }) - } else { - // tab visibility listender, web only - document.addEventListener('visibilitychange', (e) => { - let visible = document.visibilityState == "visible"; - this.documentVisibilityChanged(visible); - }); - } - - this.authManager = authManager; this.storageManager = storageManager; + this.$rootScope = $rootScope; this._hasPasscode = this.storageManager.getItemSync("offlineParams", StorageManager.Fixed) != null; this._locked = this._hasPasscode; - const MillisecondsPerSecond = 1000; - PasscodeManager.AutoLockIntervalNone = 0; - PasscodeManager.AutoLockIntervalImmediate = 1; - PasscodeManager.AutoLockIntervalOneMinute = 60 * MillisecondsPerSecond; - PasscodeManager.AutoLockIntervalFiveMinutes = 300 * MillisecondsPerSecond; - PasscodeManager.AutoLockIntervalOneHour = 3600 * MillisecondsPerSecond; + this.passcodeChangeObservers = []; - PasscodeManager.AutoLockIntervalKey = "AutoLockIntervalKey"; + this.configureAutoLock(); } - getAutoLockIntervalOptions() { - return [ - { - value: PasscodeManager.AutoLockIntervalNone, - label: "None" - }, - { - value: PasscodeManager.AutoLockIntervalImmediate, - label: "Immediately" - }, - { - value: PasscodeManager.AutoLockIntervalOneMinute, - label: "1 Min" - }, - { - value: PasscodeManager.AutoLockIntervalFiveMinutes, - label: "5 Min" - }, - { - value: PasscodeManager.AutoLockIntervalOneHour, - label: "1 Hr" - } - ] - } - - documentVisibilityChanged(visible) { - if(!visible) { - this.beginAutoLockTimer(); - } else { - this.cancelAutoLockTimer(); - } - } - - async beginAutoLockTimer() { - var interval = await this.getAutoLockInterval(); - if(interval == PasscodeManager.AutoLockIntervalNone) { - return; - } - - this.lockTimeout = setTimeout(() => { - this.lockApplication(); - }, interval); - } - - cancelAutoLockTimer() { - clearTimeout(this.lockTimeout); + addPasscodeChangeObserver(callback) { + this.passcodeChangeObservers.push(callback); } lockApplication() { @@ -171,6 +108,8 @@ class PasscodeManager { // After it's cleared, it's safe to write to it this.storageManager.setItem("offlineParams", JSON.stringify(authParams), StorageManager.Fixed); callback(true); + + this.notifyObserversOfPasscodeChange(); }); } @@ -183,6 +122,14 @@ class PasscodeManager { this.storageManager.removeItem("offlineParams", StorageManager.Fixed); this._keys = null; this._hasPasscode = false; + + this.notifyObserversOfPasscodeChange(); + } + + notifyObserversOfPasscodeChange() { + for(var observer of this.passcodeChangeObservers) { + observer(); + } } encryptLocalStorage(keys, authParams) { @@ -196,6 +143,79 @@ class PasscodeManager { this.storageManager.setKeys(keys, authParams); return this.storageManager.decryptStorage(); } + + configureAutoLock() { + if(isDesktopApplication()) { + // desktop only + this.$rootScope.$on("window-lost-focus", () => { + let visible = false; + this.documentVisibilityChanged(visible); + }) + } else { + // tab visibility listender, web only + document.addEventListener('visibilitychange', (e) => { + let visible = document.visibilityState == "visible"; + this.documentVisibilityChanged(visible); + }); + } + + const MillisecondsPerSecond = 1000; + PasscodeManager.AutoLockIntervalNone = 0; + PasscodeManager.AutoLockIntervalImmediate = 1; + PasscodeManager.AutoLockIntervalOneMinute = 60 * MillisecondsPerSecond; + PasscodeManager.AutoLockIntervalFiveMinutes = 300 * MillisecondsPerSecond; + PasscodeManager.AutoLockIntervalOneHour = 3600 * MillisecondsPerSecond; + + PasscodeManager.AutoLockIntervalKey = "AutoLockIntervalKey"; + } + + getAutoLockIntervalOptions() { + return [ + { + value: PasscodeManager.AutoLockIntervalNone, + label: "None" + }, + { + value: PasscodeManager.AutoLockIntervalImmediate, + label: "Immediately" + }, + { + value: PasscodeManager.AutoLockIntervalOneMinute, + label: "1 Min" + }, + { + value: PasscodeManager.AutoLockIntervalFiveMinutes, + label: "5 Min" + }, + { + value: PasscodeManager.AutoLockIntervalOneHour, + label: "1 Hr" + } + ] + } + + documentVisibilityChanged(visible) { + if(!visible) { + this.beginAutoLockTimer(); + } else { + this.cancelAutoLockTimer(); + } + } + + async beginAutoLockTimer() { + var interval = await this.getAutoLockInterval(); + if(interval == PasscodeManager.AutoLockIntervalNone) { + return; + } + + this.lockTimeout = setTimeout(() => { + this.lockApplication(); + }, interval); + } + + cancelAutoLockTimer() { + clearTimeout(this.lockTimeout); + } } angular.module('app').service('passcodeManager', PasscodeManager); diff --git a/app/assets/javascripts/app/services/sessionHistory.js b/app/assets/javascripts/app/services/sessionHistory.js index d64dec37f..7b5ac9f04 100644 --- a/app/assets/javascripts/app/services/sessionHistory.js +++ b/app/assets/javascripts/app/services/sessionHistory.js @@ -6,10 +6,17 @@ class SessionHistory extends SFSessionHistoryManager { "Note" : NoteHistoryEntry } + // Session History can be encrypted with passcode keys. If it changes, we need to resave session + // history with the new keys. + passcodeManager.addPasscodeChangeObserver(() => { + this.saveToDisk(); + }) + var keyRequestHandler = async () => { let offline = authManager.offline(); let auth_params = offline ? passcodeManager.passcodeAuthParams() : await authManager.getAuthParams(); let keys = offline ? passcodeManager.keys() : await authManager.keys(); + return { keys: keys, offline: offline,