lock/unlock

This commit is contained in:
Kyle Spearrin 2018-02-09 22:47:53 -05:00
parent 9cb2d2087c
commit a77b16b766
9 changed files with 113 additions and 15 deletions

View File

@ -0,0 +1,23 @@
<form id="lock-page" (ngSubmit)="submit()">
<div class="content">
<p><i class="fa fa-lock fa-4x"></i></p>
<p>{{'yourVaultIsLocked' | i18n}}</p>
<div class="box last">
<div class="box-content">
<div class="box-content-row" appBoxRow>
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<input id="masterPassword" type="password" name="MasterPassword" [(ngModel)]="masterPassword"
required appAutofocus>
</div>
</div>
</div>
<div class="buttons">
<button type="submit" class="btn primary block" appBlurClick>
<i class="fa fa-unlock-alt"></i> {{'unlock' | i18n}}
</button>
<button type="button" class="btn block" appBlurClick (click)="logOut()">
{{'logOut' | i18n}}
</button>
</div>
</div>
</form>

View File

@ -0,0 +1,56 @@
import * as template from './lock.component.html';
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
@Component({
selector: 'app-lock',
template: template,
})
export class LockComponent {
masterPassword: string = '';
constructor(private router: Router, private analytics: Angulartics2,
private toasterService: ToasterService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private messagingService: MessagingService,
private userService: UserService, private cryptoService: CryptoService) { }
async submit() {
if (this.masterPassword == null || this.masterPassword === '') {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('masterPassRequired'));
return;
}
const email = await this.userService.getEmail();
const key = this.cryptoService.makeKey(this.masterPassword, email);
const keyHash = await this.cryptoService.hashPassword(this.masterPassword, key);
const storedKeyHash = await this.cryptoService.getKeyHash();
if (storedKeyHash != null && keyHash != null && storedKeyHash === keyHash) {
await this.cryptoService.setKey(key);
this.messagingService.send('unlocked');
this.router.navigate(['vault']);
} else {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('invalidMasterPassword'));
}
}
async logOut() {
const confirmed = await this.platformUtilsService.showDialog(this.i18nService.t('logOutConfirmation'),
this.i18nService.t('logOut'), this.i18nService.t('logOut'), this.i18nService.t('cancel'));
if (confirmed) {
this.messagingService.send('logout');
}
}
}

View File

@ -7,6 +7,7 @@ import {
import { AuthGuardService } from './services/auth-guard.service';
import { HintComponent } from './accounts/hint.component';
import { LockComponent } from './accounts/lock.component';
import { LoginComponent } from './accounts/login.component';
import { RegisterComponent } from './accounts/register.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
@ -14,6 +15,7 @@ import { VaultComponent } from './vault/vault.component';
const routes: Routes = [
{ path: '', redirectTo: '/vault', pathMatch: 'full' },
{ path: 'lock', component: LockComponent },
{ path: 'login', component: LoginComponent },
{ path: '2fa', component: TwoFactorComponent },
{ path: 'register', component: RegisterComponent },

View File

@ -21,6 +21,7 @@ import { CipherService } from 'jslib/abstractions/cipher.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { FolderService } from 'jslib/abstractions/folder.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LockService } from 'jslib/abstractions/lock.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SettingsService } from 'jslib/abstractions/settings.service';
@ -50,7 +51,8 @@ export class AppComponent implements OnInit {
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
private authService: AuthService, private router: Router, private analytics: Angulartics2,
private toasterService: ToasterService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone) { }
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone,
private lockService: LockService) { }
ngOnInit() {
this.broadcasterService.subscribe((message: any) => {
@ -59,9 +61,13 @@ export class AppComponent implements OnInit {
case 'loggedIn':
break;
case 'logout':
this.logOut(message.expired);
this.logOut(!!message.expired);
break;
case 'lockVault':
await this.lockService.lock();
break;
case 'locked':
this.router.navigate(['lock']);
break;
case 'unlocked':
break;

View File

@ -17,6 +17,7 @@ import { ModalComponent } from './modal.component';
import { EnvironmentComponent } from './accounts/environment.component';
import { HintComponent } from './accounts/hint.component';
import { LockComponent } from './accounts/lock.component';
import { LoginComponent } from './accounts/login.component';
import { RegisterComponent } from './accounts/register.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
@ -72,6 +73,7 @@ import { ViewComponent } from './vault/view.component';
HintComponent,
I18nPipe,
IconComponent,
LockComponent,
LoginComponent,
ModalComponent,
PasswordGeneratorComponent,

View File

@ -87,8 +87,7 @@ const folderService = new FolderService(cryptoService, userService,
() => i18nService.t('noneFolder'), apiService, storageService, i18nService);
const collectionService = new CollectionService(cryptoService, userService, storageService, i18nService);
const lockService = new LockService(cipherService, folderService, collectionService,
cryptoService, platformUtilsService, storageService,
() => { /* set icon */ }, () => { /* refresh badge and menu */ });
cryptoService, platformUtilsService, storageService, messagingService);
const syncService = new SyncService(userService, apiService, settingsService,
folderService, cipherService, cryptoService, collectionService,
storageService, messagingService, (expired: boolean) => { /* log out */ });
@ -141,6 +140,7 @@ function initFactory(i18n: I18nService, platformUtils: DesktopPlatformUtilsServi
{ provide: MessagingServiceAbstraction, useValue: messagingService },
{ provide: BroadcasterService, useValue: broadcasterService },
{ provide: SettingsServiceAbstraction, useValue: settingsService },
{ provide: LockServiceAbstraction, useValue: lockService },
{
provide: APP_INITIALIZER,
useFactory: initFactory,

View File

@ -625,8 +625,8 @@
"loading": {
"message": "Loading..."
},
"lock": {
"message": "Lock"
"lockVault": {
"message": "Lock Vault"
},
"passwordGenerator": {
"message": "Password Generator"
@ -678,5 +678,14 @@
},
"syncingFailed": {
"message": "Syncing failed"
},
"yourVaultIsLocked": {
"message": "Your vault is locked. Verify your master password to continue."
},
"unlock": {
"message": "Unlock"
},
"invalidMasterPassword": {
"message": "Invalid master password"
}
}

View File

@ -83,9 +83,9 @@ export class MenuMain {
}
},
{
label: this.i18nService.t('lock'),
label: this.i18nService.t('lockVault'),
click() {
self.send('lockApp');
self.send('lockVault');
},
accelerator: 'CmdOrCtrl+L'
},

View File

@ -1,6 +1,6 @@
@import "variables.scss";
#login-page {
#login-page, #lock-page {
display: flex;
justify-content: center;
align-items: center;
@ -37,15 +37,15 @@
display: block;
border-radius: $border-radius;
}
p {
text-align: center
}
}
#login-page, #register-page, #hint-page, #two-factor-page {
#login-page, #register-page, #hint-page, #two-factor-page, #lock-page {
.content {
max-width: 300px;
width: 300px;
p {
text-align: center
}
p.lead, h1 {
font-size: $font-size-large;