1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 08:43:33 +00:00

pin locking

This commit is contained in:
Kyle Spearrin
2019-02-13 10:06:58 -05:00
parent e0c7cb4bd6
commit 2c91a2004c
10 changed files with 158 additions and 17 deletions

View File

@@ -1,11 +1,16 @@
<form id="lock-page" (ngSubmit)="submit()">
<div class="content">
<p><i class="fa fa-lock fa-4x text-muted"></i></p>
<p>{{'yourVaultIsLocked' | i18n}}</p>
<p>{{(pinLock ? 'yourVaultIsLockedPinCode' : 'yourVaultIsLocked') | i18n}}</p>
<div class="box last">
<div class="box-content">
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
<div class="row-main" *ngIf="pinLock">
<label for="pin">{{'pin' | i18n}}</label>
<input id="pin" type="{{showPassword ? 'text' : 'password'}}" name="PIN"
class="monospaced" [(ngModel)]="pin" required appAutofocus>
</div>
<div class="row-main" *ngIf="!pinLock">
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
class="monospaced" [(ngModel)]="masterPassword" required appAutofocus>

View File

@@ -10,6 +10,7 @@ import {
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LockService } from 'jslib/abstractions/lock.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StorageService } from 'jslib/abstractions/storage.service';
@@ -30,8 +31,9 @@ export class LockComponent extends BaseLockComponent implements OnDestroy {
platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
userService: UserService, cryptoService: CryptoService,
private ngZone: NgZone, private route: ActivatedRoute,
private storageService: StorageService) {
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService);
storageService: StorageService, lockService: LockService) {
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
storageService, lockService);
}
async ngOnInit() {

View File

@@ -15,6 +15,14 @@
</select>
<small class="help-block">{{'lockOptionsDesc' | i18n}}</small>
</div>
<div class="form-group">
<div class="checkbox">
<label for="pin">
<input id="pin" type="checkbox" name="PIN" [(ngModel)]="pin" (change)="updatePin()">
{{'unlockWithPin' | i18n}}
</label>
</div>
</div>
</div>
</div>
<div class="box">

View File

@@ -5,15 +5,18 @@ import {
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import swal from 'sweetalert';
import { DeviceType } from 'jslib/enums/deviceType';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LockService } from 'jslib/abstractions/lock.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { UserService } from 'jslib/abstractions/user.service';
import { ConstantsService } from 'jslib/services/constants.service';
@@ -27,6 +30,7 @@ import { Utils } from 'jslib/misc/utils';
})
export class SettingsComponent implements OnInit {
lockOption: number = null;
pin: boolean = null;
disableFavicons: boolean = false;
enableMinToTray: boolean = false;
enableCloseToTray: boolean = false;
@@ -40,9 +44,10 @@ export class SettingsComponent implements OnInit {
themeOptions: any[];
constructor(private analytics: Angulartics2, private toasterService: ToasterService,
i18nService: I18nService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService, private platformUtilsService: PlatformUtilsService,
private storageService: StorageService, private lockService: LockService,
private stateService: StateService, private messagingService: MessagingService) {
private stateService: StateService, private messagingService: MessagingService,
private userService: UserService, private cryptoService: CryptoService) {
this.lockOptions = [
// { name: i18nService.t('immediately'), value: 0 },
{ name: i18nService.t('oneMinute'), value: 1 },
@@ -77,6 +82,7 @@ export class SettingsComponent implements OnInit {
async ngOnInit() {
this.showMinToTray = this.platformUtilsService.getDevice() === DeviceType.WindowsDesktop;
this.lockOption = await this.storageService.get<number>(ConstantsService.lockOptionKey);
this.pin = await this.lockService.isPinLockSet();
this.disableFavicons = await this.storageService.get<boolean>(ConstantsService.disableFaviconKey);
this.enableMinToTray = await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey);
this.enableCloseToTray = await this.storageService.get<boolean>(ElectronConstants.enableCloseToTrayKey);
@@ -90,6 +96,31 @@ export class SettingsComponent implements OnInit {
await this.lockService.setLockOption(this.lockOption != null ? this.lockOption : null);
}
async updatePin() {
if (this.pin) {
const pin = await swal({
text: this.i18nService.t('setYourPinCode'),
content: { element: 'input' },
buttons: [this.i18nService.t('cancel'), this.i18nService.t('submit')],
});
if (pin != null && pin.trim() !== '') {
const kdf = await this.userService.getKdf();
const kdfIterations = await this.userService.getKdfIterations();
const email = await this.userService.getEmail();
const pinKey = await this.cryptoService.makePinKey(pin, email, kdf, kdfIterations);
const key = await this.cryptoService.getKey();
const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
await this.storageService.save(ConstantsService.pinProtectedKey, pinProtectedKey.encryptedString);
} else {
this.pin = false;
}
}
if (!this.pin) {
await this.storageService.remove(ConstantsService.pinProtectedKey);
}
}
async saveFavicons() {
await this.storageService.save(ConstantsService.disableFaviconKey, this.disableFavicons);
await this.stateService.save(ConstantsService.disableFaviconKey, this.disableFavicons);

View File

@@ -1169,5 +1169,24 @@
},
"weakMasterPasswordDesc": {
"message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?"
},
"pin": {
"message": "PIN",
"description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device."
},
"unlockWithPin": {
"message": "Unlock with PIN"
},
"setYourPinCode": {
"message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application."
},
"pinRequired": {
"message": "PIN code is required."
},
"invalidPin": {
"message": "Invalid PIN code."
},
"yourVaultIsLockedPinCode": {
"message": "Your vault is locked. Verify your PIN code to continue."
}
}

View File

@@ -95,3 +95,53 @@ $fa-font-path: "~font-awesome/fonts";
}
}
}
// SweetAlert
.swal-modal {
border-radius: $border-radius;
@include themify($themes) {
background-color: themed('backgroundColorAlt');
color: themed('textColor');
}
.swal-text {
font-size: $font-size-base;
@include themify($themes) {
color: themed('textColor');
}
}
> .swal-text:first-child {
margin-top: 20px;
}
.swal-content__input, .swal-content__textarea {
border: 1px solid #000000;
border-radius: $border-radius;
@include themify($themes) {
border-color: themed('inputBorderColor');
color: themed('textColor');
background-color: themed('inputBackgroundColor');
}
}
.swal-footer {
padding: 15px 10px 10px 10px;
margin: 0;
.swal-button {
@extend .btn;
&:focus {
box-shadow: none;
}
}
.swal-button--confirm {
@extend .btn.primary;
}
}
}