From e345bbcae07af14381730b5c559b2b3b196f934a Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 26 Jun 2018 22:51:58 -0400 Subject: [PATCH] implement two-factor setup page --- jslib | 2 +- src/app/app-routing.module.ts | 2 + src/app/app.module.ts | 2 + src/app/settings/settings.component.html | 4 +- .../settings/two-factor-setup.component.html | 35 ++++++++++ .../settings/two-factor-setup.component.ts | 69 +++++++++++++++++++ src/locales/en/messages.json | 24 ++++++- src/scss/styles.scss | 6 ++ tslint.json | 3 +- 9 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 src/app/settings/two-factor-setup.component.html create mode 100644 src/app/settings/two-factor-setup.component.ts diff --git a/jslib b/jslib index 32a636e5a5..3cc759791e 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 32a636e5a5068f705b167f8f16dd15b53493b821 +Subproject commit 3cc759791e12b7692fc2d2b4be1a2b010eee1c8e diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 869c589626..e4bf23c4f2 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -18,6 +18,7 @@ import { AccountComponent } from './settings/account.component'; import { DomainRulesComponent } from './settings/domain-rules.component'; import { OptionsComponent } from './settings/options.component'; import { SettingsComponent } from './settings/settings.component'; +import { TwoFactorSetupComponent } from './settings/two-factor-setup.component'; import { ExportComponent } from './tools/export.component'; import { ImportComponent } from './tools/import.component'; @@ -55,6 +56,7 @@ const routes: Routes = [ { path: 'account', component: AccountComponent, canActivate: [AuthGuardService] }, { path: 'options', component: OptionsComponent, canActivate: [AuthGuardService] }, { path: 'domain-rules', component: DomainRulesComponent, canActivate: [AuthGuardService] }, + { path: 'two-factor', component: TwoFactorSetupComponent, canActivate: [AuthGuardService] }, ], }, { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 123ae8dfc8..9a996ab872 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -42,6 +42,7 @@ import { OptionsComponent } from './settings/options.component'; import { ProfileComponent } from './settings/profile.component'; import { PurgeVaultComponent } from './settings/purge-vault.component'; import { SettingsComponent } from './settings/settings.component'; +import { TwoFactorSetupComponent } from './settings/two-factor-setup.component'; import { ExportComponent } from './tools/export.component'; import { ImportComponent } from './tools/import.component'; @@ -144,6 +145,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe'; TrueFalseValueDirective, TwoFactorComponent, TwoFactorOptionsComponent, + TwoFactorSetupComponent, UserLayoutComponent, VaultComponent, ], diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index 42d383e31f..5388bffbca 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -16,8 +16,8 @@ Billing & Licensing - - Two-step Login + + {{'twoStepLogin' | i18n}} Domain Rules diff --git a/src/app/settings/two-factor-setup.component.html b/src/app/settings/two-factor-setup.component.html new file mode 100644 index 0000000000..c7faabe757 --- /dev/null +++ b/src/app/settings/two-factor-setup.component.html @@ -0,0 +1,35 @@ + + +

{{'twoStepLoginRecoveryWarning' | i18n}}

+ +
+

+ {{'providers' | i18n}} + + + +

+
diff --git a/src/app/settings/two-factor-setup.component.ts b/src/app/settings/two-factor-setup.component.ts new file mode 100644 index 0000000000..0274577f20 --- /dev/null +++ b/src/app/settings/two-factor-setup.component.ts @@ -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; + } +} diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 0d1cfd9642..0ed3a8262b 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -943,7 +943,7 @@ "message": "New Custom Domain" }, "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": { "message": "Custom Domain $INDEX$", @@ -956,5 +956,27 @@ }, "domainsUpdated": { "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" } } diff --git a/src/scss/styles.scss b/src/scss/styles.scss index ff696d8230..2724e9cd9c 100644 --- a/src/scss/styles.scss +++ b/src/scss/styles.scss @@ -502,3 +502,9 @@ app-avatar { } } } + +.list-group-2fa { + .logo-2fa { + min-width: 100px; + } +} diff --git a/tslint.json b/tslint.json index b6d5571669..7e4320f723 100644 --- a/tslint.json +++ b/tslint.json @@ -48,6 +48,7 @@ "check-preblock", "check-separator", "check-type" - ] + ], + "max-classes-per-file": false } }