Suggested changes from CR
This commit is contained in:
parent
85e327ab7d
commit
568537af19
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-top-padding-sm">
|
||||
<div class="tw-mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<span>{{ "importData" | i18n }}</span>
|
||||
</button>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="confirmUserTitle">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<form class="modal-content" #form (ngSubmit)="submit()">
|
||||
<div class="tw-text-center bwi-3x">
|
||||
<i class="bwi bwi-exclamation-triangle text-warning"></i>
|
||||
</div>
|
||||
|
||||
<h2 class="tw-text-center tw-font-semibold" id="confirmUserTitle">
|
||||
{{ modalTitle | i18n }}
|
||||
</h2>
|
||||
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
{{ confirmDescription | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer-content">
|
||||
<div [formGroup]="myGroup">
|
||||
<div class="form-group">
|
||||
<app-user-verification ngDefaultControl formControlName="secret" name="secret">
|
||||
</app-user-verification>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<span>{{ confirmButtonText | i18n }}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
import { Component } from "@angular/core";
|
||||
|
||||
import { UserVerificationPromptComponent as BaseUserVerificationPrompt } from "@bitwarden/angular/components/user-verification-prompt.component";
|
||||
|
||||
@Component({
|
||||
templateUrl: "user-verification-prompt.component.html",
|
||||
})
|
||||
export class UserVerificationPromptComponent extends BaseUserVerificationPrompt {}
|
|
@ -25,7 +25,7 @@ import { OrganizationSwitcherComponent } from "../components/organization-switch
|
|||
import { PasswordRepromptComponent } from "../components/password-reprompt.component";
|
||||
import { PasswordStrengthComponent } from "../components/password-strength.component";
|
||||
import { PremiumBadgeComponent } from "../components/premium-badge.component";
|
||||
import { UserSecretPromptComponent } from "../components/user-secret-prompt.component";
|
||||
import { UserVerificationPromptComponent } from "../components/user-verification-prompt.component";
|
||||
import { FooterComponent } from "../layouts/footer.component";
|
||||
import { FrontendLayoutComponent } from "../layouts/frontend-layout.component";
|
||||
import { NavbarComponent } from "../layouts/navbar.component";
|
||||
|
@ -272,7 +272,7 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
|||
PasswordGeneratorPolicyComponent,
|
||||
PasswordRepromptComponent,
|
||||
FilePasswordPromptComponent,
|
||||
UserSecretPromptComponent,
|
||||
UserVerificationPromptComponent,
|
||||
PasswordStrengthComponent,
|
||||
PaymentComponent,
|
||||
PaymentMethodComponent,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { FormBuilder } from "@angular/forms";
|
|||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { ModalConfig, ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { UserSecretPromptService } from "@bitwarden/angular/services/userSecretPrompt.service";
|
||||
import { UserVerificationPromptService } from "@bitwarden/angular/services/userVerificationPrompt.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
|
@ -36,7 +36,7 @@ export class ExportComponent extends BaseExportComponent {
|
|||
modalService: ModalService,
|
||||
apiService: ApiService,
|
||||
stateService: StateService,
|
||||
userSecretPromptService: UserSecretPromptService,
|
||||
userVerificationPromptService: UserVerificationPromptService,
|
||||
modalConfig: ModalConfig
|
||||
) {
|
||||
super(
|
||||
|
@ -52,7 +52,7 @@ export class ExportComponent extends BaseExportComponent {
|
|||
modalService,
|
||||
apiService,
|
||||
stateService,
|
||||
userSecretPromptService,
|
||||
userVerificationPromptService,
|
||||
modalConfig
|
||||
);
|
||||
this.confirmDescription = modalConfig.data.confirmDescription;
|
||||
|
|
|
@ -31,7 +31,7 @@ import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwar
|
|||
import { StateService as BaseStateServiceAbstraction } from "@bitwarden/common/abstractions/state.service";
|
||||
import { StateMigrationService as StateMigrationServiceAbstraction } from "@bitwarden/common/abstractions/stateMigration.service";
|
||||
import { StorageService as StorageServiceAbstraction } from "@bitwarden/common/abstractions/storage.service";
|
||||
import { UserSecretPromptService as UserSecretPromptServiceAbstraction } from "@bitwarden/common/abstractions/userSecretPrompt.service";
|
||||
import { UserVerificationPromptService as UserVerificationPromptServiceAbstraction } from "@bitwarden/common/abstractions/userVerificationPrompt.service";
|
||||
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
|
||||
import { ExportService } from "@bitwarden/common/services/export.service";
|
||||
import { ImportService } from "@bitwarden/common/services/import.service";
|
||||
|
@ -47,7 +47,7 @@ import { MemoryStorageService } from "../../services/memoryStorage.service";
|
|||
import { PasswordRepromptService } from "../../services/passwordReprompt.service";
|
||||
import { StateService } from "../../services/state.service";
|
||||
import { StateMigrationService } from "../../services/stateMigration.service";
|
||||
import { UserSecretPromptService } from "../../services/userSecretPrompt.service";
|
||||
import { UserVerificationPromptService } from "../../services/userVerificationPrompt.service";
|
||||
import { WebPlatformUtilsService } from "../../services/webPlatformUtils.service";
|
||||
import { HomeGuard } from "../guards/home.guard";
|
||||
import { PermissionsGuard as OrgPermissionsGuard } from "../organizations/guards/permissions.guard";
|
||||
|
@ -156,8 +156,8 @@ import { RouterService } from "./router.service";
|
|||
useClass: FilePasswordPromptService,
|
||||
},
|
||||
{
|
||||
provide: UserSecretPromptServiceAbstraction,
|
||||
useClass: UserSecretPromptService,
|
||||
provide: UserVerificationPromptServiceAbstraction,
|
||||
useClass: UserVerificationPromptService,
|
||||
},
|
||||
HomeGuard,
|
||||
],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<form
|
||||
#form
|
||||
(ngSubmit)="promptUserForSecret(encryptionType)"
|
||||
(ngSubmit)="submit()"
|
||||
ngNativeValidate
|
||||
[appApiAction]="formPromise"
|
||||
[formGroup]="exportForm"
|
||||
|
@ -25,28 +25,21 @@
|
|||
name="format"
|
||||
formControlName="format"
|
||||
[(ngModel)]="formatControl"
|
||||
(change)="encryptionType = '0'"
|
||||
(change)="encryptionType = 0"
|
||||
>
|
||||
<option *ngFor="let f of formatOptions" [value]="f.value">{{ f.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="box form-group col-6">
|
||||
<input formControlName="secret" name="secret" style="display: none" />
|
||||
|
||||
<ng-container class="box-content condensed" *ngIf="formatControl === 'encrypted_json'">
|
||||
<div
|
||||
class="box-content-row box-content-row-radio"
|
||||
role="radiogroup"
|
||||
aria-labelledby="fileTypeHeading"
|
||||
>
|
||||
<div class="form-group col-6">
|
||||
<ng-container *ngIf="formatControl === 'encrypted_json'">
|
||||
<div role="radiogroup" aria-labelledby="fileTypeHeading">
|
||||
<label id="fileTypeHeading" class="radio-header">
|
||||
{{ "fileTypeHeading" | i18n }}
|
||||
</label>
|
||||
|
||||
<!-- First Item -- Account Backup Option -->
|
||||
<div class="radio-group align-start text-default" appBoxRow name="FileTypeOptions">
|
||||
<div appBoxRow name="FileTypeOptions">
|
||||
<input
|
||||
type="radio"
|
||||
class="radio"
|
||||
|
@ -54,9 +47,9 @@
|
|||
id="1"
|
||||
[value]="1"
|
||||
[(ngModel)]="encryptionType"
|
||||
(change)="encryptionType = '1'"
|
||||
(change)="encryptionType = 0"
|
||||
/>
|
||||
<label class="unstyled"> Account Backup </label>
|
||||
<label class="unstyled"> {{ "accountBackup" | i18n }} </label>
|
||||
<div class="small text-muted" style="margin-left: 1.25em">
|
||||
{{ "accountBackupOptionDescription" | i18n }}
|
||||
</div>
|
||||
|
@ -67,24 +60,20 @@
|
|||
id="2"
|
||||
[value]="2"
|
||||
[(ngModel)]="encryptionType"
|
||||
(change)="encryptionType = '2'"
|
||||
(change)="encryptionType = 1"
|
||||
/>
|
||||
|
||||
<input formControlName="fileEncryptionType" [ngModel]="encryptionType" hidden="true" />
|
||||
|
||||
<label class="unstyled"> Password Protected </label>
|
||||
<label class="unstyled">{{ "passwordProtected" | i18n }}</label>
|
||||
<div class="small text-muted" style="margin-left: 1.25em">
|
||||
{{ "passwordProtectedOptionDescription" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
class="row"
|
||||
*ngIf="encryptionType === '2' && formatControl === 'encrypted_json'"
|
||||
>
|
||||
<ng-container *ngIf="encryptionType == 1">
|
||||
<label for="format">{{ "filePassword" | i18n }}</label>
|
||||
|
||||
<div class="input-group">
|
||||
|
@ -149,6 +138,7 @@
|
|||
</div>
|
||||
<br />
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-submit"
|
||||
|
|
|
@ -12,8 +12,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";
|
||||
|
||||
@Component({
|
||||
selector: "app-export",
|
||||
|
@ -22,7 +23,7 @@ import { UserVerificationService } from "@bitwarden/common/abstractions/userVeri
|
|||
export class ExportComponent extends BaseExportComponent {
|
||||
organizationId: string;
|
||||
formatControl: string;
|
||||
encryptionType: string;
|
||||
encryptionType: EncryptedExportType;
|
||||
showPassword: boolean;
|
||||
showConfirmPassword: boolean;
|
||||
secretValue: string;
|
||||
|
@ -31,9 +32,6 @@ export class ExportComponent extends BaseExportComponent {
|
|||
confirmButtonText: string;
|
||||
modalTitle: string;
|
||||
|
||||
@ViewChild("viewUserApiKeyModalRef", { read: ViewContainerRef, static: true })
|
||||
viewUserApiKeyModalRef: ViewContainerRef;
|
||||
|
||||
constructor(
|
||||
cryptoService: CryptoService,
|
||||
i18nService: I18nService,
|
||||
|
@ -47,7 +45,7 @@ export class ExportComponent extends BaseExportComponent {
|
|||
modalService: ModalService,
|
||||
apiService: ApiService,
|
||||
stateService: StateService,
|
||||
userSecretPromptService: UserSecretPromptService,
|
||||
userVerificationPromptService: UserVerificationPromptService,
|
||||
modalConfig: ModalConfig
|
||||
) {
|
||||
super(
|
||||
|
@ -64,44 +62,30 @@ export class ExportComponent extends BaseExportComponent {
|
|||
modalService,
|
||||
apiService,
|
||||
stateService,
|
||||
userSecretPromptService,
|
||||
userVerificationPromptService,
|
||||
modalConfig
|
||||
);
|
||||
}
|
||||
|
||||
async promptUserForSecret(encryptionType: string) {
|
||||
//Default text values
|
||||
let confirmDescription = "encExportKeyWarningDesc";
|
||||
let confirmButtonText = "exportVault";
|
||||
let modalTitle = "confirmVaultExport";
|
||||
|
||||
//Password encrypted export
|
||||
if (encryptionType == "2") {
|
||||
confirmDescription = "confirmVaultExportDesc";
|
||||
confirmButtonText = "exportVault";
|
||||
modalTitle = "confirmVaultExport";
|
||||
}
|
||||
async submit() {
|
||||
const confirmDescription =
|
||||
this.encryptionType == EncryptedExportType.FileEncrypted
|
||||
? "confirmVaultExportDesc"
|
||||
: "encExportKeyWarningDesc";
|
||||
const confirmButtonText = "exportVault";
|
||||
const modalTitle = "confirmVaultExport";
|
||||
|
||||
try {
|
||||
if (
|
||||
await this.userSecretPromptService.showPasswordPrompt(
|
||||
await this.userVerificationPromptService.showUserVerificationPrompt(
|
||||
confirmDescription,
|
||||
confirmButtonText,
|
||||
modalTitle
|
||||
)
|
||||
) {
|
||||
//successful
|
||||
} else {
|
||||
//failed
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.submitWithSecretAlreadyVerified();
|
||||
}
|
||||
} catch {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
|
|
|
@ -119,11 +119,6 @@ export class ImportComponent implements OnInit {
|
|||
} else {
|
||||
//failed - File Password issues
|
||||
this.loading = false;
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -896,15 +896,24 @@
|
|||
"confirmFilePassword": {
|
||||
"message": "Confirm File Password"
|
||||
},
|
||||
"passwordProtectedOptionDescription": {
|
||||
"message": "Leverages your bitwarden account encryption not master password, to protect the export. This export can only be imported into the current account. Use this to create a backup that cannot be used elsewhere."
|
||||
},
|
||||
"accountBackupOptionDescription": {
|
||||
"message": "Leverages your Bitwarden account encryption not master password, to protect the export. This export can only be imported into the current account. Use this to create a backup that cannot be used elsewhere."
|
||||
},
|
||||
"passwordProtectedOptionDescription": {
|
||||
"message": "Create a user-generated password to protect the export. Use this to create an export that can be used in other accounts."
|
||||
},
|
||||
"fileTypeHeading": {
|
||||
"message": "File Type"
|
||||
},
|
||||
"accountBackup": {
|
||||
"message": "Account Backup"
|
||||
},
|
||||
"passwordProtected": {
|
||||
"message": "Password Protected"
|
||||
},
|
||||
"filePasswordAndConfirmFilePasswordDoNotMatch": {
|
||||
"message": "File Password and Confirm File Password do not match."
|
||||
},
|
||||
"confirmVaultImport": {
|
||||
"message": "Confirm Vault Import"
|
||||
},
|
||||
|
|
|
@ -875,30 +875,6 @@
|
|||
"exportVault": {
|
||||
"message": "Export vault"
|
||||
},
|
||||
"confirmFormat": {
|
||||
"message": "Confirm Format"
|
||||
},
|
||||
"filePassword": {
|
||||
"message": "File Password"
|
||||
},
|
||||
"confirmFilePassword": {
|
||||
"message": "Confirm File Password"
|
||||
},
|
||||
"passwordProtectedOptionDescription": {
|
||||
"message": "Leverages your bitwarden account encryption not master password, to protect the export. This export can only be imported into the current account. Use this to create a backup that cannot be used elsewhere."
|
||||
},
|
||||
"accountBackupOptionDescription": {
|
||||
"message": "Create a user-generated password to protect the export. Use this to create an export that can be used in other accounts."
|
||||
},
|
||||
"fileTypeHeading": {
|
||||
"message": "File Type"
|
||||
},
|
||||
"confirmVaultImport": {
|
||||
"message": "Confirm Vault Import"
|
||||
},
|
||||
"confirmVaultImportDesc": {
|
||||
"message": "This file is password protected. Please enter the file password to import data."
|
||||
},
|
||||
"fileFormat": {
|
||||
"message": "File format"
|
||||
},
|
||||
|
@ -4725,9 +4701,6 @@
|
|||
"confirmIdentity": {
|
||||
"message": "Confirm your identity to continue."
|
||||
},
|
||||
"exportPasswordDescription" : {
|
||||
"message": "This password will be used to export and import this file"
|
||||
},
|
||||
"verificationCodeRequired": {
|
||||
"message": "Verification code is required."
|
||||
},
|
||||
|
|
|
@ -6,6 +6,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
.modal-footer-content {
|
||||
border: none;
|
||||
border-radius: none;
|
||||
@include themify($themes) {
|
||||
background-color: themed("footerBackgroundColor");
|
||||
}
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
pointer-events: auto;
|
||||
background-clip: padding-box;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0.3rem;
|
||||
|
@ -75,10 +90,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.modal-top-padding-sm {
|
||||
padding-top: 1.5em;
|
||||
}
|
||||
|
||||
.close {
|
||||
@include themify($themes) {
|
||||
color: themed("textColor");
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { UserVerificationPromptService as BaseUserVerificationPrompt } from "@bitwarden/angular/services/userVerificationPrompt.service";
|
||||
|
||||
import { UserVerificationPromptComponent } from "../app/components/user-verification-prompt.component";
|
||||
|
||||
@Injectable()
|
||||
export class UserVerificationPromptService extends BaseUserVerificationPrompt {
|
||||
component = UserVerificationPromptComponent;
|
||||
}
|
|
@ -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) {
|
||||
const successfulVerification = await this.userVerificationService.verifyUser(secret);
|
||||
if (!successfulVerification) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
e.message
|
||||
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,
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue