From e318ac0ddf5eba8c5824d8818d5104ea19759939 Mon Sep 17 00:00:00 2001 From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> Date: Wed, 29 May 2024 23:58:04 +0200 Subject: [PATCH] [PM-2516][PM-8298] Add password protected export on browser/Export managed collection (#9284) * Move/replace submit and userVerification logic from web into the BaseExportComponent Add "@bitwarden/auth" as dependency to the vault-export-ui package New submit logic also checks for password-encrypted exports which will be need for future UI updates on browser and desktop * Create export-browser component using shared recipe - Create new export component that uses the shared export.component from @bitwarden/vault-export-ui * Update imports within AppModule * Switch to route to the new component * Add missing entries to messages.json * Delete old export.component * Remove duplicate verifyUser-method * Change placeholder example * Add documentation to protected members of ExportBrowserComponent --------- Co-authored-by: Daniel James Smith --- apps/browser/src/_locales/en/messages.json | 39 ++++++++++++++ apps/browser/src/popup/app-routing.module.ts | 4 +- apps/browser/src/popup/app.module.ts | 4 -- .../popup/settings/export.component.html | 35 ------------ .../tools/popup/settings/export.component.ts | 54 ------------------- .../export/export-browser.component.html | 26 +++++++++ .../export/export-browser.component.ts | 40 ++++++++++++++ 7 files changed, 107 insertions(+), 95 deletions(-) delete mode 100644 apps/browser/src/tools/popup/settings/export.component.html delete mode 100644 apps/browser/src/tools/popup/settings/export.component.ts create mode 100644 apps/browser/src/tools/popup/settings/export/export-browser.component.html create mode 100644 apps/browser/src/tools/popup/settings/export/export-browser.component.ts diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index bb672ea61d..8d0f6fe31e 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -799,12 +799,39 @@ "message": "Solarized dark", "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." }, + "exportFrom": { + "message": "Export from" + }, "exportVault": { "message": "Export vault" }, "fileFormat": { "message": "File format" }, + "fileEncryptedExportWarningDesc": { + "message": "This file export will be password protected and require the file password to decrypt." + }, + "filePassword": { + "message": "File password" + }, + "exportPasswordDescription": { + "message": "This password will be used to export and import this file" + }, + "accountRestrictedOptionDescription": { + "message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account." + }, + "passwordProtectedOptionDescription": { + "message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption." + }, + "exportTypeHeading": { + "message": "Export type" + }, + "accountRestricted": { + "message": "Account restricted" + }, + "filePasswordAndConfirmFilePasswordDoNotMatch": { + "message": "“File password” and “Confirm file password“ do not match." + }, "warning": { "message": "WARNING", "description": "WARNING (should stay in capitalized letters if the language permits)" @@ -2182,6 +2209,18 @@ } } }, + "exportingOrganizationVaultTitle": { + "message": "Exporting organization vault" + }, + "exportingOrganizationVaultDesc": { + "message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.", + "placeholders": { + "organization": { + "content": "$1", + "example": "ACME Moving Co." + } + } + }, "error": { "message": "Error" }, diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts index a84d343c31..9e0377a2f9 100644 --- a/apps/browser/src/popup/app-routing.module.ts +++ b/apps/browser/src/popup/app-routing.module.ts @@ -40,7 +40,7 @@ import { AboutPageV2Component } from "../tools/popup/settings/about-page/about-p import { AboutPageComponent } from "../tools/popup/settings/about-page/about-page.component"; import { MoreFromBitwardenPageV2Component } from "../tools/popup/settings/about-page/more-from-bitwarden-page-v2.component"; import { MoreFromBitwardenPageComponent } from "../tools/popup/settings/about-page/more-from-bitwarden-page.component"; -import { ExportComponent } from "../tools/popup/settings/export.component"; +import { ExportBrowserComponent } from "../tools/popup/settings/export/export-browser.component"; import { ImportBrowserV2Component } from "../tools/popup/settings/import/import-browser-v2.component"; import { ImportBrowserComponent } from "../tools/popup/settings/import/import-browser.component"; import { SettingsV2Component } from "../tools/popup/settings/settings-v2.component"; @@ -246,7 +246,7 @@ const routes: Routes = [ }), { path: "export", - component: ExportComponent, + component: ExportBrowserComponent, canActivate: [AuthGuard], data: { state: "export" }, }, diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index 54a9da028f..e16c33de3a 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -16,7 +16,6 @@ import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password- import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe"; import { UserVerificationDialogComponent } from "@bitwarden/auth/angular"; import { AvatarModule, ButtonModule, ToastModule } from "@bitwarden/components"; -import { ExportScopeCalloutComponent } from "@bitwarden/vault-export-ui"; import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component"; import { AccountComponent } from "../auth/popup/account-switching/account.component"; @@ -55,7 +54,6 @@ import { SendListComponent } from "../tools/popup/send/components/send-list.comp import { SendAddEditComponent } from "../tools/popup/send/send-add-edit.component"; import { SendGroupingsComponent } from "../tools/popup/send/send-groupings.component"; import { SendTypeComponent } from "../tools/popup/send/send-type.component"; -import { ExportComponent } from "../tools/popup/settings/export.component"; import { SettingsComponent } from "../tools/popup/settings/settings.component"; import { ActionButtonsComponent } from "../vault/popup/components/action-buttons.component"; import { CipherRowComponent } from "../vault/popup/components/cipher-row.component"; @@ -116,7 +114,6 @@ import "../platform/popup/locales"; AvatarModule, AccountComponent, ButtonModule, - ExportScopeCalloutComponent, PopOutComponent, PopupPageComponent, PopupTabNavigationComponent, @@ -140,7 +137,6 @@ import "../platform/popup/locales"; CurrentTabComponent, EnvironmentComponent, ExcludedDomainsComponent, - ExportComponent, Fido2CipherRowComponent, Fido2UseBrowserLinkComponent, FolderAddEditComponent, diff --git a/apps/browser/src/tools/popup/settings/export.component.html b/apps/browser/src/tools/popup/settings/export.component.html deleted file mode 100644 index ef031b7979..0000000000 --- a/apps/browser/src/tools/popup/settings/export.component.html +++ /dev/null @@ -1,35 +0,0 @@ -
-
-
- -
-

- {{ "exportVault" | i18n }} -

-
- -
-
-
- - {{ "personalVaultExportPolicyInEffect" | i18n }} - - - -
-
-
- - -
-
-
-
-
diff --git a/apps/browser/src/tools/popup/settings/export.component.ts b/apps/browser/src/tools/popup/settings/export.component.ts deleted file mode 100644 index 9f3f054d2a..0000000000 --- a/apps/browser/src/tools/popup/settings/export.component.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Component } from "@angular/core"; -import { UntypedFormBuilder } from "@angular/forms"; -import { Router } from "@angular/router"; - -import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; -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 { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; -import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { DialogService } from "@bitwarden/components"; -import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core"; -import { ExportComponent as BaseExportComponent } from "@bitwarden/vault-export-ui"; - -@Component({ - selector: "app-export", - templateUrl: "export.component.html", -}) -export class ExportComponent extends BaseExportComponent { - constructor( - i18nService: I18nService, - platformUtilsService: PlatformUtilsService, - exportService: VaultExportServiceAbstraction, - eventCollectionService: EventCollectionService, - policyService: PolicyService, - private router: Router, - logService: LogService, - formBuilder: UntypedFormBuilder, - fileDownloadService: FileDownloadService, - dialogService: DialogService, - organizationService: OrganizationService, - ) { - super( - i18nService, - platformUtilsService, - exportService, - eventCollectionService, - policyService, - logService, - formBuilder, - fileDownloadService, - dialogService, - organizationService, - ); - } - - protected saved() { - super.saved(); - // 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 - this.router.navigate(["/tabs/settings"]); - } -} diff --git a/apps/browser/src/tools/popup/settings/export/export-browser.component.html b/apps/browser/src/tools/popup/settings/export/export-browser.component.html new file mode 100644 index 0000000000..bccde32a68 --- /dev/null +++ b/apps/browser/src/tools/popup/settings/export/export-browser.component.html @@ -0,0 +1,26 @@ +
+
+ +
+

+ {{ "exportVault" | i18n }} +

+
+ +
+
+
+
+ +
+
diff --git a/apps/browser/src/tools/popup/settings/export/export-browser.component.ts b/apps/browser/src/tools/popup/settings/export/export-browser.component.ts new file mode 100644 index 0000000000..3125e0a293 --- /dev/null +++ b/apps/browser/src/tools/popup/settings/export/export-browser.component.ts @@ -0,0 +1,40 @@ +import { CommonModule } from "@angular/common"; +import { Component } from "@angular/core"; +import { Router, RouterLink } from "@angular/router"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AsyncActionsModule, ButtonModule, DialogModule } from "@bitwarden/components"; +import { ExportComponent } from "@bitwarden/vault-export-ui"; + +@Component({ + templateUrl: "export-browser.component.html", + standalone: true, + imports: [ + CommonModule, + RouterLink, + JslibModule, + DialogModule, + AsyncActionsModule, + ButtonModule, + ExportComponent, + ], +}) +export class ExportBrowserComponent { + /** + * Used to control the disabled state of the Submit button + * Gets set indirectly by the disabled state being emitted from the sub-form when thier form gets disabled or the submit button is clicked + */ + protected disabled = false; + + /** + * Used to control the disabled state of the Submit button + * Gets set indirectly by the loading state being emitted from the sub-form when their form is loading or finished loading + */ + protected loading = false; + + constructor(private router: Router) {} + + protected async onSuccessfulExport(organizationId: string): Promise { + await this.router.navigate(["/vault-settings"]); + } +}