diff --git a/src/app/modules/organizations/users/enroll-master-password-reset.component.html b/src/app/modules/organizations/users/enroll-master-password-reset.component.html
new file mode 100644
index 0000000000..e1e389caa5
--- /dev/null
+++ b/src/app/modules/organizations/users/enroll-master-password-reset.component.html
@@ -0,0 +1,59 @@
+
diff --git a/src/app/modules/organizations/users/enroll-master-password-reset.component.ts b/src/app/modules/organizations/users/enroll-master-password-reset.component.ts
new file mode 100644
index 0000000000..b996493d85
--- /dev/null
+++ b/src/app/modules/organizations/users/enroll-master-password-reset.component.ts
@@ -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;
+
+ 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;
+ }
+}
diff --git a/src/app/modules/organizations/users/organization-user.module.ts b/src/app/modules/organizations/users/organization-user.module.ts
new file mode 100644
index 0000000000..aed0ac6629
--- /dev/null
+++ b/src/app/modules/organizations/users/organization-user.module.ts
@@ -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 {}
diff --git a/src/app/modules/vault-filter/components/organization-options.component.ts b/src/app/modules/vault-filter/components/organization-options.component.ts
index 3e0256110c..fb256acd58 100644
--- a/src/app/modules/vault-filter/components/organization-options.component.ts
+++ b/src/app/modules/vault-filter/components/organization-options.component.ts
@@ -1,17 +1,17 @@
import { Component, Input } from "@angular/core";
+import { ModalService } 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 { PolicyService } from "jslib-common/abstractions/policy.service";
import { SyncService } from "jslib-common/abstractions/sync.service";
import { PolicyType } from "jslib-common/enums/policyType";
-import { Utils } from "jslib-common/misc/utils";
import { Organization } from "jslib-common/models/domain/organization";
import { Policy } from "jslib-common/models/domain/policy";
-import { OrganizationUserResetPasswordEnrollmentRequest } from "jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest";
+
+import { EnrollMasterPasswordReset } from "../../organizations/users/enroll-master-password-reset.component";
@Component({
selector: "app-organization-options",
@@ -29,8 +29,8 @@ export class OrganizationOptionsComponent {
private i18nService: I18nService,
private apiService: ApiService,
private syncService: SyncService,
- private cryptoService: CryptoService,
private policyService: PolicyService,
+ private modalService: ModalService,
private logService: LogService
) {}
@@ -113,70 +113,11 @@ export class OrganizationOptionsComponent {
}
async toggleResetPasswordEnrollment(org: Organization) {
- // Set variables
- let keyString: string = null;
- let toastStringRef = "withdrawPasswordResetSuccess";
-
- // Enrolling
- if (!org.resetPasswordEnrolled) {
- // Alert user about enrollment
- const confirmed = await this.platformUtilsService.showDialog(
- this.i18nService.t("resetPasswordEnrollmentWarning"),
- null,
- this.i18nService.t("yes"),
- this.i18nService.t("no"),
- "warning"
- );
- if (!confirmed) {
- return;
- }
-
- // Retrieve Public Key
- this.actionPromise = this.apiService
- .getOrganizationKeys(org.id)
- .then(async (response) => {
- if (response == null) {
- throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
- }
-
- const publicKey = Utils.fromB64ToArray(response.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
- const request = new OrganizationUserResetPasswordEnrollmentRequest();
- request.resetPasswordKey = keyString;
- return this.apiService.putOrganizationUserResetPasswordEnrollment(
- org.id,
- org.userId,
- request
- );
- })
- .then(() => {
- return this.syncService.fullSync(true);
- });
- } else {
- // Withdrawal
- const request = new OrganizationUserResetPasswordEnrollmentRequest();
- request.resetPasswordKey = keyString;
- this.actionPromise = this.apiService
- .putOrganizationUserResetPasswordEnrollment(org.id, org.userId, request)
- .then(() => {
- return this.syncService.fullSync(true);
- });
- }
-
- try {
- await this.actionPromise;
- this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef));
- await this.load();
- } catch (e) {
- this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e.message);
- this.logService.error(e);
- }
+ this.modalService.open(EnrollMasterPasswordReset, {
+ allowMultipleModals: true,
+ data: {
+ organization: org,
+ },
+ });
}
}
diff --git a/src/app/oss.module.ts b/src/app/oss.module.ts
index 88311f9ded..cd4d3d9d05 100644
--- a/src/app/oss.module.ts
+++ b/src/app/oss.module.ts
@@ -2,6 +2,7 @@ import { NgModule } from "@angular/core";
import { LooseComponentsModule } from "./modules/loose-components.module";
import { OrganizationManageModule } from "./modules/organizations/manage/organization-manage.module";
+import { OrganizationUserModule } from "./modules/organizations/users/organization-user.module";
import { PipesModule } from "./modules/pipes/pipes.module";
import { SharedModule } from "./modules/shared.module";
import { VaultFilterModule } from "./modules/vault-filter/vault-filter.module";
@@ -15,6 +16,7 @@ import { OrganizationBadgeModule } from "./modules/vault/modules/organization-ba
OrganizationBadgeModule,
PipesModule,
OrganizationManageModule,
+ OrganizationUserModule,
],
exports: [LooseComponentsModule, VaultFilterModule, OrganizationBadgeModule, PipesModule],
bootstrap: [],
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index 1b62eec2be..6cd0bbd02d 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -4163,7 +4163,7 @@
"message": "Password reset success!"
},
"resetPasswordEnrollmentWarning": {
- "message": "Enrollment will allow organization administrators to change your master password. Are you sure you want to enroll?"
+ "message": "Enrollment will allow organization administrators to change your master password"
},
"resetPasswordPolicy": {
"message": "Master Password Reset"