1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

implement two-factor setup page

This commit is contained in:
Kyle Spearrin
2018-06-26 22:51:58 -04:00
parent 381da132f8
commit e345bbcae0
9 changed files with 142 additions and 5 deletions

2
jslib

Submodule jslib updated: 32a636e5a5...3cc759791e

View File

@@ -18,6 +18,7 @@ import { AccountComponent } from './settings/account.component';
import { DomainRulesComponent } from './settings/domain-rules.component'; import { DomainRulesComponent } from './settings/domain-rules.component';
import { OptionsComponent } from './settings/options.component'; import { OptionsComponent } from './settings/options.component';
import { SettingsComponent } from './settings/settings.component'; import { SettingsComponent } from './settings/settings.component';
import { TwoFactorSetupComponent } from './settings/two-factor-setup.component';
import { ExportComponent } from './tools/export.component'; import { ExportComponent } from './tools/export.component';
import { ImportComponent } from './tools/import.component'; import { ImportComponent } from './tools/import.component';
@@ -55,6 +56,7 @@ const routes: Routes = [
{ path: 'account', component: AccountComponent, canActivate: [AuthGuardService] }, { path: 'account', component: AccountComponent, canActivate: [AuthGuardService] },
{ path: 'options', component: OptionsComponent, canActivate: [AuthGuardService] }, { path: 'options', component: OptionsComponent, canActivate: [AuthGuardService] },
{ path: 'domain-rules', component: DomainRulesComponent, canActivate: [AuthGuardService] }, { path: 'domain-rules', component: DomainRulesComponent, canActivate: [AuthGuardService] },
{ path: 'two-factor', component: TwoFactorSetupComponent, canActivate: [AuthGuardService] },
], ],
}, },
{ {

View File

@@ -42,6 +42,7 @@ import { OptionsComponent } from './settings/options.component';
import { ProfileComponent } from './settings/profile.component'; import { ProfileComponent } from './settings/profile.component';
import { PurgeVaultComponent } from './settings/purge-vault.component'; import { PurgeVaultComponent } from './settings/purge-vault.component';
import { SettingsComponent } from './settings/settings.component'; import { SettingsComponent } from './settings/settings.component';
import { TwoFactorSetupComponent } from './settings/two-factor-setup.component';
import { ExportComponent } from './tools/export.component'; import { ExportComponent } from './tools/export.component';
import { ImportComponent } from './tools/import.component'; import { ImportComponent } from './tools/import.component';
@@ -144,6 +145,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
TrueFalseValueDirective, TrueFalseValueDirective,
TwoFactorComponent, TwoFactorComponent,
TwoFactorOptionsComponent, TwoFactorOptionsComponent,
TwoFactorSetupComponent,
UserLayoutComponent, UserLayoutComponent,
VaultComponent, VaultComponent,
], ],

View File

@@ -16,8 +16,8 @@
<a routerLink="billing" class="list-group-item" routerLinkActive="active"> <a routerLink="billing" class="list-group-item" routerLinkActive="active">
Billing &amp; Licensing Billing &amp; Licensing
</a> </a>
<a routerLink="two-step" class="list-group-item" routerLinkActive="active"> <a routerLink="two-factor" class="list-group-item" routerLinkActive="active">
Two-step Login {{'twoStepLogin' | i18n}}
</a> </a>
<a routerLink="domain-rules" class="list-group-item" routerLinkActive="active"> <a routerLink="domain-rules" class="list-group-item" routerLinkActive="active">
Domain Rules Domain Rules

View File

@@ -0,0 +1,35 @@
<div class="page-header">
<h1>{{'twoStepLogin' | i18n}}</h1>
</div>
<app-callout type="warning">
<p>{{'twoStepLoginRecoveryWarning' | i18n}}</p>
<button type="button" class="btn btn-outline-secondary">{{'viewRecoveryCode' | i18n}}</button>
</app-callout>
<h2 class="mt-5">
{{'providers' | i18n}}
<small *ngIf="loading">
<i class="fa fa-spinner fa-spin text-muted"></i>
</small>
</h2>
<ul class="list-group list-group-2fa">
<li *ngFor="let p of providers" class="list-group-item d-flex align-items-center">
<div class="logo-2fa d-flex justify-content-center">
<img [src]="'../images/two-factor/' + p.type + '.png'" alt="">
</div>
<div class="mx-4">
<h3 class="mb-0">
{{p.name}}
<i class="fa fa-check text-success fa-fw" *ngIf="p.enabled" title="{{'enabled' | i18n}}"></i>
<a href="#" appStopClick class="badge badge-primary" *ngIf="!premium && p.premium">
{{'premium' | i18n}}
</a>
</h3>
{{p.description}}
</div>
<div class="ml-auto">
<button type="button" class="btn btn-outline-secondary btn-sm" [disabled]="!premium && p.premium">
{{'manage' | i18n}}
</button>
</div>
</li>
</ul>

View File

@@ -0,0 +1,69 @@
import {
Component,
OnInit,
} from '@angular/core';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { TokenService } from 'jslib/abstractions/token.service';
import { TwoFactorProviders } from 'jslib/services/auth.service';
import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType';
@Component({
selector: 'app-two-factor-setup',
templateUrl: 'two-factor-setup.component.html',
})
export class TwoFactorSetupComponent implements OnInit {
providers: any[] = [];
premium: boolean;
loading = true;
constructor(private apiService: ApiService, private i18nService: I18nService,
private analytics: Angulartics2, private toasterService: ToasterService,
private tokenService: TokenService) { }
async ngOnInit() {
this.premium = this.tokenService.getPremium();
for (const key in TwoFactorProviders) {
if (!TwoFactorProviders.hasOwnProperty(key)) {
continue;
}
const p = (TwoFactorProviders as any)[key];
if (p.type === TwoFactorProviderType.OrganizationDuo) {
continue;
}
this.providers.push({
type: p.type,
name: p.name,
description: p.description,
enabled: false,
premium: p.premium,
sort: p.sort,
});
}
this.providers.sort((a: any, b: any) => a.sort - b.sort);
await this.load();
}
async load() {
this.loading = true;
const providerList = await this.apiService.getTwoFactorProviders();
providerList.data.forEach((p) => {
this.providers.forEach((p2) => {
if (p.type === p2.type) {
p2.enabled = p.enabled;
}
});
});
this.loading = false;
}
}

View File

@@ -943,7 +943,7 @@
"message": "New Custom Domain" "message": "New Custom Domain"
}, },
"newCustomDomainDesc": { "newCustomDomainDesc": {
"message": "Only \"base\" domains are allowed. Do not enter subdomains. For example, enter \"google.com\" instead of \"www.google.com\". You can also enter \"androidapp://package.name\" to associate an android app with other website domains." "message": "Enter a list of domains separated by commas. Only \"base\" domains are allowed. Do not enter subdomains. For example, enter \"google.com\" instead of \"www.google.com\". You can also enter \"androidapp://package.name\" to associate an android app with other website domains."
}, },
"customDomainX": { "customDomainX": {
"message": "Custom Domain $INDEX$", "message": "Custom Domain $INDEX$",
@@ -956,5 +956,27 @@
}, },
"domainsUpdated": { "domainsUpdated": {
"message": "Domains updated" "message": "Domains updated"
},
"twoStepLogin": {
"message": "Two-step Login"
},
"twoStepLoginRecoveryWarning": {
"message": "Enabling two-step login can permanently lock you out of your Bitwarden account. A recovery code allows you to access your account in the event that you can no longer use your normal two-step login provider (ex. you lose your device). Bitwarden support will not be able to assist you if you lose access to your account. We recommend you write down or print the recovery code and keep it in a safe place."
},
"viewRecoveryCode": {
"message": "View Recovery Code"
},
"providers": {
"message": "Providers",
"description": "Two-step login providers such as YubiKey, Duo, Authenticator apps, Email, etc."
},
"enabled": {
"message": "Enabled"
},
"premium": {
"message": "Premium"
},
"manage": {
"message": "Manage"
} }
} }

View File

@@ -502,3 +502,9 @@ app-avatar {
} }
} }
} }
.list-group-2fa {
.logo-2fa {
min-width: 100px;
}
}

View File

@@ -48,6 +48,7 @@
"check-preblock", "check-preblock",
"check-separator", "check-separator",
"check-type" "check-type"
] ],
"max-classes-per-file": false
} }
} }