1
0
mirror of https://github.com/bitwarden/web synced 2025-12-06 00:03:28 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Carlos J. Muentes
a001ac72b5 Adding IIFE for obtaining master password 2022-04-06 10:46:35 -04:00
Carlos J. Muentes
356bd14bb4 Update jslib 2022-04-05 19:43:50 -04:00
Carlos J. Muentes
66046660d1 CSA-2 - capturing user master password for password change enrollment 2022-04-05 19:42:38 -04:00
8 changed files with 120 additions and 5 deletions

2
jslib

Submodule jslib updated: e595c0548e...dc7efa4970

3
package-lock.json generated
View File

@@ -87,7 +87,7 @@
}
},
"jslib/angular": {
"name": "@bitwarden/jslib-common",
"name": "@bitwarden/jslib-angular",
"version": "0.0.0",
"license": "GPL-3.0",
"dependencies": {
@@ -113,6 +113,7 @@
}
},
"jslib/common": {
"name": "@bitwarden/jslib-common",
"version": "0.0.0",
"license": "GPL-3.0",
"dependencies": {

View File

@@ -171,6 +171,7 @@ import { EmergencyAccessViewComponent } from "./settings/emergency-access-view.c
import { EmergencyAccessComponent } from "./settings/emergency-access.component";
import { EmergencyAddEditComponent } from "./settings/emergency-add-edit.component";
import { LinkSsoComponent } from "./settings/link-sso.component";
import { MasterPasswordEnrollmentComponent } from "./settings/master-password-enrollment.component";
import { OptionsComponent } from "./settings/options.component";
import { OrganizationPlansComponent } from "./settings/organization-plans.component";
import { OrganizationsComponent } from "./settings/organizations.component";
@@ -335,6 +336,7 @@ registerLocaleData(localeZhTw, "zh-TW");
LockComponent,
LoginComponent,
MasterPasswordPolicyComponent,
MasterPasswordEnrollmentComponent,
NavbarComponent,
NestedCheckboxComponent,
OptionsComponent,

View File

@@ -0,0 +1,39 @@
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="passwordEnrollment">
<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="passwordEnrollmentTitle">
{{ passwordEnrollmentTitle | i18n }}
</h2>
<button
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>{{ passwordEnrollmentDescription | i18n }}</p>
<app-verify-master-password [(ngModel)]="masterPassword" ngDefaultControl name="secret">
</app-verify-master-password>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit">
<i class="fa fa-paper-plane" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "submit" | i18n }}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{ "close" | i18n }}
</button>
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,37 @@
import { Component, EventEmitter, Output } from "@angular/core";
import { LogService } from "jslib-common/abstractions/log.service";
import { UserVerificationService } from "jslib-common/abstractions/userVerification.service";
import { SecretVerificationRequest } from "jslib-common/models/request/secretVerificationRequest";
import { Verification } from "jslib-common/types/verification";
@Component({
selector: "master-password-enrollment",
templateUrl: "master-password-enrollment.component.html",
})
export class MasterPasswordEnrollmentComponent {
masterPassword: Verification;
formPromise: Promise<void | SecretVerificationRequest>;
passwordEnrollmentTitle: string;
passwordEnrollmentDescription: string;
@Output()
requestBuilt = new EventEmitter<SecretVerificationRequest>();
constructor(
private userVerificationService: UserVerificationService,
private logService: LogService
) {}
async submit() {
try {
this.formPromise = this.userVerificationService
.buildRequest(this.masterPassword)
.then((request) => this.requestBuilt.emit(request));
return await this.formPromise;
} catch (e) {
this.logService.error(e);
}
}
}

View File

@@ -153,3 +153,4 @@
</table>
</ng-container>
</ng-container>
<ng-template #confirmMasterPassword></ng-template>

View File

@@ -1,5 +1,6 @@
import { Component, Input, OnInit } from "@angular/core";
import { Component, Input, OnInit, ViewChild, ViewContainerRef } 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";
@@ -14,12 +15,16 @@ 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 { MasterPasswordEnrollmentComponent } from "./master-password-enrollment.component";
@Component({
selector: "app-organizations",
templateUrl: "organizations.component.html",
})
export class OrganizationsComponent implements OnInit {
@Input() vault = false;
@ViewChild("confirmMasterPassword", { read: ViewContainerRef, static: true })
confirmMasterPasswordModalRef: ViewContainerRef;
organizations: Organization[];
policies: Policy[];
@@ -34,7 +39,8 @@ export class OrganizationsComponent implements OnInit {
private syncService: SyncService,
private cryptoService: CryptoService,
private policyService: PolicyService,
private logService: LogService
private logService: LogService,
private modalService: ModalService
) {}
async ngOnInit() {
@@ -157,11 +163,14 @@ export class OrganizationsComponent implements OnInit {
// Create request and execute enrollment
const request = new OrganizationUserResetPasswordEnrollmentRequest();
request.resetPasswordKey = keyString;
return this.apiService.putOrganizationUserResetPasswordEnrollment(
request.masterPasswordHash = await this.getMasterPassword();
const res = this.apiService.putOrganizationUserResetPasswordEnrollment(
org.id,
org.userId,
request
);
return res;
})
.then(() => {
return this.syncService.fullSync(true);
@@ -170,6 +179,7 @@ export class OrganizationsComponent implements OnInit {
// Withdrawal
const request = new OrganizationUserResetPasswordEnrollmentRequest();
request.resetPasswordKey = keyString;
request.masterPasswordHash = await this.getMasterPassword();
this.actionPromise = this.apiService
.putOrganizationUserResetPasswordEnrollment(org.id, org.userId, request)
.then(() => {
@@ -185,4 +195,23 @@ export class OrganizationsComponent implements OnInit {
this.logService.error(e);
}
}
private async getMasterPassword(): Promise<string> {
return new Promise((resolve, reject) => {
(async () => {
const [modal] = await this.modalService.openViewRef(
MasterPasswordEnrollmentComponent,
this.confirmMasterPasswordModalRef,
(comp) => {
comp.passwordEnrollmentTitle = "passwordResetEnrollment";
comp.passwordEnrollmentDescription = "passwordResetEnrollmentDescription";
comp.requestBuilt.subscribe((val) => {
modal.close();
resolve(val.masterPasswordHash);
});
}
);
})();
});
}
}

View File

@@ -4876,5 +4876,11 @@
},
"service": {
"message": "Service"
},
"passwordResetEnrollment" : {
"message": "Password Reset Enrollment"
},
"passwordResetEnrollmentDescription": {
"message": "Enter your master password so we can enroll you in password reset"
}
}