From 8a36536d40b406d3a06eac6afb4cf6f586c41536 Mon Sep 17 00:00:00 2001
From: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Date: Thu, 17 Mar 2022 08:55:00 -0500
Subject: [PATCH] [End User Vault Refresh] Security sub-page (#1538)
* [End User Vault Refresh] Security section
* Updated routing module
* Update routing for change-password
* Updated buttons of all modified classes // imported button module
* Converted modified class to use bit-callout
* removed comments
* Update small button to current cl button
---
src/app/oss-routing.module.ts | 11 ++--
src/app/oss.module.ts | 8 ++-
src/app/settings/account.component.html | 30 +--------
src/app/settings/account.component.ts | 41 +------------
src/app/settings/change-kdf.component.html | 7 ++-
.../settings/change-password.component.html | 8 ++-
src/app/settings/change-password.component.ts | 12 +++-
src/app/settings/security-keys.component.html | 18 ++++++
src/app/settings/security-keys.component.ts | 61 +++++++++++++++++++
src/app/settings/security.component.html | 22 +++++++
src/app/settings/security.component.ts | 17 ++++++
src/app/settings/security.module.ts | 39 ++++++++++++
src/app/settings/settings.component.html | 6 +-
.../settings/two-factor-setup.component.html | 16 ++---
src/locales/en/messages.json | 9 +++
src/scss/base.scss | 8 ++-
src/scss/navigation.scss | 33 ++++++----
17 files changed, 244 insertions(+), 102 deletions(-)
create mode 100644 src/app/settings/security-keys.component.html
create mode 100644 src/app/settings/security-keys.component.ts
create mode 100644 src/app/settings/security.component.html
create mode 100644 src/app/settings/security.component.ts
create mode 100644 src/app/settings/security.module.ts
diff --git a/src/app/oss-routing.module.ts b/src/app/oss-routing.module.ts
index 1f122840..911b93b2 100644
--- a/src/app/oss-routing.module.ts
+++ b/src/app/oss-routing.module.ts
@@ -58,9 +58,9 @@ import { EmergencyAccessComponent } from "./settings/emergency-access.component"
import { OrganizationsComponent } from "./settings/organizations.component";
import { PreferencesComponent } from "./settings/preferences.component";
import { PremiumComponent } from "./settings/premium.component";
+import { SecurityComponent } from "./settings/security.component";
import { SettingsComponent } from "./settings/settings.component";
import { SponsoredFamiliesComponent } from "./settings/sponsored-families.component";
-import { TwoFactorSetupComponent } from "./settings/two-factor-setup.component";
import { UserBillingComponent } from "./settings/user-billing.component";
import { UserSubscriptionComponent } from "./settings/user-subscription.component";
import { BreachReportComponent } from "./tools/breach-report.component";
@@ -183,16 +183,15 @@ const routes: Routes = [
component: PreferencesComponent,
data: { titleId: "preferences" },
},
+ {
+ path: "security",
+ loadChildren: async () => (await import("./settings/security.module")).SecurityModule,
+ },
{
path: "domain-rules",
component: DomainRulesComponent,
data: { titleId: "domainRules" },
},
- {
- path: "two-factor",
- component: TwoFactorSetupComponent,
- data: { titleId: "twoStepLogin" },
- },
{ path: "premium", component: PremiumComponent, data: { titleId: "goPremium" } },
{ path: "billing", component: UserBillingComponent, data: { titleId: "billing" } },
{
diff --git a/src/app/oss.module.ts b/src/app/oss.module.ts
index daa8d37f..9f17cb8c 100644
--- a/src/app/oss.module.ts
+++ b/src/app/oss.module.ts
@@ -53,7 +53,7 @@ import localeZhTw from "@angular/common/locales/zh-Hant";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { RouterModule } from "@angular/router";
-import { BadgeModule } from "@bitwarden/components";
+import { BadgeModule, ButtonModule, CalloutModule } from "@bitwarden/components";
import { InfiniteScrollModule } from "ngx-infinite-scroll";
import { ToastrModule } from "ngx-toastr";
@@ -191,6 +191,8 @@ import { PreferencesComponent } from "./settings/preferences.component";
import { PremiumComponent } from "./settings/premium.component";
import { ProfileComponent } from "./settings/profile.component";
import { PurgeVaultComponent } from "./settings/purge-vault.component";
+import { SecurityKeysComponent } from "./settings/security-keys.component";
+import { SecurityComponent } from "./settings/security.component";
import { SettingsComponent } from "./settings/settings.component";
import { SponsoredFamiliesComponent } from "./settings/sponsored-families.component";
import { SponsoringOrgRowComponent } from "./settings/sponsoring-org-row.component";
@@ -296,6 +298,8 @@ registerLocaleData(localeZhTw, "zh-TW");
ReactiveFormsModule,
RouterModule,
BadgeModule,
+ ButtonModule,
+ CalloutModule,
],
declarations: [
A11yInvalidDirective,
@@ -431,6 +435,8 @@ registerLocaleData(localeZhTw, "zh-TW");
ReusedPasswordsReportComponent,
SearchCiphersPipe,
SearchPipe,
+ SecurityComponent,
+ SecurityKeysComponent,
SelectCopyDirective,
SendAddEditComponent,
SendComponent,
diff --git a/src/app/settings/account.component.html b/src/app/settings/account.component.html
index af894442..18814983 100644
--- a/src/app/settings/account.component.html
+++ b/src/app/settings/account.component.html
@@ -8,43 +8,19 @@
-
-
-
-
-
-
-
-
-
-
- {{ "userApiKeyDesc" | i18n }}
-
-
-
{{ "dangerZoneDesc" | i18n }}
-
diff --git a/src/app/settings/account.component.ts b/src/app/settings/account.component.ts
index 557e4c82..aa13eb45 100644
--- a/src/app/settings/account.component.ts
+++ b/src/app/settings/account.component.ts
@@ -5,7 +5,6 @@ import { ApiService } from "jslib-common/abstractions/api.service";
import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
import { StateService } from "jslib-common/abstractions/state.service";
-import { ApiKeyComponent } from "./api-key.component";
import { DeauthorizeSessionsComponent } from "./deauthorize-sessions.component";
import { DeleteAccountComponent } from "./delete-account.component";
import { PurgeVaultComponent } from "./purge-vault.component";
@@ -21,13 +20,7 @@ export class AccountComponent {
purgeModalRef: ViewContainerRef;
@ViewChild("deleteAccountTemplate", { read: ViewContainerRef, static: true })
deleteModalRef: ViewContainerRef;
- @ViewChild("viewUserApiKeyTemplate", { read: ViewContainerRef, static: true })
- viewUserApiKeyModalRef: ViewContainerRef;
- @ViewChild("rotateUserApiKeyTemplate", { read: ViewContainerRef, static: true })
- rotateUserApiKeyModalRef: ViewContainerRef;
- showChangePassword = true;
- showChangeKdf = true;
showChangeEmail = true;
constructor(
@@ -38,10 +31,7 @@ export class AccountComponent {
) {}
async ngOnInit() {
- this.showChangeEmail =
- this.showChangeKdf =
- this.showChangePassword =
- !(await this.keyConnectorService.getUsesKeyConnector());
+ this.showChangeEmail = !(await this.keyConnectorService.getUsesKeyConnector());
}
async deauthorizeSessions() {
@@ -55,33 +45,4 @@ export class AccountComponent {
async deleteAccount() {
await this.modalService.openViewRef(DeleteAccountComponent, this.deleteModalRef);
}
-
- async viewUserApiKey() {
- const entityId = await this.stateService.getUserId();
- await this.modalService.openViewRef(ApiKeyComponent, this.viewUserApiKeyModalRef, (comp) => {
- comp.keyType = "user";
- comp.entityId = entityId;
- comp.postKey = this.apiService.postUserApiKey.bind(this.apiService);
- comp.scope = "api";
- comp.grantType = "client_credentials";
- comp.apiKeyTitle = "apiKey";
- comp.apiKeyWarning = "userApiKeyWarning";
- comp.apiKeyDescription = "userApiKeyDesc";
- });
- }
-
- async rotateUserApiKey() {
- const entityId = await this.stateService.getUserId();
- await this.modalService.openViewRef(ApiKeyComponent, this.rotateUserApiKeyModalRef, (comp) => {
- comp.keyType = "user";
- comp.isRotation = true;
- comp.entityId = entityId;
- comp.postKey = this.apiService.postUserRotateApiKey.bind(this.apiService);
- comp.scope = "api";
- comp.grantType = "client_credentials";
- comp.apiKeyTitle = "apiKey";
- comp.apiKeyWarning = "userApiKeyWarning";
- comp.apiKeyDescription = "apiKeyRotateDesc";
- });
- }
}
diff --git a/src/app/settings/change-kdf.component.html b/src/app/settings/change-kdf.component.html
index ebd616f1..b87e6c12 100644
--- a/src/app/settings/change-kdf.component.html
+++ b/src/app/settings/change-kdf.component.html
@@ -1,4 +1,7 @@
-
{{ "loggedOutWarning" | i18n }}
+
+
{{ "loggedOutWarning" | i18n }}
-
+
{{ "changeKdf" | i18n }}
diff --git a/src/app/settings/change-password.component.html b/src/app/settings/change-password.component.html
index 2b3b6f53..f8a4dd4c 100644
--- a/src/app/settings/change-password.component.html
+++ b/src/app/settings/change-password.component.html
@@ -1,4 +1,8 @@
-{{ "loggedOutWarning" | i18n }}
+
+
+{{ "loggedOutWarning" | i18n }}
-
+
{{ "changeMasterPassword" | i18n }}
diff --git a/src/app/settings/change-password.component.ts b/src/app/settings/change-password.component.ts
index d2311b1f..577c66b0 100644
--- a/src/app/settings/change-password.component.ts
+++ b/src/app/settings/change-password.component.ts
@@ -1,4 +1,5 @@
import { Component } from "@angular/core";
+import { Router } from "@angular/router";
import { ChangePasswordComponent as BaseChangePasswordComponent } from "jslib-angular/components/change-password.component";
import { ApiService } from "jslib-common/abstractions/api.service";
@@ -6,6 +7,7 @@ import { CipherService } from "jslib-common/abstractions/cipher.service";
import { CryptoService } from "jslib-common/abstractions/crypto.service";
import { FolderService } from "jslib-common/abstractions/folder.service";
import { I18nService } from "jslib-common/abstractions/i18n.service";
+import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { OrganizationService } from "jslib-common/abstractions/organization.service";
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
@@ -47,7 +49,9 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
private syncService: SyncService,
private apiService: ApiService,
private sendService: SendService,
- private organizationService: OrganizationService
+ private organizationService: OrganizationService,
+ private keyConnectorService: KeyConnectorService,
+ private router: Router
) {
super(
i18nService,
@@ -60,6 +64,12 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
);
}
+ async ngOnInit() {
+ if (await this.keyConnectorService.getUsesKeyConnector()) {
+ this.router.navigate(["/settings/security/two-factor"]);
+ }
+ }
+
async rotateEncKeyClicked() {
if (this.rotateEncKey) {
const ciphers = await this.cipherService.getAllDecrypted();
diff --git a/src/app/settings/security-keys.component.html b/src/app/settings/security-keys.component.html
new file mode 100644
index 00000000..9c9b8df5
--- /dev/null
+++ b/src/app/settings/security-keys.component.html
@@ -0,0 +1,18 @@
+
+
+
{{ "apiKey" | i18n }}
+
+
+ {{ "userApiKeyDesc" | i18n }}
+
+
+ {{ "viewApiKey" | i18n }}
+
+
+ {{ "rotateApiKey" | i18n }}
+
+
+
diff --git a/src/app/settings/security-keys.component.ts b/src/app/settings/security-keys.component.ts
new file mode 100644
index 00000000..650f5c48
--- /dev/null
+++ b/src/app/settings/security-keys.component.ts
@@ -0,0 +1,61 @@
+import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
+
+import { ModalService } from "jslib-angular/services/modal.service";
+import { ApiService } from "jslib-common/abstractions/api.service";
+import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
+import { StateService } from "jslib-common/abstractions/state.service";
+
+import { ApiKeyComponent } from "./api-key.component";
+
+@Component({
+ selector: "app-security-keys",
+ templateUrl: "security-keys.component.html",
+})
+export class SecurityKeysComponent implements OnInit {
+ @ViewChild("viewUserApiKeyTemplate", { read: ViewContainerRef, static: true })
+ viewUserApiKeyModalRef: ViewContainerRef;
+ @ViewChild("rotateUserApiKeyTemplate", { read: ViewContainerRef, static: true })
+ rotateUserApiKeyModalRef: ViewContainerRef;
+
+ showChangeKdf = true;
+
+ constructor(
+ private keyConnectorService: KeyConnectorService,
+ private stateService: StateService,
+ private modalService: ModalService,
+ private apiService: ApiService
+ ) {}
+
+ async ngOnInit() {
+ this.showChangeKdf = !(await this.keyConnectorService.getUsesKeyConnector());
+ }
+
+ async viewUserApiKey() {
+ const entityId = await this.stateService.getUserId();
+ await this.modalService.openViewRef(ApiKeyComponent, this.viewUserApiKeyModalRef, (comp) => {
+ comp.keyType = "user";
+ comp.entityId = entityId;
+ comp.postKey = this.apiService.postUserApiKey.bind(this.apiService);
+ comp.scope = "api";
+ comp.grantType = "client_credentials";
+ comp.apiKeyTitle = "apiKey";
+ comp.apiKeyWarning = "userApiKeyWarning";
+ comp.apiKeyDescription = "userApiKeyDesc";
+ });
+ }
+
+ async rotateUserApiKey() {
+ const entityId = await this.stateService.getUserId();
+ await this.modalService.openViewRef(ApiKeyComponent, this.rotateUserApiKeyModalRef, (comp) => {
+ comp.keyType = "user";
+ comp.isRotation = true;
+ comp.entityId = entityId;
+ comp.postKey = this.apiService.postUserRotateApiKey.bind(this.apiService);
+ comp.scope = "api";
+ comp.grantType = "client_credentials";
+ comp.apiKeyTitle = "apiKey";
+ comp.apiKeyWarning = "userApiKeyWarning";
+ comp.apiKeyDescription = "apiKeyRotateDesc";
+ });
+ }
+}
diff --git a/src/app/settings/security.component.html b/src/app/settings/security.component.html
new file mode 100644
index 00000000..6e6b76fb
--- /dev/null
+++ b/src/app/settings/security.component.html
@@ -0,0 +1,22 @@
+
+
diff --git a/src/app/settings/security.component.ts b/src/app/settings/security.component.ts
new file mode 100644
index 00000000..7312392e
--- /dev/null
+++ b/src/app/settings/security.component.ts
@@ -0,0 +1,17 @@
+import { Component } from "@angular/core";
+
+import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
+
+@Component({
+ selector: "app-security",
+ templateUrl: "security.component.html",
+})
+export class SecurityComponent {
+ showChangePassword = true;
+
+ constructor(private keyConnectorService: KeyConnectorService) {}
+
+ async ngOnInit() {
+ this.showChangePassword = !(await this.keyConnectorService.getUsesKeyConnector());
+ }
+}
diff --git a/src/app/settings/security.module.ts b/src/app/settings/security.module.ts
new file mode 100644
index 00000000..16b79a5b
--- /dev/null
+++ b/src/app/settings/security.module.ts
@@ -0,0 +1,39 @@
+import { NgModule } from "@angular/core";
+import { RouterModule, Routes } from "@angular/router";
+
+import { ChangePasswordComponent } from "./change-password.component";
+import { SecurityKeysComponent } from "./security-keys.component";
+import { SecurityComponent } from "./security.component";
+import { TwoFactorSetupComponent } from "./two-factor-setup.component";
+
+const routes: Routes = [
+ {
+ path: "",
+ component: SecurityComponent,
+ data: { titleId: "security" },
+ children: [
+ { path: "", pathMatch: "full", redirectTo: "change-password" },
+ {
+ path: "change-password",
+ component: ChangePasswordComponent,
+ data: { titleId: "masterPassword" },
+ },
+ {
+ path: "two-factor",
+ component: TwoFactorSetupComponent,
+ data: { titleId: "twoStepLogin" },
+ },
+ {
+ path: "security-keys",
+ component: SecurityKeysComponent,
+ data: { titleId: "keys" },
+ },
+ ],
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class SecurityModule {}
diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html
index a0e5a15f..9c3c36cc 100644
--- a/src/app/settings/settings.component.html
+++ b/src/app/settings/settings.component.html
@@ -7,6 +7,9 @@
{{ "myAccount" | i18n }}
+
+ {{ "security" | i18n }}
+
{{ "preferences" | i18n }}
@@ -37,9 +40,6 @@
>
{{ "billing" | i18n }}
-
- {{ "twoStepLogin" | i18n }}
-
{{ "domainRules" | i18n }}
diff --git a/src/app/settings/two-factor-setup.component.html b/src/app/settings/two-factor-setup.component.html
index d3e4c453..549636f8 100644
--- a/src/app/settings/two-factor-setup.component.html
+++ b/src/app/settings/two-factor-setup.component.html
@@ -1,14 +1,14 @@
-