[PM-2157] Migrate EnrollMasterPasswordReset to CL (#6277)

This commit is contained in:
Oscar Hinton 2023-09-29 15:54:07 +02:00 committed by GitHub
parent b607d1dcfa
commit ab0807072d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 100 deletions

View File

@ -1,52 +1,19 @@
<div <form [formGroup]="formGroup" [bitSubmit]="submit">
class="modal fade" <bit-dialog>
role="dialog" <span bitDialogTitle>{{ "enrollAccountRecovery" | i18n }}</span>
aria-modal="true" <div bitDialogContent>
aria-labelledby="enrollMasterPasswordResetTitle" <bit-callout type="warning">
> {{ "resetPasswordEnrollmentWarning" | i18n }}
<div class="modal-dialog modal-dialog-scrollable" role="document"> </bit-callout>
<form <app-user-verification formControlName="verification"></app-user-verification>
class="modal-content" </div>
#form <ng-container bitDialogFooter>
(ngSubmit)="submit()" <button bitButton buttonType="primary" bitFormButton type="submit">
[appApiAction]="formPromise" {{ "submit" | i18n }}
ngNativeValidate </button>
> <button type="button" bitButton buttonType="secondary" bitDialogClose>
<div class="modal-header"> {{ "cancel" | i18n }}
<h1 class="modal-title" id="enrollMasterPasswordResetTitle"> </button>
{{ "enrollAccountRecovery" | i18n }} </ng-container>
</h1> </bit-dialog>
<button </form>
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<app-callout type="warning">
{{ "resetPasswordEnrollmentWarning" | i18n }}
</app-callout>
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
</div>
<div class="modal-footer">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</button>
<button
bitButton
buttonType="secondary"
type="button"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span>
{{ "cancel" | i18n }}
</span>
</button>
</div>
</form>
</div>
</div>

View File

@ -1,7 +1,7 @@
import { Component } from "@angular/core"; import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
import { ModalConfig } from "@bitwarden/angular/services/modal.service";
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/abstractions/organization-user/requests"; import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/abstractions/organization-user/requests";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
@ -14,71 +14,83 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { Verification } from "@bitwarden/common/types/verification"; import { Verification } from "@bitwarden/common/types/verification";
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";
interface EnrollMasterPasswordResetData {
organization: Organization;
}
@Component({ @Component({
selector: "app-enroll-master-password-reset", selector: "app-enroll-master-password-reset",
templateUrl: "enroll-master-password-reset.component.html", templateUrl: "enroll-master-password-reset.component.html",
}) })
export class EnrollMasterPasswordReset { export class EnrollMasterPasswordReset {
organization: Organization; protected organization: Organization;
verification: Verification; protected formGroup = new FormGroup({
formPromise: Promise<void>; verification: new FormControl<Verification>(null, Validators.required),
});
constructor( constructor(
private dialogRef: DialogRef,
@Inject(DIALOG_DATA) protected data: EnrollMasterPasswordResetData,
private userVerificationService: UserVerificationService, private userVerificationService: UserVerificationService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService, private i18nService: I18nService,
private cryptoService: CryptoService, private cryptoService: CryptoService,
private syncService: SyncService, private syncService: SyncService,
private logService: LogService, private logService: LogService,
private modalRef: ModalRef,
config: ModalConfig,
private organizationApiService: OrganizationApiServiceAbstraction, private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserService: OrganizationUserService private organizationUserService: OrganizationUserService
) { ) {
this.organization = config.data.organization; this.organization = data.organization;
} }
async submit() { submit = async () => {
let toastStringRef = "withdrawPasswordResetSuccess"; let toastStringRef = "withdrawPasswordResetSuccess";
this.formPromise = this.userVerificationService
.buildRequest(this.verification, OrganizationUserResetPasswordEnrollmentRequest)
.then(async (request) => {
// Set variables
let keyString: string = null;
// Retrieve Public Key
const orgKeys = await this.organizationApiService.getKeys(this.organization.id);
if (orgKeys == null) {
throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
}
const publicKey = Utils.fromB64ToArray(orgKeys.publicKey);
// RSA Encrypt user's encKey.key with organization public key
const userKey = await this.cryptoService.getUserKey();
const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey);
keyString = encryptedKey.encryptedString;
toastStringRef = "enrollPasswordResetSuccess";
// Create request and execute enrollment
request.resetPasswordKey = keyString;
await this.organizationUserService.putOrganizationUserResetPasswordEnrollment(
this.organization.id,
this.organization.userId,
request
);
await this.syncService.fullSync(true);
});
try { try {
await this.formPromise; await this.userVerificationService
.buildRequest(
this.formGroup.value.verification,
OrganizationUserResetPasswordEnrollmentRequest
)
.then(async (request) => {
// Set variables
let keyString: string = null;
// Retrieve Public Key
const orgKeys = await this.organizationApiService.getKeys(this.organization.id);
if (orgKeys == null) {
throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
}
const publicKey = Utils.fromB64ToArray(orgKeys.publicKey);
// RSA Encrypt user's encKey.key with organization public key
const userKey = await this.cryptoService.getUserKey();
const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey);
keyString = encryptedKey.encryptedString;
toastStringRef = "enrollPasswordResetSuccess";
// Create request and execute enrollment
request.resetPasswordKey = keyString;
await this.organizationUserService.putOrganizationUserResetPasswordEnrollment(
this.organization.id,
this.organization.userId,
request
);
await this.syncService.fullSync(true);
});
this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef)); this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef));
this.modalRef.close(); this.dialogRef.close();
} catch (e) { } catch (e) {
this.logService.error(e); this.logService.error(e);
} }
};
static open(dialogService: DialogService, data: EnrollMasterPasswordResetData) {
return dialogService.open(EnrollMasterPasswordReset, { data });
} }
} }

View File

@ -125,12 +125,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
async toggleResetPasswordEnrollment(org: Organization) { async toggleResetPasswordEnrollment(org: Organization) {
if (!this.organization.resetPasswordEnrolled) { if (!this.organization.resetPasswordEnrolled) {
this.modalService.open(EnrollMasterPasswordReset, { EnrollMasterPasswordReset.open(this.dialogService, { organization: org });
allowMultipleModals: true,
data: {
organization: org,
},
});
} else { } else {
// Remove reset password // Remove reset password
const request = new OrganizationUserResetPasswordEnrollmentRequest(); const request = new OrganizationUserResetPasswordEnrollmentRequest();