1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-09-27 04:03:00 +02:00

Vault Timeout Policy (#2048)

This commit is contained in:
Oscar Hinton 2021-09-14 13:36:34 +02:00 committed by GitHub
parent 63d0b8f9d2
commit 2e6f0f4166
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 135 additions and 29 deletions

2
jslib

@ -1 +1 @@
Subproject commit 5f64d956520612a681611a27c5f4f2e5f27b640e
Subproject commit a85c45a34ed90b09f59ec27bdba754d66452915e

View File

@ -1764,7 +1764,7 @@
},
"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."
},
},
"resetPasswordPolicyAutoEnroll": {
"message": "Automatic Enrollment"
},
@ -1776,5 +1776,27 @@
},
"ssoCompleteRegistration": {
"message": "In order to complete logging in with SSO, please set a master password to access and protect your vault."
},
"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"
}
}
},
"vaultTimeoutToLarge": {
"message": "Your vault timeout exceeds the restrictions set by your organization."
}
}

View File

@ -197,7 +197,7 @@ export default class MainBackground {
this.policyService = new PolicyService(this.userService, this.storageService);
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService,
this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService,
this.messagingService, this.searchService, this.userService, this.tokenService,
this.messagingService, this.searchService, this.userService, this.tokenService, this.policyService,
async () => {
if (this.notificationsService != null) {
this.notificationsService.updateConnection(false);

View File

@ -37,6 +37,7 @@ import { OptionsComponent } from './settings/options.component';
import { PremiumComponent } from './settings/premium.component';
import { SettingsComponent } from './settings/settings.component';
import { SyncComponent } from './settings/sync.component';
import { VaultTimeoutInputComponent } from './settings/vault-timeout-input.component';
import { AddEditComponent } from './vault/add-edit.component';
import { AttachmentsComponent } from './vault/attachments.component';
@ -242,6 +243,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
UpdateTempPasswordComponent,
ViewComponent,
PasswordRepromptComponent,
VaultTimeoutInputComponent,
],
entryComponents: [],
providers: [

View File

@ -200,6 +200,13 @@
}
}
&.last:last-child:before {
border-bottom: 1px solid #000000;
@include themify($themes) {
border-bottom-color: themed('boxBorderColor');
}
}
&:after {
content: "";
display: table;

11
src/popup/scss/grid.scss Normal file
View File

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

View File

@ -1,6 +1,7 @@
@import "../css/webfonts.css";
@import "variables.scss";
@import "base.scss";
@import "grid.scss";
@import "box.scss";
@import "buttons.scss";
@import "misc.scss";

View File

@ -28,13 +28,7 @@
<div class="box list">
<div class="box-header">{{'security' | i18n}}</div>
<div class="box-content single-line">
<div class="box-content-row display-block" appBoxRow>
<label for="vaultTimeout">{{'vaultTimeout' | i18n}}</label>
<select #vaultTimeoutSelect id="vaultTimeout" name="VaultTimeouts" [ngModel]="vaultTimeout"
(ngModelChange)="saveVaultTimeout($event)">
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
</select>
</div>
<app-vault-timeout-input [vaultTimeouts]="vaultTimeouts" [formControl]="vaultTimeout" ngDefaultControl></app-vault-timeout-input>
<div class="box-content-row display-block" appBoxRow>
<label for="vaultTimeoutAction">{{'vaultTimeoutAction' | i18n}}</label>
<select #vaultTimeoutActionSelect id="vaultTimeoutAction" name="VaultTimeoutActions"

View File

@ -1,12 +1,13 @@
import Swal from 'sweetalert2/src/sweetalert2.js';
import {
Component,
ElementRef,
OnInit,
ViewChild,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import Swal from 'sweetalert2/src/sweetalert2.js';
import { BrowserApi } from '../../browser/browserApi';
@ -44,10 +45,8 @@ const RateUrls = {
templateUrl: 'settings.component.html',
})
export class SettingsComponent implements OnInit {
@ViewChild('vaultTimeoutSelect', { read: ElementRef, static: true }) vaultTimeoutSelectRef: ElementRef;
@ViewChild('vaultTimeoutActionSelect', { read: ElementRef, static: true }) vaultTimeoutActionSelectRef: ElementRef;
vaultTimeouts: any[];
vaultTimeout: number = null;
vaultTimeoutActions: any[];
vaultTimeoutAction: string;
pin: boolean = null;
@ -55,11 +54,14 @@ export class SettingsComponent implements OnInit {
biometric: boolean = false;
previousVaultTimeout: number = null;
vaultTimeout: FormControl = new FormControl(null);
constructor(private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
private vaultTimeoutService: VaultTimeoutService, private storageService: StorageService,
public messagingService: MessagingService, private router: Router,
private environmentService: EnvironmentService, private cryptoService: CryptoService,
private userService: UserService, private popupUtilsService: PopupUtilsService) {
private userService: UserService, private popupUtilsService: PopupUtilsService,
private toasterService: ToasterService) {
}
async ngOnInit() {
@ -89,14 +91,18 @@ export class SettingsComponent implements OnInit {
{ name: this.i18nService.t('logOut'), value: 'logOut' },
];
let timeout = await this.storageService.get<number>(ConstantsService.vaultTimeoutKey);
let timeout = await this.vaultTimeoutService.getVaultTimeout();
if (timeout != null) {
if (timeout === -2 && !showOnLocked) {
timeout = -1;
}
this.vaultTimeout = timeout;
this.vaultTimeout.setValue(timeout);
}
this.previousVaultTimeout = this.vaultTimeout;
this.previousVaultTimeout = this.vaultTimeout.value;
this.vaultTimeout.valueChanges.subscribe(value => {
this.saveVaultTimeout(value);
});
const action = await this.storageService.get<string>(ConstantsService.vaultTimeoutActionKey);
this.vaultTimeoutAction = action == null ? 'lock' : action;
@ -113,18 +119,19 @@ export class SettingsComponent implements OnInit {
this.i18nService.t('neverLockWarning'), null,
this.i18nService.t('yes'), this.i18nService.t('cancel'), 'warning');
if (!confirmed) {
this.vaultTimeouts.forEach((option: any, i) => {
if (option.value === this.vaultTimeout) {
this.vaultTimeoutSelectRef.nativeElement.value = i + ': ' + this.vaultTimeout;
}
});
this.vaultTimeout.setValue(this.previousVaultTimeout);
return;
}
}
this.previousVaultTimeout = this.vaultTimeout;
this.vaultTimeout = newValue;
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null,
this.vaultTimeoutAction);
if (!this.vaultTimeout.valid) {
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
return;
}
this.previousVaultTimeout = this.vaultTimeout.value;
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction);
if (this.previousVaultTimeout == null) {
this.messagingService.send('bgReseedStorage');
}
@ -145,9 +152,14 @@ export class SettingsComponent implements OnInit {
return;
}
}
if (!this.vaultTimeout.valid) {
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
return;
}
this.vaultTimeoutAction = newValue;
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null,
this.vaultTimeoutAction);
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction);
}
async updatePin() {

View File

@ -0,0 +1,29 @@
<app-callout type="info" *ngIf="vaultTimeoutPolicy">
{{'vaultTimeoutPolicyInEffect' | i18n : vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes}}
</app-callout>
<div [formGroup]="form">
<div class="box-content-row last display-block" appBoxRow>
<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>
</div>
<div class="box-content-row last" *ngIf="showCustom">
<div formGroupName="custom" class="row">
<div class="col">
<div class="display-block" appBoxRow>
<label for="customVaultTimeout">{{'hours' | i18n }}</label>
<input id="hours" class="form-control" type="number" min="0" name="hours" formControlName="hours">
</div>
</div>
<div class="col">
<div class="display-block" appBoxRow>
<label for="customVaultTimeout">{{'minutes' | i18n }}</label>
<input id="minutes" class="form-control" type="number" min="0" max="59" name="minutes"
formControlName="minutes">
</div>
</div>
</div>
</div>
</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 {
}