1
0
mirror of https://github.com/bitwarden/desktop.git synced 2024-11-30 12:54:31 +01:00

Vault Timeout Policy (#1052)

This commit is contained in:
Oscar Hinton 2021-09-15 20:02:46 +02:00 committed by GitHub
parent da4af743f3
commit aa19e678f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 116 additions and 18 deletions

View File

@ -7,14 +7,7 @@
{{'security' | i18n}}
</div>
<div class="box-content box-content-padded">
<div class="form-group">
<label for="vaultTimeouts">{{'vaultTimeout' | i18n}}</label>
<select id="vaultTimeouts" name="VaultTimeouts" [(ngModel)]="vaultTimeout"
(change)="saveVaultTimeoutOptions()">
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
</select>
<small class="help-block">{{'vaultTimeoutDesc' | i18n}}</small>
</div>
<app-vault-timeout-input [vaultTimeouts]="vaultTimeouts" [formControl]="vaultTimeout" ngDefaultControl></app-vault-timeout-input>
<div class="form-group">
<label>{{'vaultTimeoutAction' | i18n}}</label>
<div class="radio radio-mt-2">

View File

@ -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<number>(ConstantsService.vaultTimeoutKey);
this.vaultTimeout.setValue(await this.vaultTimeoutService.getVaultTimeout());
this.vaultTimeoutAction = await this.storageService.get<string>(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() {

View File

@ -0,0 +1,24 @@
<app-callout type="info" *ngIf="vaultTimeoutPolicy">
{{'vaultTimeoutPolicyInEffect' | i18n : vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes}}
</app-callout>
<div [formGroup]="form">
<div class="form-group">
<label for="vaultTimeout">{{'vaultTimeout' | i18n}}</label>
<select id="vaultTimeout" name="VaultTimeout" formControlName="vaultTimeout" class="form-control">
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
</select>
<small class="form-text text-muted">{{'vaultTimeoutDesc' | i18n}}</small>
</div>
<div class="form-group row" *ngIf="showCustom" formGroupName="custom">
<div class="col">
<label for="hours">{{'hours' | i18n}}</label>
<input id="hours" class="form-control" type="number" min="0" name="hours" formControlName="hours">
</div>
<div class="col">
<label for="minutes">{{'minutes' | i18n}}</label>
<input id="minutes" class="form-control" type="number" min="0" max="59" name="minutes" formControlName="minutes">
</div>
</div>
<div class="form-group"></div> <!-- Styling fix -->
</div>

View File

@ -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 {
}

View File

@ -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],

View File

@ -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 }));

View File

@ -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"
},

10
src/scss/grid.scss Normal file
View File

@ -0,0 +1,10 @@
.row {
display: flex;
margin: 0 -15px;
}
.col {
flex-basis: 0;
flex-grow: 1;
padding: 0 15px;
}

View File

@ -253,6 +253,11 @@ form, .form {
border-color: themed('inputBorderColor');
}
}
input[type=text], input[type=number] {
padding: 5px;
width: 100%;
}
}
.checkbox {

View File

@ -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";