diff --git a/angular/src/components/settings/vault-timeout-input.component.ts b/angular/src/components/settings/vault-timeout-input.component.ts deleted file mode 100644 index 749e75953a..0000000000 --- a/angular/src/components/settings/vault-timeout-input.component.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { - Directive, - Input, - OnInit, -} from '@angular/core'; -import { - AbstractControl, - ControlValueAccessor, - FormBuilder, - ValidationErrors, - Validator -} from '@angular/forms'; - -import { I18nService } from 'jslib-common/abstractions/i18n.service'; -import { PolicyService } from 'jslib-common/abstractions/policy.service'; - -import { PolicyType } from 'jslib-common/enums/policyType'; -import { Policy } from 'jslib-common/models/domain/policy'; - -@Directive() -export class VaultTimeoutInputComponent implements ControlValueAccessor, Validator, OnInit { - - get showCustom() { - return this.form.get('vaultTimeout').value === VaultTimeoutInputComponent.CUSTOM_VALUE; - } - - static CUSTOM_VALUE = -100; - - form = this.fb.group({ - vaultTimeout: [null], - custom: this.fb.group({ - hours: [null], - minutes: [null], - }), - }); - - @Input() vaultTimeouts: { name: string; value: number; }[]; - vaultTimeoutPolicy: Policy; - vaultTimeoutPolicyHours: number; - vaultTimeoutPolicyMinutes: number; - - private onChange: (vaultTimeout: number) => void; - private validatorChange: () => void; - - constructor(private fb: FormBuilder, private policyService: PolicyService, private i18nService: I18nService) { - } - - async ngOnInit() { - if (await this.policyService.policyAppliesToUser(PolicyType.MaximumVaultTimeout)) { - const vaultTimeoutPolicy = await this.policyService.getAll(PolicyType.MaximumVaultTimeout); - - this.vaultTimeoutPolicy = vaultTimeoutPolicy[0]; - this.vaultTimeoutPolicyHours = Math.floor(this.vaultTimeoutPolicy.data.minutes / 60); - this.vaultTimeoutPolicyMinutes = this.vaultTimeoutPolicy.data.minutes % 60; - - this.vaultTimeouts = this.vaultTimeouts.filter(t => - t.value <= this.vaultTimeoutPolicy.data.minutes && - (t.value > 0 || t.value === VaultTimeoutInputComponent.CUSTOM_VALUE) && - t.value != null - ); - this.validatorChange(); - } - - this.form.valueChanges.subscribe(async value => { - this.onChange(this.getVaultTimeout(value)); - }); - - // Assign the previous value to the custom fields - this.form.get('vaultTimeout').valueChanges.subscribe(value => { - if (value !== VaultTimeoutInputComponent.CUSTOM_VALUE) { - return; - } - - const current = Math.max(this.form.value.vaultTimeout, 0); - this.form.patchValue({ - custom: { - hours: Math.floor(current / 60), - minutes: current % 60, - }, - }); - }); - } - - ngOnChanges() { - this.vaultTimeouts.push({ name: this.i18nService.t('custom'), value: VaultTimeoutInputComponent.CUSTOM_VALUE }); - } - - getVaultTimeout(value: any) { - if (value.vaultTimeout !== VaultTimeoutInputComponent.CUSTOM_VALUE) { - return value.vaultTimeout; - } - - return value.custom.hours * 60 + value.custom.minutes; - } - - writeValue(value: number): void { - if (value == null) { - return; - } - - if (this.vaultTimeouts.every(p => p.value !== value)) { - this.form.setValue({ - vaultTimeout: VaultTimeoutInputComponent.CUSTOM_VALUE, - custom: { - hours: Math.floor(value / 60), - minutes: value % 60, - }, - }); - return; - } - - this.form.patchValue({ - vaultTimeout: value, - }); - } - - registerOnChange(onChange: any): void { - this.onChange = onChange; - } - - // tslint:disable-next-line - registerOnTouched(onTouched: any): void {} - - // tslint:disable-next-line - setDisabledState?(isDisabled: boolean): void { } - - validate(control: AbstractControl): ValidationErrors { - if (this.vaultTimeoutPolicy && this.vaultTimeoutPolicy?.data?.minutes < control.value) { - return { policyError: true }; - } - - return null; - } - - registerOnValidatorChange(fn: () => void): void { - this.validatorChange = fn; - } -} diff --git a/common/src/abstractions/platformUtils.service.ts b/common/src/abstractions/platformUtils.service.ts index 5e0f311a12..8828d3af7b 100644 --- a/common/src/abstractions/platformUtils.service.ts +++ b/common/src/abstractions/platformUtils.service.ts @@ -13,6 +13,10 @@ export abstract class PlatformUtilsService { isIE: () => boolean; isMacAppStore: () => boolean; isViewOpen: () => Promise; + /** + * @deprecated This only ever returns null. Pull from your platform's storage using ConstantsService.vaultTimeoutKey + */ + lockTimeout: () => number; launchUri: (uri: string, options?: any) => void; saveFile: (win: Window, blobData: any, blobOptions: any, fileName: string) => void; getApplicationVersion: () => Promise; diff --git a/common/src/abstractions/vaultTimeout.service.ts b/common/src/abstractions/vaultTimeout.service.ts index a5944c4813..d709d363b3 100644 --- a/common/src/abstractions/vaultTimeout.service.ts +++ b/common/src/abstractions/vaultTimeout.service.ts @@ -9,7 +9,6 @@ export abstract class VaultTimeoutService { lock: (allowSoftLock?: boolean) => Promise; logOut: () => Promise; setVaultTimeoutOptions: (vaultTimeout: number, vaultTimeoutAction: string) => Promise; - getVaultTimeout: () => Promise; isPinLockSet: () => Promise<[boolean, boolean]>; isBiometricLockSet: () => Promise; clear: () => Promise; diff --git a/common/src/enums/policyType.ts b/common/src/enums/policyType.ts index 9af8cebd9b..8d5020988a 100644 --- a/common/src/enums/policyType.ts +++ b/common/src/enums/policyType.ts @@ -8,5 +8,4 @@ export enum PolicyType { DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow - MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout } diff --git a/common/src/services/vaultTimeout.service.ts b/common/src/services/vaultTimeout.service.ts index 907f382995..b08ed1d205 100644 --- a/common/src/services/vaultTimeout.service.ts +++ b/common/src/services/vaultTimeout.service.ts @@ -6,14 +6,12 @@ import { CryptoService } from '../abstractions/crypto.service'; import { FolderService } from '../abstractions/folder.service'; import { MessagingService } from '../abstractions/messaging.service'; import { PlatformUtilsService } from '../abstractions/platformUtils.service'; -import { PolicyService } from '../abstractions/policy.service'; import { SearchService } from '../abstractions/search.service'; import { StorageService } from '../abstractions/storage.service'; import { TokenService } from '../abstractions/token.service'; import { UserService } from '../abstractions/user.service'; import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from '../abstractions/vaultTimeout.service'; -import { PolicyType } from '../enums/policyType'; import { EncString } from '../models/domain/encString'; export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { @@ -27,7 +25,7 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { private collectionService: CollectionService, private cryptoService: CryptoService, protected platformUtilsService: PlatformUtilsService, private storageService: StorageService, private messagingService: MessagingService, private searchService: SearchService, - private userService: UserService, private tokenService: TokenService, private policyService: PolicyService, + private userService: UserService, private tokenService: TokenService, private lockedCallback: () => Promise = null, private loggedOutCallback: () => Promise = null) { } @@ -73,7 +71,12 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { return; } - const vaultTimeout = await this.getVaultTimeout(); + // This has the potential to be removed. Evaluate after all platforms complete with auto-logout + let vaultTimeout = this.platformUtilsService.lockTimeout(); + if (vaultTimeout == null) { + vaultTimeout = await this.storageService.get(ConstantsService.vaultTimeoutKey); + } + if (vaultTimeout == null || vaultTimeout < 0) { return; } @@ -138,29 +141,6 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { return await this.storageService.get(ConstantsService.biometricUnlockKey); } - async getVaultTimeout(): Promise { - const vaultTimeout = await this.storageService.get(ConstantsService.vaultTimeoutKey); - - if (await this.policyService.policyAppliesToUser(PolicyType.MaximumVaultTimeout)) { - const policy = await this.policyService.getAll(PolicyType.MaximumVaultTimeout); - // Remove negative values, and ensure it's smaller than maximum allowed value according to policy - let timeout = Math.min(vaultTimeout, policy[0].data.minutes); - - if (vaultTimeout == null || timeout < 0) { - timeout = policy[0].data.minutes; - } - - // We really shouldn't need to set the value here, but multiple services relies on this value being correct. - if (vaultTimeout !== timeout) { - await this.storageService.save(ConstantsService.vaultTimeoutKey, timeout); - } - - return timeout; - } - - return vaultTimeout; - } - clear(): Promise { this.everBeenUnlocked = false; this.pinProtectedKey = null; diff --git a/electron/src/services/electronPlatformUtils.service.ts b/electron/src/services/electronPlatformUtils.service.ts index 07f9660396..87f719defd 100644 --- a/electron/src/services/electronPlatformUtils.service.ts +++ b/electron/src/services/electronPlatformUtils.service.ts @@ -88,6 +88,10 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService { return Promise.resolve(false); } + lockTimeout(): number { + return null; + } + launchUri(uri: string, options?: any): void { shell.openExternal(uri); } diff --git a/node/src/cli/services/cliPlatformUtils.service.ts b/node/src/cli/services/cliPlatformUtils.service.ts index 0b81b2e854..fe2af22c4e 100644 --- a/node/src/cli/services/cliPlatformUtils.service.ts +++ b/node/src/cli/services/cliPlatformUtils.service.ts @@ -76,6 +76,10 @@ export class CliPlatformUtilsService implements PlatformUtilsService { return Promise.resolve(false); } + lockTimeout(): number { + return null; + } + launchUri(uri: string, options?: any): void { if (process.platform === 'linux') { child_process.spawnSync('xdg-open', [uri]);