mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 02:33:46 +00:00
Merge branch 'autofill/pm-6921-optimize-inline-menu-background-collect-page-details-for-tab-process' into autofill/pm-5189-fix-issues-present-with-inline-menu-rendering-in-iframes
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { DefaultPassphraseGenerationOptions } from "@bitwarden/common/tools/generator/passphrase";
|
import { DefaultPassphraseGenerationOptions } from "@bitwarden/common/tools/generator/passphrase";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
import {
|
||||||
|
DefaultPasswordGenerationOptions,
|
||||||
|
PasswordGenerationServiceAbstraction,
|
||||||
|
} from "@bitwarden/common/tools/generator/password";
|
||||||
import { PasswordGeneratorOptions } from "@bitwarden/common/tools/generator/password/password-generator-options";
|
import { PasswordGeneratorOptions } from "@bitwarden/common/tools/generator/password/password-generator-options";
|
||||||
|
|
||||||
import { Response } from "../models/response";
|
import { Response } from "../models/response";
|
||||||
@@ -64,7 +67,10 @@ class Options {
|
|||||||
this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize);
|
this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize);
|
||||||
this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber);
|
this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber);
|
||||||
this.ambiguous = CliUtils.convertBooleanOption(passedOptions?.ambiguous);
|
this.ambiguous = CliUtils.convertBooleanOption(passedOptions?.ambiguous);
|
||||||
this.length = CliUtils.convertNumberOption(passedOptions?.length, 14);
|
this.length = CliUtils.convertNumberOption(
|
||||||
|
passedOptions?.length,
|
||||||
|
DefaultPasswordGenerationOptions.length,
|
||||||
|
);
|
||||||
this.type = passedOptions?.passphrase ? "passphrase" : "password";
|
this.type = passedOptions?.passphrase ? "passphrase" : "password";
|
||||||
this.separator = CliUtils.convertStringOption(
|
this.separator = CliUtils.convertStringOption(
|
||||||
passedOptions?.separator,
|
passedOptions?.separator,
|
||||||
@@ -74,8 +80,14 @@ class Options {
|
|||||||
passedOptions?.words,
|
passedOptions?.words,
|
||||||
DefaultPassphraseGenerationOptions.numWords,
|
DefaultPassphraseGenerationOptions.numWords,
|
||||||
);
|
);
|
||||||
this.minNumber = CliUtils.convertNumberOption(passedOptions?.minNumber, 1);
|
this.minNumber = CliUtils.convertNumberOption(
|
||||||
this.minSpecial = CliUtils.convertNumberOption(passedOptions?.minSpecial, 1);
|
passedOptions?.minNumber,
|
||||||
|
DefaultPasswordGenerationOptions.minNumber,
|
||||||
|
);
|
||||||
|
this.minSpecial = CliUtils.convertNumberOption(
|
||||||
|
passedOptions?.minSpecial,
|
||||||
|
DefaultPasswordGenerationOptions.minSpecial,
|
||||||
|
);
|
||||||
|
|
||||||
if (!this.uppercase && !this.lowercase && !this.special && !this.number) {
|
if (!this.uppercase && !this.lowercase && !this.special && !this.number) {
|
||||||
this.lowercase = true;
|
this.lowercase = true;
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
<app-header></app-header>
|
<app-header></app-header>
|
||||||
|
|
||||||
<bit-container>
|
<bit-container>
|
||||||
<form
|
<form [formGroup]="exportForm" [bitSubmit]="submit">
|
||||||
#form
|
|
||||||
(ngSubmit)="submit()"
|
|
||||||
[appApiAction]="formPromise"
|
|
||||||
[formGroup]="exportForm"
|
|
||||||
*ngIf="exportForm"
|
|
||||||
>
|
|
||||||
<bit-callout type="danger" title="{{ 'vaultExportDisabled' | i18n }}" *ngIf="disabledByPolicy">
|
<bit-callout type="danger" title="{{ 'vaultExportDisabled' | i18n }}" *ngIf="disabledByPolicy">
|
||||||
{{ "personalVaultExportPolicyInEffect" | i18n }}
|
{{ "personalVaultExportPolicyInEffect" | i18n }}
|
||||||
</bit-callout>
|
</bit-callout>
|
||||||
@@ -110,9 +104,9 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
bitButton
|
bitButton
|
||||||
|
bitFormButton
|
||||||
type="submit"
|
type="submit"
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
[loading]="form.loading"
|
|
||||||
[disabled]="disabledByPolicy"
|
[disabled]="disabledByPolicy"
|
||||||
>
|
>
|
||||||
{{ "confirmFormat" | i18n }}
|
{{ "confirmFormat" | i18n }}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { UntypedFormBuilder } from "@angular/forms";
|
import { UntypedFormBuilder } from "@angular/forms";
|
||||||
import { firstValueFrom } from "rxjs";
|
|
||||||
|
|
||||||
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component";
|
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component";
|
||||||
|
import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
@@ -11,20 +11,14 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { EncryptedExportType } from "@bitwarden/common/tools/enums/encrypted-export-type.enum";
|
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
||||||
|
|
||||||
import { openUserVerificationPrompt } from "../../auth/shared/components/user-verification";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-export",
|
selector: "app-export",
|
||||||
templateUrl: "export.component.html",
|
templateUrl: "export.component.html",
|
||||||
})
|
})
|
||||||
export class ExportComponent extends BaseExportComponent {
|
export class ExportComponent extends BaseExportComponent {
|
||||||
encryptedExportType = EncryptedExportType;
|
|
||||||
protected showFilePassword: boolean;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
@@ -53,7 +47,7 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
submit = async () => {
|
||||||
if (this.isFileEncryptedExport && this.filePassword != this.confirmFilePassword) {
|
if (this.isFileEncryptedExport && this.filePassword != this.confirmFilePassword) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
@@ -64,7 +58,7 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.exportForm.markAllAsTouched();
|
this.exportForm.markAllAsTouched();
|
||||||
if (!this.exportForm.valid) {
|
if (this.exportForm.invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,14 +79,14 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.doExport();
|
this.doExport();
|
||||||
}
|
};
|
||||||
|
|
||||||
protected saved() {
|
protected saved() {
|
||||||
super.saved();
|
super.saved();
|
||||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("exportSuccess"));
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("exportSuccess"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private verifyUser() {
|
private async verifyUser(): Promise<boolean> {
|
||||||
let confirmDescription = "exportWarningDesc";
|
let confirmDescription = "exportWarningDesc";
|
||||||
if (this.isFileEncryptedExport) {
|
if (this.isFileEncryptedExport) {
|
||||||
confirmDescription = "fileEncryptedExportWarningDesc";
|
confirmDescription = "fileEncryptedExportWarningDesc";
|
||||||
@@ -100,32 +94,30 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
confirmDescription = "encExportKeyWarningDesc";
|
confirmDescription = "encExportKeyWarningDesc";
|
||||||
}
|
}
|
||||||
|
|
||||||
const ref = openUserVerificationPrompt(this.dialogService, {
|
const result = await UserVerificationDialogComponent.open(this.dialogService, {
|
||||||
data: {
|
clientSideOnlyVerification: true,
|
||||||
confirmDescription: confirmDescription,
|
title: "confirmVaultExport",
|
||||||
confirmButtonText: "exportVault",
|
bodyText: confirmDescription,
|
||||||
modalTitle: "confirmVaultExport",
|
confirmButtonOptions: {
|
||||||
|
text: "exportVault",
|
||||||
|
type: "primary",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ref == null) {
|
// Handle the result of the dialog based on user action and verification success
|
||||||
return;
|
if (result.userAction === "cancel") {
|
||||||
|
// User cancelled the dialog
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstValueFrom(ref.closed);
|
// User confirmed the dialog so check verification success
|
||||||
|
if (!result.verificationSuccess) {
|
||||||
|
if (result.noAvailableClientVerificationMethods) {
|
||||||
|
// No client-side verification methods are available
|
||||||
|
// Could send user to configure a verification method like PIN or biometrics
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
get isFileEncryptedExport() {
|
|
||||||
return (
|
|
||||||
this.format === "encrypted_json" &&
|
|
||||||
this.fileEncryptionType === EncryptedExportType.FileEncrypted
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
get isAccountEncryptedExport() {
|
|
||||||
return (
|
|
||||||
this.format === "encrypted_json" &&
|
|
||||||
this.fileEncryptionType === EncryptedExportType.AccountEncrypted
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
@Output() onSaved = new EventEmitter();
|
@Output() onSaved = new EventEmitter();
|
||||||
@ViewChild(PasswordStrengthComponent) passwordStrengthComponent: PasswordStrengthComponent;
|
@ViewChild(PasswordStrengthComponent) passwordStrengthComponent: PasswordStrengthComponent;
|
||||||
|
|
||||||
|
encryptedExportType = EncryptedExportType;
|
||||||
|
protected showFilePassword: boolean;
|
||||||
|
|
||||||
filePasswordValue: string = null;
|
filePasswordValue: string = null;
|
||||||
formPromise: Promise<string>;
|
|
||||||
private _disabledByPolicy = false;
|
private _disabledByPolicy = false;
|
||||||
|
|
||||||
protected organizationId: string = null;
|
protected organizationId: string = null;
|
||||||
@@ -126,10 +128,23 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
return this.format === "encrypted_json";
|
return this.format === "encrypted_json";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isFileEncryptedExport() {
|
||||||
|
return (
|
||||||
|
this.format === "encrypted_json" &&
|
||||||
|
this.fileEncryptionType === EncryptedExportType.FileEncrypted
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get isAccountEncryptedExport() {
|
||||||
|
return (
|
||||||
|
this.format === "encrypted_json" &&
|
||||||
|
this.fileEncryptionType === EncryptedExportType.AccountEncrypted
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected async doExport() {
|
protected async doExport() {
|
||||||
try {
|
try {
|
||||||
this.formPromise = this.getExportData();
|
const data = await this.getExportData();
|
||||||
const data = await this.formPromise;
|
|
||||||
this.downloadFile(data);
|
this.downloadFile(data);
|
||||||
this.saved();
|
this.saved();
|
||||||
await this.collectEvent();
|
await this.collectEvent();
|
||||||
|
|||||||
@@ -78,6 +78,6 @@ export const DefaultPasswordGenerationOptions: Partial<PasswordGenerationOptions
|
|||||||
lowercase: true,
|
lowercase: true,
|
||||||
number: true,
|
number: true,
|
||||||
minNumber: 1,
|
minNumber: 1,
|
||||||
special: true,
|
special: false,
|
||||||
minSpecial: 1,
|
minSpecial: 0,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const DefaultOptions: PasswordGeneratorOptions = {
|
|||||||
lowercase: true,
|
lowercase: true,
|
||||||
minLowercase: 0,
|
minLowercase: 0,
|
||||||
special: false,
|
special: false,
|
||||||
minSpecial: 1,
|
minSpecial: 0,
|
||||||
type: "password",
|
type: "password",
|
||||||
numWords: 3,
|
numWords: 3,
|
||||||
wordSeparator: "-",
|
wordSeparator: "-",
|
||||||
|
|||||||
Reference in New Issue
Block a user