From aa19e678f7ddd7a0b9783f75883a5bf55d4fbe71 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 15 Sep 2021 20:02:46 +0200 Subject: [PATCH] Vault Timeout Policy (#1052) --- src/app/accounts/settings.component.html | 9 +----- src/app/accounts/settings.component.ts | 31 +++++++++++++------ .../vault-timeout-input.component.html | 24 ++++++++++++++ .../accounts/vault-timeout-input.component.ts | 28 +++++++++++++++++ src/app/app.module.ts | 2 ++ src/app/services.module.ts | 2 +- src/locales/en/messages.json | 22 +++++++++++++ src/scss/grid.scss | 10 ++++++ src/scss/misc.scss | 5 +++ src/scss/styles.scss | 1 + 10 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 src/app/accounts/vault-timeout-input.component.html create mode 100644 src/app/accounts/vault-timeout-input.component.ts create mode 100644 src/scss/grid.scss diff --git a/src/app/accounts/settings.component.html b/src/app/accounts/settings.component.html index 2852e6f1378..297f0f02fc9 100644 --- a/src/app/accounts/settings.component.html +++ b/src/app/accounts/settings.component.html @@ -7,14 +7,7 @@ {{'security' | i18n}}
-
- - - {{'vaultTimeoutDesc' | i18n}} -
+
diff --git a/src/app/accounts/settings.component.ts b/src/app/accounts/settings.component.ts index 47b5114da1c..93305726b3a 100644 --- a/src/app/accounts/settings.component.ts +++ b/src/app/accounts/settings.component.ts @@ -2,8 +2,8 @@ import { Component, OnInit, } from '@angular/core'; - -import Swal from 'sweetalert2/src/sweetalert2.js'; +import { FormControl } from '@angular/forms'; +import { debounceTime } from 'rxjs/operators'; import { DeviceType } from 'jslib-common/enums/deviceType'; @@ -13,7 +13,6 @@ import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StateService } from 'jslib-common/abstractions/state.service'; import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; import { ConstantsService } from 'jslib-common/services/constants.service'; @@ -32,7 +31,6 @@ import { SetPinComponent } from '../components/set-pin.component'; templateUrl: 'settings.component.html', }) export class SettingsComponent implements OnInit { - vaultTimeout: number = null; vaultTimeoutAction: string; pin: boolean = null; disableFavicons: boolean = false; @@ -70,11 +68,12 @@ export class SettingsComponent implements OnInit { startToTrayText: string; startToTrayDescText: string; + vaultTimeout: FormControl = new FormControl(null); + constructor(private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, private storageService: StorageService, private vaultTimeoutService: VaultTimeoutService, private stateService: StateService, private messagingService: MessagingService, - private userService: UserService, private cryptoService: CryptoService, - private modalService: ModalService) { + private cryptoService: CryptoService, private modalService: ModalService) { const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop; // Workaround to avoid ghosting trays https://github.com/electron/electron/issues/17622 @@ -117,6 +116,10 @@ export class SettingsComponent implements OnInit { { name: i18nService.t('never'), value: null }, ]); + this.vaultTimeout.valueChanges.pipe(debounceTime(500)).subscribe(() => { + this.saveVaultTimeoutOptions(); + }); + const localeOptions: any[] = []; i18nService.supportedTranslationLocales.forEach(locale => { let name = locale; @@ -149,7 +152,7 @@ export class SettingsComponent implements OnInit { async ngOnInit() { this.showMinToTray = this.platformUtilsService.getDevice() !== DeviceType.LinuxDesktop; - this.vaultTimeout = await this.storageService.get(ConstantsService.vaultTimeoutKey); + this.vaultTimeout.setValue(await this.vaultTimeoutService.getVaultTimeout()); this.vaultTimeoutAction = await this.storageService.get(ConstantsService.vaultTimeoutActionKey); const pinSet = await this.vaultTimeoutService.isPinLockSet(); this.pin = pinSet[0] || pinSet[1]; @@ -187,8 +190,18 @@ export class SettingsComponent implements OnInit { return; } } - await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null, - this.vaultTimeoutAction); + + // Avoid saving 0 since it's useless as a timeout value. + if (this.vaultTimeout.value === 0) { + return; + } + + if (!this.vaultTimeout.valid) { + this.platformUtilsService.showToast('error', null, this.i18nService.t('vaultTimeoutTooLarge')); + return; + } + + await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction); } async updatePin() { diff --git a/src/app/accounts/vault-timeout-input.component.html b/src/app/accounts/vault-timeout-input.component.html new file mode 100644 index 00000000000..f959adffc69 --- /dev/null +++ b/src/app/accounts/vault-timeout-input.component.html @@ -0,0 +1,24 @@ + + {{'vaultTimeoutPolicyInEffect' | i18n : vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes}} + + +
+
+ + + {{'vaultTimeoutDesc' | i18n}} +
+
+
+ + +
+
+ + +
+
+
+
diff --git a/src/app/accounts/vault-timeout-input.component.ts b/src/app/accounts/vault-timeout-input.component.ts new file mode 100644 index 00000000000..47335e51c46 --- /dev/null +++ b/src/app/accounts/vault-timeout-input.component.ts @@ -0,0 +1,28 @@ +import { Component } from '@angular/core'; +import { + NG_VALIDATORS, + NG_VALUE_ACCESSOR, +} from '@angular/forms'; + +import { + VaultTimeoutInputComponent as VaultTimeoutInputComponentBase +} from 'jslib-angular/components/settings/vault-timeout-input.component'; + +@Component({ + selector: 'app-vault-timeout-input', + templateUrl: 'vault-timeout-input.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: VaultTimeoutInputComponent, + }, + { + provide: NG_VALIDATORS, + multi: true, + useExisting: VaultTimeoutInputComponent, + }, + ], +}) +export class VaultTimeoutInputComponent extends VaultTimeoutInputComponentBase { +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 501ba8564f1..1895d07f64d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -28,6 +28,7 @@ import { SsoComponent } from './accounts/sso.component'; import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component'; import { TwoFactorComponent } from './accounts/two-factor.component'; import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component'; +import { VaultTimeoutInputComponent } from './accounts/vault-timeout-input.component'; import { CalloutComponent } from 'jslib-angular/components/callout.component'; import { IconComponent } from 'jslib-angular/components/icon.component'; @@ -224,6 +225,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); ViewComponent, PasswordRepromptComponent, SetPinComponent, + VaultTimeoutInputComponent, ], providers: [DatePipe], bootstrap: [AppComponent], diff --git a/src/app/services.module.ts b/src/app/services.module.ts index 1f4c8a5545f..6ff5a5af42a 100644 --- a/src/app/services.module.ts +++ b/src/app/services.module.ts @@ -120,7 +120,7 @@ const sendService = new SendService(cryptoService, userService, apiService, file const policyService = new PolicyService(userService, storageService); const vaultTimeoutService = new VaultTimeoutService(cipherService, folderService, collectionService, cryptoService, platformUtilsService, storageService, messagingService, searchService, userService, tokenService, - null, async () => messagingService.send('logout', { expired: false })); + policyService, null, async () => messagingService.send('logout', { expired: false })); const syncService = new SyncService(userService, apiService, settingsService, folderService, cipherService, cryptoService, collectionService, storageService, messagingService, policyService, sendService, async (expired: boolean) => messagingService.send('logout', { expired: expired })); diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 8e26db42047..1610f8ef9b6 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -1703,6 +1703,28 @@ "updateMasterPasswordWarning": { "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, "resetPasswordPolicyAutoEnroll": { "message": "Automatic Enrollment" }, diff --git a/src/scss/grid.scss b/src/scss/grid.scss new file mode 100644 index 00000000000..81d5ee2a2b9 --- /dev/null +++ b/src/scss/grid.scss @@ -0,0 +1,10 @@ +.row { + display: flex; + margin: 0 -15px; +} + +.col { + flex-basis: 0; + flex-grow: 1; + padding: 0 15px; +} diff --git a/src/scss/misc.scss b/src/scss/misc.scss index 819fbbd9cb2..d9699e81538 100644 --- a/src/scss/misc.scss +++ b/src/scss/misc.scss @@ -253,6 +253,11 @@ form, .form { border-color: themed('inputBorderColor'); } } + + input[type=text], input[type=number] { + padding: 5px; + width: 100%; + } } .checkbox { diff --git a/src/scss/styles.scss b/src/scss/styles.scss index c75e55a93a5..968100e119d 100644 --- a/src/scss/styles.scss +++ b/src/scss/styles.scss @@ -1,6 +1,7 @@ @import "../css/webfonts.css"; @import "variables.scss"; @import "base.scss"; +@import "grid.scss"; @import "pages.scss"; @import "vault.scss"; @import "list.scss";