From 10029910222f296f645c5e06f252061721235404 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Thu, 14 Feb 2019 14:00:09 -0500 Subject: [PATCH] soft lock with PIN --- jslib | 2 +- src/app/accounts/settings.component.ts | 46 ++++++++++++++++++++------ src/app/app.component.ts | 6 ++-- src/app/services.module.ts | 2 +- src/locales/en/messages.json | 3 ++ src/scss/plugins.scss | 15 +++++++++ 6 files changed, 59 insertions(+), 15 deletions(-) diff --git a/jslib b/jslib index f67fac3eebc..a19a30ffed1 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit f67fac3eebc21b8935a54a28b7a21152c8513322 +Subproject commit a19a30ffed177e18d6e64801066510bc983a3e8d diff --git a/src/app/accounts/settings.component.ts b/src/app/accounts/settings.component.ts index 0d232617cdd..ecfbb0d92f3 100644 --- a/src/app/accounts/settings.component.ts +++ b/src/app/accounts/settings.component.ts @@ -82,7 +82,8 @@ export class SettingsComponent implements OnInit { async ngOnInit() { this.showMinToTray = this.platformUtilsService.getDevice() === DeviceType.WindowsDesktop; this.lockOption = await this.storageService.get(ConstantsService.lockOptionKey); - this.pin = await this.lockService.isPinLockSet(); + const pinSet = await this.lockService.isPinLockSet(); + this.pin = pinSet[0] || pinSet[1]; this.disableFavicons = await this.storageService.get(ConstantsService.disableFaviconKey); this.enableMinToTray = await this.storageService.get(ElectronConstants.enableMinimizeToTrayKey); this.enableCloseToTray = await this.storageService.get(ElectronConstants.enableCloseToTrayKey); @@ -98,26 +99,49 @@ export class SettingsComponent implements OnInit { async updatePin() { if (this.pin) { - const pin = await swal({ + const div = document.createElement('div'); + const label = document.createElement('label'); + label.className = 'checkbox'; + const checkboxText = document.createElement('span'); + const restartText = document.createTextNode(this.i18nService.t('lockWithMasterPassOnRestart')); + checkboxText.appendChild(restartText); + label.innerHTML = ''; + label.appendChild(checkboxText); + div.innerHTML = ''; + (div.querySelector('#pin-val') as HTMLInputElement).placeholder = this.i18nService.t('pin'); + div.appendChild(label); + + const submitted = await swal({ text: this.i18nService.t('setYourPinCode'), - content: { element: 'input' }, + content: { element: div }, buttons: [this.i18nService.t('cancel'), this.i18nService.t('submit')], }); - + let pin: string = null; + let masterPassOnRestart: boolean = null; + if (submitted) { + pin = (document.getElementById('pin-val') as HTMLInputElement).value; + masterPassOnRestart = (document.getElementById('master-pass-restart') as HTMLInputElement).checked; + } 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); + if (masterPassOnRestart) { + const encPin = await this.cryptoService.encrypt(pin); + await this.storageService.save(ConstantsService.protectedPin, encPin.encryptedString); + } else { + 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); + await this.storageService.remove(ConstantsService.protectedPin); } } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2088d9c647a..8e0a817ade1 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -120,7 +120,7 @@ export class AppComponent implements OnInit { this.logOut(!!message.expired); break; case 'lockVault': - await this.lockService.lock(); + await this.lockService.lock(true); break; case 'locked': this.router.navigate(['lock'], { queryParams: { refresh: true } }); @@ -175,7 +175,7 @@ export class AppComponent implements OnInit { private async updateAppMenu() { this.messagingService.send('updateAppMenu', { isAuthenticated: await this.userService.isAuthenticated(), - isLocked: !(await this.cryptoService.hasKey()), + isLocked: await this.lockService.isLocked(), }); } @@ -192,8 +192,10 @@ export class AppComponent implements OnInit { this.folderService.clear(userId), this.collectionService.clear(userId), this.passwordGenerationService.clear(), + this.lockService.clear(), ]); + this.lockService.pinLocked = false; this.searchService.clearIndex(); this.authService.logOut(async () => { this.analytics.eventTrack.next({ action: 'Logged Out' }); diff --git a/src/app/services.module.ts b/src/app/services.module.ts index 6783358f3e4..815474dce64 100644 --- a/src/app/services.module.ts +++ b/src/app/services.module.ts @@ -113,7 +113,7 @@ const authService = new AuthService(cryptoService, apiService, const exportService = new ExportService(folderService, cipherService, apiService); const auditService = new AuditService(cryptoFunctionService, apiService); const notificationsService = new NotificationsService(userService, syncService, appIdService, - apiService, cryptoService, async () => messagingService.send('logout', { expired: true })); + apiService, lockService, async () => messagingService.send('logout', { expired: true })); const environmentService = new EnvironmentService(apiService, storageService, notificationsService); const analytics = new Analytics(window, () => isDev(), platformUtilsService, storageService, appIdService); diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 68bfb597c83..30a78e082bc 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -1188,5 +1188,8 @@ }, "yourVaultIsLockedPinCode": { "message": "Your vault is locked. Verify your PIN code to continue." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" } } diff --git a/src/scss/plugins.scss b/src/scss/plugins.scss index 0af7ee4a2a3..cc2470af14f 100644 --- a/src/scss/plugins.scss +++ b/src/scss/plugins.scss @@ -106,6 +106,21 @@ $fa-font-path: "~font-awesome/fonts"; color: themed('textColor'); } + .swal-content { + font-size: $font-size-base; + + label.checkbox { + margin-top: 10px; + display: flex; + text-align: left; + align-items: top; + + input { + margin: 3px 5px 0 1px; + } + } + } + .swal-text { font-size: $font-size-base;