mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 22:44:11 +00:00
Suggested changes from CR
This commit is contained in:
@@ -18,8 +18,9 @@ import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { UserSecretPromptService } from "@bitwarden/common/abstractions/userSecretPrompt.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
|
||||
import { UserVerificationPromptService } from "@bitwarden/common/abstractions/userVerificationPrompt.service";
|
||||
import { EncryptedExportType } from "@bitwarden/common/enums/EncryptedExportType";
|
||||
import { EventType } from "@bitwarden/common/enums/eventType";
|
||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||
|
||||
@@ -29,7 +30,6 @@ export class ExportComponent implements OnInit {
|
||||
|
||||
formPromise: Promise<string>;
|
||||
disabledByPolicy = false;
|
||||
private alreadyVerified = false;
|
||||
|
||||
@ViewChild("viewUserApiKeyTemplate", { read: ViewContainerRef, static: true })
|
||||
viewUserApiKeyModalRef: ViewContainerRef;
|
||||
@@ -64,7 +64,7 @@ export class ExportComponent implements OnInit {
|
||||
protected modalService: ModalService,
|
||||
protected apiService: ApiService,
|
||||
protected stateService: StateService,
|
||||
protected userSecretPromptService: UserSecretPromptService,
|
||||
protected userVerificationPromptService: UserVerificationPromptService,
|
||||
protected modalConfig: ModalConfig
|
||||
) {}
|
||||
|
||||
@@ -86,12 +86,29 @@ export class ExportComponent implements OnInit {
|
||||
}
|
||||
|
||||
async submitWithSecretAlreadyVerified() {
|
||||
if (this.disabledByPolicy) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("personalVaultExportPolicyInEffect")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.validForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.alreadyVerified = true;
|
||||
this.submit();
|
||||
try {
|
||||
this.formPromise = this.getExportData();
|
||||
const data = await this.formPromise;
|
||||
this.downloadFile(data);
|
||||
this.saved();
|
||||
await this.collectEvent();
|
||||
this.exportForm.get("secret").setValue("");
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
async submit() {
|
||||
@@ -104,24 +121,22 @@ export class ExportComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.alreadyVerified) {
|
||||
const acceptedWarning = await this.warningDialog();
|
||||
if (!acceptedWarning) {
|
||||
return;
|
||||
}
|
||||
const secret = this.exportForm.get("secret").value;
|
||||
|
||||
try {
|
||||
await this.userVerificationService.verifyUser(secret);
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
e.message
|
||||
);
|
||||
return;
|
||||
}
|
||||
const acceptedWarning = await this.warningDialog();
|
||||
if (!acceptedWarning) {
|
||||
return;
|
||||
}
|
||||
const secret = this.exportForm.get("secret").value;
|
||||
|
||||
const successfulVerification = await this.userVerificationService.verifyUser(secret);
|
||||
if (!successfulVerification) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.formPromise = this.getExportData();
|
||||
const data = await this.formPromise;
|
||||
@@ -184,22 +199,21 @@ export class ExportComponent implements OnInit {
|
||||
}
|
||||
|
||||
get validForm() {
|
||||
//fileEncryptionType 2 = file requires a user entered password, specific to the file
|
||||
if (this.fileEncryptionType == 2 && this.format == "encrypted_json") {
|
||||
const password = this.password;
|
||||
const confirmPassword = this.confirmPassword;
|
||||
|
||||
if (password.length > 0 || confirmPassword.length > 0) {
|
||||
if (password != confirmPassword) {
|
||||
if (
|
||||
this.fileEncryptionType == EncryptedExportType.FileEncrypted &&
|
||||
this.format == "encrypted_json"
|
||||
) {
|
||||
if (this.password.length > 0 || this.confirmPassword.length > 0) {
|
||||
if (this.password != this.confirmPassword) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
"File Password and Confirm File Password do not match."
|
||||
this.i18nService.t("filePasswordAndConfirmFilePasswordDoNotMatch")
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.encryptionPassword = password;
|
||||
this.encryptionPassword = this.password;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Directive } from "@angular/core";
|
||||
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@@ -21,7 +20,6 @@ export class FilePasswordPromptComponent {
|
||||
|
||||
constructor(
|
||||
private modalRef: ModalRef,
|
||||
private cryptoService: CryptoService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private importService: ImportService,
|
||||
@@ -50,7 +48,11 @@ export class FilePasswordPromptComponent {
|
||||
const passwordError = await formPromise;
|
||||
|
||||
if (passwordError != null) {
|
||||
this.modalRef.close(false);
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
} else {
|
||||
this.modalRef.close(true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Directive } from "@angular/core";
|
||||
import { FormBuilder, FormControl } from "@angular/forms";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
|
||||
|
||||
import { ModalConfig } from "../services/modal.service";
|
||||
|
||||
import { ModalRef } from "./modal/modal.ref";
|
||||
|
||||
/**
|
||||
* Used to verify the user's secret, you can customize all of the text in the modal.
|
||||
*/
|
||||
@Directive()
|
||||
export class UserVerificationPromptComponent {
|
||||
showPassword = false;
|
||||
organizationId = "";
|
||||
confirmDescription = this.config.data.confirmDescription;
|
||||
confirmButtonText = this.config.data.confirmButtonText;
|
||||
modalTitle = this.config.data.modalTitle;
|
||||
myGroup = this.formBuilder.group({
|
||||
secret: new FormControl(),
|
||||
});
|
||||
|
||||
constructor(
|
||||
private modalRef: ModalRef,
|
||||
protected config: ModalConfig,
|
||||
protected userVerificationService: UserVerificationService,
|
||||
private formBuilder: FormBuilder,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService
|
||||
) {}
|
||||
|
||||
togglePassword() {
|
||||
this.showPassword = !this.showPassword;
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const secret = this.myGroup.get("secret").value;
|
||||
|
||||
try {
|
||||
//Incorrect secret will throw an invalid password error.
|
||||
await this.userVerificationService.verifyUser(secret);
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.modalRef.close(true);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import { Injectable } from "@angular/core";
|
||||
import { FilePasswordPromptService as FilePasswordPromptServiceAbstraction } from "@bitwarden/common/abstractions/filePasswordPrompt.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
|
||||
|
||||
|
||||
import { FilePasswordPromptComponent } from "../components/file-password-prompt.component";
|
||||
|
||||
import { ModalService } from "./modal.service";
|
||||
@@ -29,7 +28,7 @@ export class FilePasswordPromptService implements FilePasswordPromptServiceAbstr
|
||||
return true;
|
||||
}
|
||||
|
||||
const ref = this.modalService.open(this.component, {
|
||||
const ref = await this.modalService.open(this.component, {
|
||||
allowMultipleModals: true,
|
||||
data: {
|
||||
fileContents: fcontents,
|
||||
|
||||
56
libs/angular/src/services/userVerificationPrompt.service.ts
Normal file
56
libs/angular/src/services/userVerificationPrompt.service.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
|
||||
import { UserVerificationPromptService as UserVerificationPromptServiceAbstraction } from "@bitwarden/common/abstractions/userVerificationPrompt.service";
|
||||
|
||||
import { UserVerificationPromptComponent } from "../components/user-verification-prompt.component";
|
||||
|
||||
import { ModalService } from "./modal.service";
|
||||
|
||||
/**
|
||||
* Used to verify the user's File Password for the "Import passwords using File Password" feature only.
|
||||
*/
|
||||
@Injectable()
|
||||
export class UserVerificationPromptService implements UserVerificationPromptServiceAbstraction {
|
||||
protected component = UserVerificationPromptComponent;
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
protected i18nService: I18nService
|
||||
) {}
|
||||
|
||||
protectedFields() {
|
||||
return ["TOTP", "Password", "H_Field", "Card Number", "Security Code"];
|
||||
}
|
||||
|
||||
async showUserVerificationPrompt(
|
||||
confirmDescription?: string,
|
||||
confirmButtonText?: string,
|
||||
modalTitle?: string
|
||||
) {
|
||||
if (!(await this.enabled())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const ref = await this.modalService.open(this.component, {
|
||||
allowMultipleModals: true,
|
||||
data: {
|
||||
confirmDescription: confirmDescription ? confirmDescription : "passwordConfirmationDesc",
|
||||
confirmButtonText: confirmButtonText ? confirmButtonText : "ok",
|
||||
modalTitle: modalTitle ? modalTitle : "passwordConfirmation",
|
||||
},
|
||||
});
|
||||
|
||||
if (ref == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (await ref.onClosedPromise()) === true;
|
||||
}
|
||||
|
||||
async enabled() {
|
||||
return !(await this.keyConnectorService.getUsesKeyConnector());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user