1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-21 16:18:28 +01:00

Use UserVerificationDialogComponent for account recovery enrollment (#8632)

This commit is contained in:
Addison Beck 2024-04-12 06:38:53 -05:00 committed by GitHub
parent 8d698d9d84
commit bf11b90c43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 60 additions and 94 deletions

View File

@ -1,19 +0,0 @@
<form [formGroup]="formGroup" [bitSubmit]="submit">
<bit-dialog>
<span bitDialogTitle>{{ "enrollAccountRecovery" | i18n }}</span>
<div bitDialogContent>
<bit-callout type="warning">
{{ "resetPasswordEnrollmentWarning" | i18n }}
</bit-callout>
<app-user-verification formControlName="verification"></app-user-verification>
</div>
<ng-container bitDialogFooter>
<button bitButton buttonType="primary" bitFormButton type="submit">
{{ "submit" | i18n }}
</button>
<button type="button" bitButton buttonType="secondary" bitDialogClose>
{{ "cancel" | i18n }}
</button>
</ng-container>
</bit-dialog>
</form>

View File

@ -1,12 +1,7 @@
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog"; import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
import { Component, Inject } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service"; import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/admin-console/abstractions/organization-user/requests"; import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/admin-console/abstractions/organization-user/requests";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { Verification } from "@bitwarden/common/auth/types/verification";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -19,63 +14,58 @@ interface EnrollMasterPasswordResetData {
organization: Organization; organization: Organization;
} }
@Component({
selector: "app-enroll-master-password-reset",
templateUrl: "enroll-master-password-reset.component.html",
})
export class EnrollMasterPasswordReset { export class EnrollMasterPasswordReset {
protected organization: Organization; constructor() {}
protected formGroup = new FormGroup({ static async open(
verification: new FormControl<Verification>(null, Validators.required), dialogService: DialogService,
}); data: EnrollMasterPasswordResetData,
resetPasswordService: OrganizationUserResetPasswordService,
constructor( organizationUserService: OrganizationUserService,
private dialogRef: DialogRef, platformUtilsService: PlatformUtilsService,
@Inject(DIALOG_DATA) protected data: EnrollMasterPasswordResetData, i18nService: I18nService,
private resetPasswordService: OrganizationUserResetPasswordService, syncService: SyncService,
private userVerificationService: UserVerificationService, logService: LogService,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService,
private syncService: SyncService,
private logService: LogService,
private organizationUserService: OrganizationUserService,
) { ) {
this.organization = data.organization; const result = await UserVerificationDialogComponent.open(dialogService, {
} title: "enrollAccountRecovery",
calloutOptions: {
text: "resetPasswordEnrollmentWarning",
type: "warning",
},
});
submit = async () => { // Handle the result of the dialog based on user action and verification success
try { if (result.userAction === "cancel") {
await this.userVerificationService return;
.buildRequest(
this.formGroup.value.verification,
OrganizationUserResetPasswordEnrollmentRequest,
)
.then(async (request) => {
// Create request and execute enrollment
request.resetPasswordKey = await this.resetPasswordService.buildRecoveryKey(
this.organization.id,
);
await this.organizationUserService.putOrganizationUserResetPasswordEnrollment(
this.organization.id,
this.organization.userId,
request,
);
await this.syncService.fullSync(true);
});
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("enrollPasswordResetSuccess"),
);
this.dialogRef.close();
} catch (e) {
this.logService.error(e);
} }
};
static open(dialogService: DialogService, data: EnrollMasterPasswordResetData) { // User confirmed the dialog so check verification success
return dialogService.open(EnrollMasterPasswordReset, { data }); if (!result.verificationSuccess) {
// verification failed
return;
}
// Verification succeeded
try {
// This object is missing most of the properties in the
// `OrganizationUserResetPasswordEnrollmentRequest()`, but those
// properties don't carry over to the server model anyway and are
// never used by this flow.
const request = new OrganizationUserResetPasswordEnrollmentRequest();
request.resetPasswordKey = await resetPasswordService.buildRecoveryKey(data.organization.id);
await organizationUserService.putOrganizationUserResetPasswordEnrollment(
data.organization.id,
data.organization.userId,
request,
);
platformUtilsService.showToast("success", null, i18nService.t("enrollPasswordResetSuccess"));
await syncService.fullSync(true);
} catch (e) {
logService.error(e);
}
} }
} }

View File

@ -1,14 +0,0 @@
import { ScrollingModule } from "@angular/cdk/scrolling";
import { NgModule } from "@angular/core";
import { UserVerificationModule } from "../../../auth/shared/components/user-verification";
import { LooseComponentsModule, SharedModule } from "../../../shared";
import { EnrollMasterPasswordReset } from "./enroll-master-password-reset.component";
@NgModule({
imports: [SharedModule, ScrollingModule, LooseComponentsModule, UserVerificationModule],
declarations: [EnrollMasterPasswordReset],
exports: [EnrollMasterPasswordReset],
})
export class OrganizationUserModule {}

View File

@ -1,6 +1,5 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { OrganizationUserModule } from "./admin-console/organizations/users/organization-user.module";
import { AuthModule } from "./auth"; import { AuthModule } from "./auth";
import { LoginModule } from "./auth/login/login.module"; import { LoginModule } from "./auth/login/login.module";
import { TrialInitiationModule } from "./auth/trial-initiation/trial-initiation.module"; import { TrialInitiationModule } from "./auth/trial-initiation/trial-initiation.module";
@ -16,7 +15,6 @@ import { VaultFilterModule } from "./vault/individual-vault/vault-filter/vault-f
TrialInitiationModule, TrialInitiationModule,
VaultFilterModule, VaultFilterModule,
OrganizationBadgeModule, OrganizationBadgeModule,
OrganizationUserModule,
LoginModule, LoginModule,
AuthModule, AuthModule,
AccessComponent, AccessComponent,

View File

@ -16,6 +16,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { DialogService } from "@bitwarden/components"; import { DialogService } from "@bitwarden/components";
import { OrganizationUserResetPasswordService } from "../../../../admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service";
import { EnrollMasterPasswordReset } from "../../../../admin-console/organizations/users/enroll-master-password-reset.component"; import { EnrollMasterPasswordReset } from "../../../../admin-console/organizations/users/enroll-master-password-reset.component";
import { OptionsInput } from "../shared/components/vault-filter-section.component"; import { OptionsInput } from "../shared/components/vault-filter-section.component";
import { OrganizationFilter } from "../shared/models/vault-filter.type"; import { OrganizationFilter } from "../shared/models/vault-filter.type";
@ -46,6 +47,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
private organizationUserService: OrganizationUserService, private organizationUserService: OrganizationUserService,
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
private dialogService: DialogService, private dialogService: DialogService,
private resetPasswordService: OrganizationUserResetPasswordService,
) {} ) {}
async ngOnInit() { async ngOnInit() {
@ -144,7 +146,16 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
async toggleResetPasswordEnrollment(org: Organization) { async toggleResetPasswordEnrollment(org: Organization) {
if (!this.organization.resetPasswordEnrolled) { if (!this.organization.resetPasswordEnrolled) {
EnrollMasterPasswordReset.open(this.dialogService, { organization: org }); await EnrollMasterPasswordReset.open(
this.dialogService,
{ organization: org },
this.resetPasswordService,
this.organizationUserService,
this.platformUtilsService,
this.i18nService,
this.syncService,
this.logService,
);
} else { } else {
// Remove reset password // Remove reset password
const request = new OrganizationUserResetPasswordEnrollmentRequest(); const request = new OrganizationUserResetPasswordEnrollmentRequest();