diff --git a/app/assets/javascripts/app/controllers/footer.js b/app/assets/javascripts/app/controllers/footer.js index 47ac00b76..5aeb5b176 100644 --- a/app/assets/javascripts/app/controllers/footer.js +++ b/app/assets/javascripts/app/controllers/footer.js @@ -182,11 +182,12 @@ angular.module('app') if(!room.showRoom) { // About to show, check if has privileges - if(await privilegesManager.actionRequiresPrivilege(PrivilegesManager.ActionManageExtensions)) { privilegesManager.presentPrivilegesModal(PrivilegesManager.ActionManageExtensions, () => { run(); }); + } else { + run(); } } else { run(); diff --git a/app/assets/javascripts/app/directives/views/privilegesAuthModal.js b/app/assets/javascripts/app/directives/views/privilegesAuthModal.js index 99dad564d..072741c34 100644 --- a/app/assets/javascripts/app/directives/views/privilegesAuthModal.js +++ b/app/assets/javascripts/app/directives/views/privilegesAuthModal.js @@ -25,6 +25,17 @@ class PrivilegesAuthModal { 'ngInject'; $scope.authenticationParameters = {}; + $scope.sessionLengthOptions = privilegesManager.getSessionLengthOptions(); + + privilegesManager.getSelectedSessionLength().then((length) => { + $timeout(() => { + $scope.selectedSessionLength = length; + }) + }) + + $scope.selectSessionLength = function(length) { + $scope.selectedSessionLength = length; + } privilegesManager.getPrivileges().then((privileges) => { $timeout(() => { @@ -55,6 +66,7 @@ class PrivilegesAuthModal { privilegesManager.authenticateAction($scope.action, $scope.authenticationParameters).then((result) => { $timeout(() => { if(result.success) { + privilegesManager.setSessionLength($scope.selectedSessionLength); $scope.onSuccess(); $scope.dismiss(); } else { diff --git a/app/assets/javascripts/app/services/passcodeManager.js b/app/assets/javascripts/app/services/passcodeManager.js index 4abd4fba0..188a1aee7 100644 --- a/app/assets/javascripts/app/services/passcodeManager.js +++ b/app/assets/javascripts/app/services/passcodeManager.js @@ -89,11 +89,11 @@ class PasscodeManager { } async setAutoLockInterval(interval) { - return this.storageManager.setItem(PasscodeManager.AutoLockIntervalKey, JSON.stringify(interval), StorageManager.Fixed); + return this.storageManager.setItem(PasscodeManager.AutoLockIntervalKey, JSON.stringify(interval), StorageManager.FixedEncrypted); } async getAutoLockInterval() { - let interval = await this.storageManager.getItem(PasscodeManager.AutoLockIntervalKey, StorageManager.Fixed); + let interval = await this.storageManager.getItem(PasscodeManager.AutoLockIntervalKey, StorageManager.FixedEncrypted); if(interval) { return JSON.parse(interval); } else { diff --git a/app/assets/javascripts/app/services/privilegesManager.js b/app/assets/javascripts/app/services/privilegesManager.js index 178034d92..8b77653af 100644 --- a/app/assets/javascripts/app/services/privilegesManager.js +++ b/app/assets/javascripts/app/services/privilegesManager.js @@ -1,10 +1,11 @@ class PrivilegesManager { - constructor(passcodeManager, authManager, singletonManager, modelManager, $rootScope, $compile) { + constructor(passcodeManager, authManager, singletonManager, modelManager, storageManager, $rootScope, $compile) { this.passcodeManager = passcodeManager; this.authManager = authManager; this.singletonManager = singletonManager; this.modelManager = modelManager; + this.storageManager = storageManager; this.$rootScope = $rootScope; this.$compile = $compile; @@ -18,6 +19,14 @@ class PrivilegesManager { PrivilegesManager.ActionViewLockedNotes = "ActionViewLockedNotes"; PrivilegesManager.ActionManagePrivileges = "ActionManagePrivileges"; + PrivilegesManager.SessionExpiresAtKey = "SessionExpiresAtKey"; + PrivilegesManager.SessionLengthKey = "SessionLengthKey"; + + PrivilegesManager.SessionLengthNone = 0; + PrivilegesManager.SessionLengthFiveMinutes = 5; + PrivilegesManager.SessionLengthOneHour = 3600; + PrivilegesManager.SessionLengthOneWeek = 604800; + this.availableActions = [ PrivilegesManager.ActionManageExtensions, PrivilegesManager.ActionDownloadBackup, @@ -29,6 +38,14 @@ class PrivilegesManager { PrivilegesManager.CredentialAccountPassword, PrivilegesManager.CredentialLocalPasscode ]; + + this.sessionLengths = [ + PrivilegesManager.SessionLengthNone, + PrivilegesManager.SessionLengthFiveMinutes, + PrivilegesManager.SessionLengthOneHour, + PrivilegesManager.SessionLengthOneWeek, + PrivilegesManager.SessionLengthIndefinite + ] } getAvailableActions() { @@ -122,7 +139,7 @@ class PrivilegesManager { metadata[PrivilegesManager.ActionManageExtensions] = { label: "Manage Extensions" - } + }; metadata[PrivilegesManager.ActionDownloadBackup] = { label: "Download Backups" @@ -134,12 +151,70 @@ class PrivilegesManager { metadata[PrivilegesManager.ActionManagePrivileges] = { label: "Manage Privileges" - } + }; return metadata[action]; } + getSessionLengthOptions() { + return [ + { + value: PrivilegesManager.SessionLengthNone, + label: "Don't Remember" + }, + { + value: PrivilegesManager.SessionLengthFiveMinutes, + label: "5 Min" + }, + { + value: PrivilegesManager.SessionLengthOneHour, + label: "1 Hr" + }, + { + value: PrivilegesManager.SessionLengthOneWeek, + label: "1 Week" + } + ] + } + + async setSessionLength(length) { + let addToNow = (seconds) => { + let date = new Date(); + date.setSeconds(date.getSeconds() + seconds); + return date; + } + + let expiresAt = addToNow(length); + + return Promise.all([ + this.storageManager.setItem(PrivilegesManager.SessionExpiresAtKey, JSON.stringify(expiresAt), StorageManager.FixedEncrypted), + this.storageManager.setItem(PrivilegesManager.SessionLengthKey, JSON.stringify(length), StorageManager.FixedEncrypted), + ]) + } + + async getSelectedSessionLength() { + let length = await this.storageManager.getItem(PrivilegesManager.SessionLengthKey, StorageManager.FixedEncrypted); + if(length) { + return JSON.parse(length); + } else { + return PrivilegesManager.SessionLengthNone; + } + } + + async getSessionExpirey() { + let expiresAt = await this.storageManager.getItem(PrivilegesManager.SessionExpiresAtKey, StorageManager.FixedEncrypted); + if(expiresAt) { + return new Date(JSON.parse(expiresAt)); + } else { + return new Date(); + } + } + async actionRequiresPrivilege(action) { + let expiresAt = await this.getSessionExpirey(); + if(expiresAt > new Date()) { + return false; + } return (await this.getPrivileges()).getCredentialsForAction(action).length > 0; } diff --git a/app/assets/templates/directives/privileges-auth-modal.html.haml b/app/assets/templates/directives/privileges-auth-modal.html.haml index 2603614a0..fd9074df3 100644 --- a/app/assets/templates/directives/privileges-auth-modal.html.haml +++ b/app/assets/templates/directives/privileges-auth-modal.html.haml @@ -12,6 +12,12 @@ %p {{promptForCredential(credential)}} %input{"type" => "password", "ng-model" => "authenticationParameters[credential]"} %label.danger{"ng-if" => "isCredentialInFailureState(credential)"} Invalid authentication. Please try again. + .panel-row + .horizontal-group + %h4 Remember for + %a.info{"ng-repeat" => "option in sessionLengthOptions", "ng-click" => "selectSessionLength(option.value)", + "ng-class" => "{'info boxed' : option.value == selectedSessionLength}"} + {{option.label}} .footer .button.info.big.block.bold{"ng-click" => "submit()"} Submit