diff --git a/src/popup2/accounts/home.component.html b/src/popup2/accounts/home.component.html index 225b6c2429..f4c3eed96c 100644 --- a/src/popup2/accounts/home.component.html +++ b/src/popup2/accounts/home.component.html @@ -2,7 +2,7 @@  {{'settings' | i18n}} - bitwarden + bitwarden

{{'loginOrCreateNewAccount' | i18n}}

diff --git a/src/popup2/app-routing.animations.ts b/src/popup2/app-routing.animations.ts index 038ee1e2b4..877854230a 100644 --- a/src/popup2/app-routing.animations.ts +++ b/src/popup2/app-routing.animations.ts @@ -86,7 +86,11 @@ const outSlideUp = [ ]; export const routerTransition = trigger('routerTransition', [ + transition('void => home', inSlideLeft), + transition('void => tabs', inSlideLeft), + transition('home => login', inSlideLeft), + transition('home => environment', inSlideUp), transition('login => home', outSlideRight), transition('login => hint', inSlideUp), @@ -94,6 +98,8 @@ export const routerTransition = trigger('routerTransition', [ transition('hint => login', outSlideDown), + transition('environment => home', outSlideDown), + transition('2fa => login', outSlideRight), transition('2fa => 2fa-options', inSlideUp), transition('2fa-options => 2fa', outSlideDown), diff --git a/src/popup2/app-routing.module.ts b/src/popup2/app-routing.module.ts index ac46ea312d..e7c624e31e 100644 --- a/src/popup2/app-routing.module.ts +++ b/src/popup2/app-routing.module.ts @@ -6,6 +6,8 @@ import { import { AuthGuardService } from 'jslib/angular/services/auth-guard.service'; +import { LaunchGuardService } from './services/launch-guard.service'; + import { EnvironmentComponent } from './accounts/environment.component'; import { HintComponent } from './accounts/hint.component'; import { HomeComponent } from './accounts/home.component'; @@ -27,28 +29,115 @@ import { GroupingsComponent } from './vault/groupings.component'; import { ViewComponent } from './vault/view.component'; const routes: Routes = [ - { path: '', redirectTo: '/tabs/current', pathMatch: 'full' }, - { path: 'vault', redirectTo: '/tabs/vault', pathMatch: 'full' }, - { path: 'home', component: HomeComponent, data: { state: 'home' } }, - { path: 'login', component: LoginComponent, data: { state: 'login' } }, - { path: 'lock', component: LockComponent, data: { state: 'lock' } }, - { path: '2fa', component: TwoFactorComponent, data: { state: '2fa' } }, - { path: '2fa-options', component: TwoFactorOptionsComponent, data: { state: '2fa-options' } }, - { path: 'register', component: RegisterComponent, data: { state: 'register' } }, - { path: 'hint', component: HintComponent, data: { state: 'hint' } }, - { path: 'environment', component: EnvironmentComponent, data: { state: 'environment' } }, - { path: 'ciphers', component: CiphersComponent, data: { state: 'ciphers' } }, - { path: 'view-cipher', component: ViewComponent, data: { state: 'view-cipher' } }, - { path: 'add-cipher', component: AddEditComponent, data: { state: 'add-cipher' } }, - { path: 'edit-cipher', component: AddEditComponent, data: { state: 'edit-cipher' } }, - { path: 'generator', component: PasswordGeneratorComponent, data: { state: 'generator' } }, - { path: 'generator-history', component: PasswordGeneratorHistoryComponent, data: { state: 'generator-history' } }, - { path: 'export', component: ExportComponent, data: { state: 'export' } }, { - path: 'tabs', component: TabsComponent, + path: '', + redirectTo: 'home', + pathMatch: 'full', + }, + { + path: 'vault', + redirectTo: '/tabs/vault', + pathMatch: 'full', + }, + { + path: 'home', + component: HomeComponent, + canActivate: [LaunchGuardService], + data: { state: 'home' }, + }, + { + path: 'login', + component: LoginComponent, + canActivate: [LaunchGuardService], + data: { state: 'login' }, + }, + { + path: 'lock', + component: LockComponent, + data: { state: 'lock' }, + }, + { + path: '2fa', + component: TwoFactorComponent, + canActivate: [LaunchGuardService], + data: { state: '2fa' }, + }, + { + path: '2fa-options', + component: TwoFactorOptionsComponent, + canActivate: [LaunchGuardService], + data: { state: '2fa-options' }, + }, + { + path: 'register', + component: RegisterComponent, + canActivate: [LaunchGuardService], + data: { state: 'register' }, + }, + { + path: 'hint', + component: HintComponent, + canActivate: [LaunchGuardService], + data: { state: 'hint' }, + }, + { + path: 'environment', + component: EnvironmentComponent, + canActivate: [LaunchGuardService], + data: { state: 'environment' }, + }, + { + path: 'ciphers', + component: CiphersComponent, + canActivate: [AuthGuardService], + data: { state: 'ciphers' }, + }, + { + path: 'view-cipher', + component: ViewComponent, + canActivate: [AuthGuardService], + data: { state: 'view-cipher' }, + }, + { + path: 'add-cipher', + component: AddEditComponent, + canActivate: [AuthGuardService], + data: { state: 'add-cipher' }, + }, + { + path: 'edit-cipher', + component: AddEditComponent, + canActivate: [AuthGuardService], + data: { state: 'edit-cipher' }, + }, + { + path: 'generator', + component: PasswordGeneratorComponent, + canActivate: [AuthGuardService], + data: { state: 'generator' }, + }, + { + path: 'generator-history', + component: PasswordGeneratorHistoryComponent, + canActivate: [AuthGuardService], + data: { state: 'generator-history' }, + }, + { + path: 'export', + component: ExportComponent, + canActivate: [AuthGuardService], + data: { state: 'export' }, + }, + { + path: 'tabs', + component: TabsComponent, data: { state: 'tabs' }, children: [ - { path: '', redirectTo: '/tabs/vault', pathMatch: 'full' }, + { + path: '', + redirectTo: '/tabs/vault', + pathMatch: 'full', + }, { path: 'current', component: CurrentTabComponent, diff --git a/src/popup2/app.component.ts b/src/popup2/app.component.ts index 80ea445db8..65f2cfe378 100644 --- a/src/popup2/app.component.ts +++ b/src/popup2/app.component.ts @@ -6,7 +6,9 @@ import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; import swal from 'sweetalert'; import { + ChangeDetectorRef, Component, + NgZone, OnInit, } from '@angular/core'; import { @@ -59,7 +61,8 @@ export class AppComponent implements OnInit { private toasterService: ToasterService, private storageService: StorageService, private broadcasterService: BroadcasterService, private authService: AuthService, private i18nService: I18nService, private router: Router, - private stateService: StateService, private messagingService: MessagingService) { } + private stateService: StateService, private messagingService: MessagingService, + private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone) { } ngOnInit() { window.onmousemove = () => this.recordActivity(); @@ -71,13 +74,16 @@ export class AppComponent implements OnInit { (window as any).bitwardenPopupMainMessageListener = async (msg: any, sender: any, sendResponse: any) => { if (msg.command === 'doneLoggingOut') { - this.authService.logOut(() => { - this.analytics.eventTrack.next({ action: 'Logged Out' }); - if (msg.expired) { - this.toasterService.popAsync('warning', this.i18nService.t('loggedOut'), - this.i18nService.t('loginExpired')); - } - this.router.navigate(['home']); + this.ngZone.run(async () => { + this.authService.logOut(() => { + this.analytics.eventTrack.next({ action: 'Logged Out' }); + if (msg.expired) { + this.toasterService.popAsync('warning', this.i18nService.t('loggedOut'), + this.i18nService.t('loginExpired')); + } + this.router.navigate(['home']); + }); + this.changeDetectorRef.detectChanges(); }); } else if (msg.command === 'showDialog') { const buttons = [msg.confirmText == null ? this.i18nService.t('ok') : msg.confirmText]; diff --git a/src/popup2/services/launch-guard.service.ts b/src/popup2/services/launch-guard.service.ts new file mode 100644 index 0000000000..b60b99ecda --- /dev/null +++ b/src/popup2/services/launch-guard.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { + CanActivate, + Router, +} from '@angular/router'; + +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +@Injectable() +export class LaunchGuardService implements CanActivate { + constructor(private cryptoService: CryptoService, private userService: UserService, private router: Router) { } + + async canActivate() { + const isAuthed = await this.userService.isAuthenticated(); + if (!isAuthed) { + return true; + } + + const key = await this.cryptoService.getKey(); + if (key == null) { + this.router.navigate(['lock']); + } else { + this.router.navigate(['tabs/current']); + } + + return false; + } +} diff --git a/src/popup2/services/services.module.ts b/src/popup2/services/services.module.ts index 5fab8f4bd3..c27bb61a37 100644 --- a/src/popup2/services/services.module.ts +++ b/src/popup2/services/services.module.ts @@ -5,6 +5,8 @@ import { import { ToasterModule } from 'angular2-toaster'; +import { LaunchGuardService } from './launch-guard.service'; + import { AuthGuardService } from 'jslib/angular/services/auth-guard.service'; import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; import { ValidationService } from 'jslib/angular/services/validation.service'; @@ -87,6 +89,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer providers: [ ValidationService, AuthGuardService, + LaunchGuardService, PopupUtilsService, BroadcasterService, { provide: MessagingService, useValue: messagingService },