mirror of https://github.com/bitwarden/web.git
Browse Source
* Make enrollment a modal component * Add verification to org user module * Move enroll to component * Update warning for modal * update jslib * Use ModalRef to close the modal * Use bit-buttonpull/1723/head
6 changed files with 183 additions and 70 deletions
@ -0,0 +1,59 @@ |
|||||||
|
<div |
||||||
|
class="modal fade" |
||||||
|
role="dialog" |
||||||
|
aria-modal="true" |
||||||
|
aria-labelledby="enrollMasterPasswordResetTitle" |
||||||
|
> |
||||||
|
<div class="modal-dialog modal-dialog-scrollable" role="document"> |
||||||
|
<form |
||||||
|
class="modal-content" |
||||||
|
#form |
||||||
|
(ngSubmit)="submit()" |
||||||
|
[appApiAction]="formPromise" |
||||||
|
ngNativeValidate |
||||||
|
> |
||||||
|
<div class="modal-header"> |
||||||
|
<h2 class="modal-title" id="enrollMasterPasswordResetTitle"> |
||||||
|
{{ (isEnrolled ? "withdrawPasswordReset" : "enrollPasswordReset") | i18n }} |
||||||
|
</h2> |
||||||
|
<button |
||||||
|
type="button" |
||||||
|
class="close" |
||||||
|
data-dismiss="modal" |
||||||
|
appA11yTitle="{{ 'close' | i18n }}" |
||||||
|
> |
||||||
|
<span aria-hidden="true">×</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
<div class="modal-body"> |
||||||
|
<app-callout type="warning" *ngIf="!isEnrolled"> |
||||||
|
{{ "resetPasswordEnrollmentWarning" | i18n }} |
||||||
|
</app-callout> |
||||||
|
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification> |
||||||
|
</div> |
||||||
|
<div class="modal-footer"> |
||||||
|
<button bit-button buttonType="primary" type="submit" [disabled]="form.loading"> |
||||||
|
<i |
||||||
|
class="bwi bwi-spinner bwi-spin" |
||||||
|
title="{{ 'loading' | i18n }}" |
||||||
|
*ngIf="form.loading" |
||||||
|
></i> |
||||||
|
<span> |
||||||
|
{{ "submit" | i18n }} |
||||||
|
</span> |
||||||
|
</button> |
||||||
|
<button |
||||||
|
bit-button |
||||||
|
buttonType="secondary" |
||||||
|
type="button" |
||||||
|
data-dismiss="modal" |
||||||
|
appA11yTitle="{{ 'close' | i18n }}" |
||||||
|
> |
||||||
|
<span> |
||||||
|
{{ "cancel" | i18n }} |
||||||
|
</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
@ -0,0 +1,97 @@ |
|||||||
|
import { Component } from "@angular/core"; |
||||||
|
|
||||||
|
import { ModalRef } from "jslib-angular/components/modal/modal.ref"; |
||||||
|
import { ModalConfig } from "jslib-angular/services/modal.service"; |
||||||
|
import { ApiService } from "jslib-common/abstractions/api.service"; |
||||||
|
import { CryptoService } from "jslib-common/abstractions/crypto.service"; |
||||||
|
import { I18nService } from "jslib-common/abstractions/i18n.service"; |
||||||
|
import { LogService } from "jslib-common/abstractions/log.service"; |
||||||
|
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; |
||||||
|
import { SyncService } from "jslib-common/abstractions/sync.service"; |
||||||
|
import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; |
||||||
|
import { Utils } from "jslib-common/misc/utils"; |
||||||
|
import { Organization } from "jslib-common/models/domain/organization"; |
||||||
|
import { OrganizationUserResetPasswordEnrollmentRequest } from "jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest"; |
||||||
|
import { Verification } from "jslib-common/types/verification"; |
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: "app-enroll-master-password-reset", |
||||||
|
templateUrl: "enroll-master-password-reset.component.html", |
||||||
|
}) |
||||||
|
export class EnrollMasterPasswordReset { |
||||||
|
organization: Organization; |
||||||
|
|
||||||
|
verification: Verification; |
||||||
|
formPromise: Promise<any>; |
||||||
|
|
||||||
|
constructor( |
||||||
|
private userVerificationService: UserVerificationService, |
||||||
|
private apiService: ApiService, |
||||||
|
private platformUtilsService: PlatformUtilsService, |
||||||
|
private i18nService: I18nService, |
||||||
|
private cryptoService: CryptoService, |
||||||
|
private syncService: SyncService, |
||||||
|
private logService: LogService, |
||||||
|
private modalRef: ModalRef, |
||||||
|
config: ModalConfig |
||||||
|
) { |
||||||
|
this.organization = config.data.organization; |
||||||
|
} |
||||||
|
|
||||||
|
async submit() { |
||||||
|
let toastStringRef = "withdrawPasswordResetSuccess"; |
||||||
|
|
||||||
|
this.formPromise = this.userVerificationService |
||||||
|
.buildRequest(this.verification, OrganizationUserResetPasswordEnrollmentRequest) |
||||||
|
.then(async (request) => { |
||||||
|
// Set variables
|
||||||
|
let keyString: string = null; |
||||||
|
|
||||||
|
// Enrolling
|
||||||
|
if (!this.organization.resetPasswordEnrolled) { |
||||||
|
// Retrieve Public Key
|
||||||
|
const orgKeys = await this.apiService.getOrganizationKeys(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 encKey = await this.cryptoService.getEncKey(); |
||||||
|
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer); |
||||||
|
keyString = encryptedKey.encryptedString; |
||||||
|
toastStringRef = "enrollPasswordResetSuccess"; |
||||||
|
|
||||||
|
// Create request and execute enrollment
|
||||||
|
request.resetPasswordKey = keyString; |
||||||
|
await this.apiService.putOrganizationUserResetPasswordEnrollment( |
||||||
|
this.organization.id, |
||||||
|
this.organization.userId, |
||||||
|
request |
||||||
|
); |
||||||
|
} else { |
||||||
|
// Withdrawal
|
||||||
|
request.resetPasswordKey = keyString; |
||||||
|
await this.apiService.putOrganizationUserResetPasswordEnrollment( |
||||||
|
this.organization.id, |
||||||
|
this.organization.userId, |
||||||
|
request |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
await this.syncService.fullSync(true); |
||||||
|
}); |
||||||
|
try { |
||||||
|
await this.formPromise; |
||||||
|
this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef)); |
||||||
|
this.modalRef.close(); |
||||||
|
} catch (e) { |
||||||
|
this.logService.error(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
get isEnrolled(): boolean { |
||||||
|
return this.organization.resetPasswordEnrolled; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
import { ScrollingModule } from "@angular/cdk/scrolling"; |
||||||
|
import { NgModule } from "@angular/core"; |
||||||
|
|
||||||
|
import { LooseComponentsModule } from "../../loose-components.module"; |
||||||
|
import { SharedModule } from "../../shared.module"; |
||||||
|
|
||||||
|
import { EnrollMasterPasswordReset } from "./enroll-master-password-reset.component"; |
||||||
|
|
||||||
|
@NgModule({ |
||||||
|
imports: [SharedModule, ScrollingModule, LooseComponentsModule], |
||||||
|
declarations: [EnrollMasterPasswordReset], |
||||||
|
exports: [EnrollMasterPasswordReset], |
||||||
|
}) |
||||||
|
export class OrganizationUserModule {} |
||||||
Loading…
Reference in new issue