From 00bb814fbe10f4a584c32d9524e03d30bd6e155f Mon Sep 17 00:00:00 2001 From: rr-bw <102181210+rr-bw@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:48:06 -0800 Subject: [PATCH] [PM-2414] Angular 16 Upgrade - SetPinComponent (#7214) * migrate to DialogService * use static method * add reactive form dependencies * begin migrating to reactive forms * migrate template inputs to use CL * update set-pin.component.ts file to work with reactive forms * migrate desktop template and class file to Dialog and ReactiveForms * update settings page * remove old properties * update settings form upon dialog close * refactor ngOnInit() * remove duplicate validator (already have a validator in class file) --- .../popup/components/set-pin.component.html | 93 ++++++------------ .../popup/components/set-pin.component.ts | 28 +++++- apps/browser/src/popup/app.module.ts | 2 - .../src/popup/settings/settings.component.ts | 7 +- .../src/app/accounts/settings.component.ts | 8 +- apps/desktop/src/app/app.module.ts | 2 - .../auth/components/set-pin.component.html | 94 ++++++------------- .../src/auth/components/set-pin.component.ts | 29 +++++- .../src/auth/components/set-pin.component.ts | 44 +++++---- 9 files changed, 146 insertions(+), 161 deletions(-) diff --git a/apps/browser/src/auth/popup/components/set-pin.component.html b/apps/browser/src/auth/popup/components/set-pin.component.html index 54a3fab10d..aff87b5371 100644 --- a/apps/browser/src/auth/popup/components/set-pin.component.html +++ b/apps/browser/src/auth/popup/components/set-pin.component.html @@ -1,64 +1,29 @@ - +
+ +
+ {{ "unlockWithPin" | i18n }} +
+
+

+ {{ "setYourPinCode" | i18n }} +

+ + {{ "pin" | i18n }} + + + + +
+
+ + +
+
+
diff --git a/apps/browser/src/auth/popup/components/set-pin.component.ts b/apps/browser/src/auth/popup/components/set-pin.component.ts index 41ce33eabd..d79f9eeca8 100644 --- a/apps/browser/src/auth/popup/components/set-pin.component.ts +++ b/apps/browser/src/auth/popup/components/set-pin.component.ts @@ -1,8 +1,34 @@ +import { CommonModule } from "@angular/common"; import { Component } from "@angular/core"; +import { ReactiveFormsModule } from "@angular/forms"; import { SetPinComponent as BaseSetPinComponent } from "@bitwarden/angular/auth/components/set-pin.component"; +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { + AsyncActionsModule, + ButtonModule, + DialogModule, + DialogService, + FormFieldModule, + IconButtonModule, +} from "@bitwarden/components"; @Component({ + standalone: true, templateUrl: "set-pin.component.html", + imports: [ + DialogModule, + CommonModule, + JslibModule, + ButtonModule, + IconButtonModule, + ReactiveFormsModule, + AsyncActionsModule, + FormFieldModule, + ], }) -export class SetPinComponent extends BaseSetPinComponent {} +export class SetPinComponent extends BaseSetPinComponent { + static open(dialogService: DialogService) { + return dialogService.open(SetPinComponent); + } +} diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index ae8fd394df..c444fec7f9 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -20,7 +20,6 @@ import { AvatarModule } from "@bitwarden/components"; import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component"; import { AccountComponent } from "../auth/popup/account-switching/account.component"; import { CurrentAccountComponent } from "../auth/popup/account-switching/current-account.component"; -import { SetPinComponent } from "../auth/popup/components/set-pin.component"; import { EnvironmentComponent } from "../auth/popup/environment.component"; import { HintComponent } from "../auth/popup/hint.component"; import { HomeComponent } from "../auth/popup/home.component"; @@ -148,7 +147,6 @@ import "../platform/popup/locales"; SendListComponent, SendTypeComponent, SetPasswordComponent, - SetPinComponent, SettingsComponent, ShareComponent, SsoComponent, diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts index aefd21624b..e679c025b9 100644 --- a/apps/browser/src/popup/settings/settings.component.ts +++ b/apps/browser/src/popup/settings/settings.component.ts @@ -316,14 +316,15 @@ export class SettingsComponent implements OnInit { async updatePin(value: boolean) { if (value) { - const ref = this.modalService.open(SetPinComponent, { allowMultipleModals: true }); + const dialogRef = SetPinComponent.open(this.dialogService); - if (ref == null) { + if (dialogRef == null) { this.form.controls.pin.setValue(false, { emitEvent: false }); return; } - this.form.controls.pin.setValue(await ref.onClosedPromise(), { emitEvent: false }); + const userHasPinSet = await firstValueFrom(dialogRef.closed); + this.form.controls.pin.setValue(userHasPinSet, { emitEvent: false }); } else { await this.vaultTimeoutSettingsService.clear(); } diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index 55760c95d6..4155d34d71 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -409,16 +409,17 @@ export class SettingsComponent implements OnInit { async updatePin(value: boolean) { if (value) { - const ref = this.modalService.open(SetPinComponent, { allowMultipleModals: true }); + const dialogRef = SetPinComponent.open(this.dialogService); - if (ref == null) { + if (dialogRef == null) { this.form.controls.pin.setValue(false, { emitEvent: false }); return; } - this.userHasPinSet = await ref.onClosedPromise(); + this.userHasPinSet = await firstValueFrom(dialogRef.closed); this.form.controls.pin.setValue(this.userHasPinSet, { emitEvent: false }); } + if (!value) { // If user turned off PIN without having a MP and has biometric + require MP/PIN on restart enabled if (this.form.value.requirePasswordOnStart && !this.userHasMasterPassword) { @@ -429,6 +430,7 @@ export class SettingsComponent implements OnInit { await this.vaultTimeoutSettingsService.clear(); } + this.messagingService.send("redrawMenu"); } diff --git a/apps/desktop/src/app/app.module.ts b/apps/desktop/src/app/app.module.ts index d57256aac8..bb25500eb4 100644 --- a/apps/desktop/src/app/app.module.ts +++ b/apps/desktop/src/app/app.module.ts @@ -10,7 +10,6 @@ import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe" import { DialogModule } from "@bitwarden/components"; import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.component"; -import { SetPinComponent } from "../auth/components/set-pin.component"; import { DeleteAccountComponent } from "../auth/delete-account.component"; import { EnvironmentComponent } from "../auth/environment.component"; import { HintComponent } from "../auth/hint.component"; @@ -92,7 +91,6 @@ import { SendComponent } from "./tools/send/send.component"; SendAddEditComponent, SendComponent, SetPasswordComponent, - SetPinComponent, SettingsComponent, ShareComponent, SsoComponent, diff --git a/apps/desktop/src/auth/components/set-pin.component.html b/apps/desktop/src/auth/components/set-pin.component.html index 4c23ad3dde..aff87b5371 100644 --- a/apps/desktop/src/auth/components/set-pin.component.html +++ b/apps/desktop/src/auth/components/set-pin.component.html @@ -1,65 +1,29 @@ - +
+ +
+ {{ "unlockWithPin" | i18n }} +
+
+

+ {{ "setYourPinCode" | i18n }} +

+ + {{ "pin" | i18n }} + + + + +
+
+ + +
+
+
diff --git a/apps/desktop/src/auth/components/set-pin.component.ts b/apps/desktop/src/auth/components/set-pin.component.ts index 41ce33eabd..a5221442a3 100644 --- a/apps/desktop/src/auth/components/set-pin.component.ts +++ b/apps/desktop/src/auth/components/set-pin.component.ts @@ -1,8 +1,33 @@ +import { CommonModule } from "@angular/common"; import { Component } from "@angular/core"; +import { ReactiveFormsModule } from "@angular/forms"; import { SetPinComponent as BaseSetPinComponent } from "@bitwarden/angular/auth/components/set-pin.component"; - +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { + AsyncActionsModule, + ButtonModule, + DialogModule, + DialogService, + FormFieldModule, + IconButtonModule, +} from "@bitwarden/components"; @Component({ + standalone: true, templateUrl: "set-pin.component.html", + imports: [ + DialogModule, + CommonModule, + JslibModule, + ButtonModule, + IconButtonModule, + ReactiveFormsModule, + AsyncActionsModule, + FormFieldModule, + ], }) -export class SetPinComponent extends BaseSetPinComponent {} +export class SetPinComponent extends BaseSetPinComponent { + static open(dialogService: DialogService) { + return dialogService.open(SetPinComponent); + } +} diff --git a/libs/angular/src/auth/components/set-pin.component.ts b/libs/angular/src/auth/components/set-pin.component.ts index 6b5bd40fd3..ade23f4fef 100644 --- a/libs/angular/src/auth/components/set-pin.component.ts +++ b/libs/angular/src/auth/components/set-pin.component.ts @@ -1,57 +1,63 @@ +import { DialogRef } from "@angular/cdk/dialog"; import { Directive, OnInit } from "@angular/core"; +import { FormBuilder, Validators } from "@angular/forms"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { ModalRef } from "../../components/modal/modal.ref"; - @Directive() export class SetPinComponent implements OnInit { - pin = ""; - showPin = false; - masterPassOnRestart = true; showMasterPassOnRestart = true; + setPinForm = this.formBuilder.group({ + pin: ["", [Validators.required]], + masterPassOnRestart: true, + }); + constructor( - private modalRef: ModalRef, + private dialogRef: DialogRef, private cryptoService: CryptoService, private userVerificationService: UserVerificationService, private stateService: StateService, + private formBuilder: FormBuilder, ) {} async ngOnInit() { - this.showMasterPassOnRestart = this.masterPassOnRestart = - await this.userVerificationService.hasMasterPassword(); + const hasMasterPassword = await this.userVerificationService.hasMasterPassword(); + + this.setPinForm.controls.masterPassOnRestart.setValue(hasMasterPassword); + this.showMasterPassOnRestart = hasMasterPassword; } - toggleVisibility() { - this.showPin = !this.showPin; - } + submit = async () => { + const pin = this.setPinForm.get("pin").value; + const masterPassOnRestart = this.setPinForm.get("masterPassOnRestart").value; - async submit() { - if (Utils.isNullOrWhitespace(this.pin)) { - this.modalRef.close(false); + if (Utils.isNullOrWhitespace(pin)) { + this.dialogRef.close(false); return; } const pinKey = await this.cryptoService.makePinKey( - this.pin, + pin, await this.stateService.getEmail(), await this.stateService.getKdfType(), await this.stateService.getKdfConfig(), ); const userKey = await this.cryptoService.getUserKey(); const pinProtectedKey = await this.cryptoService.encrypt(userKey.key, pinKey); - const encPin = await this.cryptoService.encrypt(this.pin, userKey); + const encPin = await this.cryptoService.encrypt(pin, userKey); + await this.stateService.setProtectedPin(encPin.encryptedString); - if (this.masterPassOnRestart) { + + if (masterPassOnRestart) { await this.stateService.setPinKeyEncryptedUserKeyEphemeral(pinProtectedKey); } else { await this.stateService.setPinKeyEncryptedUserKey(pinProtectedKey); } - this.modalRef.close(true); - } + this.dialogRef.close(true); + }; }