-
diff --git a/apps/desktop/src/auth/two-factor-v1.component.ts b/apps/desktop/src/auth/two-factor-v1.component.ts
deleted file mode 100644
index 13c7d0a452b..00000000000
--- a/apps/desktop/src/auth/two-factor-v1.component.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Component, Inject, NgZone, OnDestroy, ViewChild, ViewContainerRef } from "@angular/core";
-import { ActivatedRoute, Router } from "@angular/router";
-import { firstValueFrom } from "rxjs";
-
-import { TwoFactorComponentV1 as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor-v1.component";
-import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
-import {
- LoginStrategyServiceAbstraction,
- LoginEmailServiceAbstraction,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
-import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
-import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.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 { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
-import { ToastService } from "@bitwarden/components";
-
-import { TwoFactorOptionsComponentV1 } from "./two-factor-options-v1.component";
-
-const BroadcasterSubscriptionId = "TwoFactorComponent";
-
-@Component({
- selector: "app-two-factor",
- templateUrl: "two-factor-v1.component.html",
-})
-export class TwoFactorComponentV1 extends BaseTwoFactorComponent implements OnDestroy {
- @ViewChild("twoFactorOptions", { read: ViewContainerRef, static: true })
- twoFactorOptionsModal: ViewContainerRef;
-
- showingModal = false;
- duoCallbackSubscriptionEnabled: boolean = false;
-
- constructor(
- loginStrategyService: LoginStrategyServiceAbstraction,
- router: Router,
- i18nService: I18nService,
- apiService: ApiService,
- platformUtilsService: PlatformUtilsService,
- syncService: SyncService,
- environmentService: EnvironmentService,
- private broadcasterService: BroadcasterService,
- private modalService: ModalService,
- stateService: StateService,
- private ngZone: NgZone,
- route: ActivatedRoute,
- logService: LogService,
- twoFactorService: TwoFactorService,
- appIdService: AppIdService,
- loginEmailService: LoginEmailServiceAbstraction,
- userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
- ssoLoginService: SsoLoginServiceAbstraction,
- configService: ConfigService,
- masterPasswordService: InternalMasterPasswordServiceAbstraction,
- accountService: AccountService,
- toastService: ToastService,
- @Inject(WINDOW) protected win: Window,
- ) {
- super(
- loginStrategyService,
- router,
- i18nService,
- apiService,
- platformUtilsService,
- win,
- environmentService,
- stateService,
- route,
- logService,
- twoFactorService,
- appIdService,
- loginEmailService,
- userDecryptionOptionsService,
- ssoLoginService,
- configService,
- masterPasswordService,
- accountService,
- toastService,
- );
- this.onSuccessfulLogin = async () => {
- // 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
- syncService.fullSync(true);
- };
-
- this.onSuccessfulLoginTde = async () => {
- // 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
- syncService.fullSync(true);
- };
- }
-
- async anotherMethod() {
- const [modal, childComponent] = await this.modalService.openViewRef(
- TwoFactorOptionsComponentV1,
- this.twoFactorOptionsModal,
- );
-
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil
- modal.onShown.subscribe(() => {
- this.showingModal = true;
- });
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil
- modal.onClosed.subscribe(() => {
- this.showingModal = false;
- });
-
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
- childComponent.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => {
- modal.close();
- this.selectedProviderType = provider;
- await this.init();
- });
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil
- childComponent.onRecoverSelected.subscribe(() => {
- modal.close();
- });
- }
-
- async submit() {
- await super.submit();
- if (this.captchaSiteKey) {
- const content = document.getElementById("content") as HTMLDivElement;
- content.setAttribute("style", "width:335px");
- }
- }
-
- protected override setupDuoResultListener() {
- if (!this.duoCallbackSubscriptionEnabled) {
- this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
- await this.ngZone.run(async () => {
- if (message.command === "duoCallback") {
- this.token = message.code + "|" + message.state;
- await this.submit();
- }
- });
- });
- this.duoCallbackSubscriptionEnabled = true;
- }
- }
-
- override async launchDuoFrameless() {
- if (this.duoFramelessUrl === null) {
- this.toastService.showToast({
- variant: "error",
- title: null,
- message: this.i18nService.t("duoHealthCheckResultsInNullAuthUrlError"),
- });
- return;
- }
-
- const duoHandOffMessage = {
- title: this.i18nService.t("youSuccessfullyLoggedIn"),
- message: this.i18nService.t("youMayCloseThisWindow"),
- isCountdown: false,
- };
-
- // we're using the connector here as a way to set a cookie with translations
- // before continuing to the duo frameless url
- const env = await firstValueFrom(this.environmentService.environment$);
- const launchUrl =
- env.getWebVaultUrl() +
- "/duo-redirect-connector.html" +
- "?duoFramelessUrl=" +
- encodeURIComponent(this.duoFramelessUrl) +
- "&handOffMessage=" +
- encodeURIComponent(JSON.stringify(duoHandOffMessage));
- this.platformUtilsService.launchUri(launchUrl);
- }
-
- ngOnDestroy(): void {
- if (this.duoCallbackSubscriptionEnabled) {
- this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
- this.duoCallbackSubscriptionEnabled = false;
- }
- }
-}
diff --git a/apps/desktop/src/locales/af/messages.json b/apps/desktop/src/locales/af/messages.json
index ae324eda6bc..e288e9e70cc 100644
--- a/apps/desktop/src/locales/af/messages.json
+++ b/apps/desktop/src/locales/af/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/ar/messages.json b/apps/desktop/src/locales/ar/messages.json
index 9f5b1f3501c..7de8ecb50f5 100644
--- a/apps/desktop/src/locales/ar/messages.json
+++ b/apps/desktop/src/locales/ar/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "تصدير خزانة المؤسسة"
},
diff --git a/apps/desktop/src/locales/az/messages.json b/apps/desktop/src/locales/az/messages.json
index b7c7cb3cd67..738944f1791 100644
--- a/apps/desktop/src/locales/az/messages.json
+++ b/apps/desktop/src/locales/az/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Yalnız $EMAIL$ ilə əlaqələndirilmiş qoşmalar daxil olmaqla fərdi anbar elementləri xaricə köçürüləcək. Təşkilat anbar elementləri daxil edilməyəcək",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Təşkilat seyfini xaricə köçürmə"
},
diff --git a/apps/desktop/src/locales/be/messages.json b/apps/desktop/src/locales/be/messages.json
index 4c90222be42..ef73dcb3ed3 100644
--- a/apps/desktop/src/locales/be/messages.json
+++ b/apps/desktop/src/locales/be/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/bg/messages.json b/apps/desktop/src/locales/bg/messages.json
index 6a1c0983278..c9bae830eff 100644
--- a/apps/desktop/src/locales/bg/messages.json
+++ b/apps/desktop/src/locales/bg/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Ще бъдат изнесени само записите и прикачените файлове от личния трезор свързан с $EMAIL$. Записите в трезора на организацията няма да бъдат включени.",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Изнасяне на трезора на организацията"
},
diff --git a/apps/desktop/src/locales/bn/messages.json b/apps/desktop/src/locales/bn/messages.json
index 68848c9ef2a..440462cf5d3 100644
--- a/apps/desktop/src/locales/bn/messages.json
+++ b/apps/desktop/src/locales/bn/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/bs/messages.json b/apps/desktop/src/locales/bs/messages.json
index 885af404f95..4fb9697a2c9 100644
--- a/apps/desktop/src/locales/bs/messages.json
+++ b/apps/desktop/src/locales/bs/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/ca/messages.json b/apps/desktop/src/locales/ca/messages.json
index 5707fd0c0ff..dbba24a9050 100644
--- a/apps/desktop/src/locales/ca/messages.json
+++ b/apps/desktop/src/locales/ca/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "S'està exportant la caixa forta de l’organització"
},
diff --git a/apps/desktop/src/locales/cs/messages.json b/apps/desktop/src/locales/cs/messages.json
index 336ea2a795c..c4d61da936b 100644
--- a/apps/desktop/src/locales/cs/messages.json
+++ b/apps/desktop/src/locales/cs/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Budou exportovány jen osobní položky trezoru včetně příloh spojené s účtem $EMAIL$. Nebudou zahrnuty položky trezoru v organizaci.",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exportování trezoru organizace"
},
diff --git a/apps/desktop/src/locales/cy/messages.json b/apps/desktop/src/locales/cy/messages.json
index 1c6d824c22e..5f06fd762f4 100644
--- a/apps/desktop/src/locales/cy/messages.json
+++ b/apps/desktop/src/locales/cy/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/da/messages.json b/apps/desktop/src/locales/da/messages.json
index ef5b22e33f4..e11aef18e14 100644
--- a/apps/desktop/src/locales/da/messages.json
+++ b/apps/desktop/src/locales/da/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Eksport af organisationsboks"
},
diff --git a/apps/desktop/src/locales/de/messages.json b/apps/desktop/src/locales/de/messages.json
index 79f61475ab0..b28c2fced1d 100644
--- a/apps/desktop/src/locales/de/messages.json
+++ b/apps/desktop/src/locales/de/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Tresor der Organisation wird exportiert"
},
diff --git a/apps/desktop/src/locales/el/messages.json b/apps/desktop/src/locales/el/messages.json
index ecee8bd9894..9c59be2e0a7 100644
--- a/apps/desktop/src/locales/el/messages.json
+++ b/apps/desktop/src/locales/el/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Εξαγωγή θησαυ/κίου οργανισμού"
},
diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json
index 07404b37fcd..42eebd98223 100644
--- a/apps/desktop/src/locales/en/messages.json
+++ b/apps/desktop/src/locales/en/messages.json
@@ -833,18 +833,6 @@
"continue": {
"message": "Continue"
},
- "enterVerificationCodeApp": {
- "message": "Enter the 6 digit verification code from your authenticator app."
- },
- "enterVerificationCodeEmail": {
- "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.",
- "placeholders": {
- "email": {
- "content": "$1",
- "example": "example@gmail.com"
- }
- }
- },
"verificationCodeEmailSent": {
"message": "Verification email sent to $EMAIL$.",
"placeholders": {
@@ -854,18 +842,9 @@
}
}
},
- "rememberMe": {
- "message": "Remember me"
- },
"dontAskAgainOnThisDeviceFor30Days": {
"message": "Don't ask again on this device for 30 days"
},
- "sendVerificationCodeEmailAgain": {
- "message": "Send verification code email again"
- },
- "useAnotherTwoStepMethod": {
- "message": "Use another two-step login method"
- },
"selectAnotherMethod": {
"message": "Select another method",
"description": "Select another two-step login method"
@@ -873,9 +852,6 @@
"useYourRecoveryCode": {
"message": "Use your recovery code"
},
- "insertYubiKey": {
- "message": "Insert your YubiKey into your computer's USB port, then touch its button."
- },
"insertU2f": {
"message": "Insert your security key into your computer's USB port. If it has a button, touch it."
},
@@ -3224,9 +3200,6 @@
"duoHealthCheckResultsInNullAuthUrlError": {
"message": "Error connecting with the Duo service. Use a different two-step login method or contact Duo for assistance."
},
- "launchDuoAndFollowStepsToFinishLoggingIn": {
- "message": "Launch Duo and follow the steps to finish logging in."
- },
"duoRequiredByOrgForAccount": {
"message": "Duo two-step login is required for your account."
},
diff --git a/apps/desktop/src/locales/en_GB/messages.json b/apps/desktop/src/locales/en_GB/messages.json
index f70a70e975a..74e43b24076 100644
--- a/apps/desktop/src/locales/en_GB/messages.json
+++ b/apps/desktop/src/locales/en_GB/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organisation vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organisation vault"
},
diff --git a/apps/desktop/src/locales/en_IN/messages.json b/apps/desktop/src/locales/en_IN/messages.json
index f91a7b21876..3ec9e17769b 100644
--- a/apps/desktop/src/locales/en_IN/messages.json
+++ b/apps/desktop/src/locales/en_IN/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organisation vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organisation vault"
},
diff --git a/apps/desktop/src/locales/eo/messages.json b/apps/desktop/src/locales/eo/messages.json
index 200c3f4a1de..2dfdcdd9484 100644
--- a/apps/desktop/src/locales/eo/messages.json
+++ b/apps/desktop/src/locales/eo/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/es/messages.json b/apps/desktop/src/locales/es/messages.json
index 665721beb3a..6936753ebb2 100644
--- a/apps/desktop/src/locales/es/messages.json
+++ b/apps/desktop/src/locales/es/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exportando caja fuerte de la organización"
},
diff --git a/apps/desktop/src/locales/et/messages.json b/apps/desktop/src/locales/et/messages.json
index c4ca9bef886..20650145478 100644
--- a/apps/desktop/src/locales/et/messages.json
+++ b/apps/desktop/src/locales/et/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Ekspordin organisatsiooni hoidlat"
},
diff --git a/apps/desktop/src/locales/eu/messages.json b/apps/desktop/src/locales/eu/messages.json
index 1abc24612ca..57763cc62c1 100644
--- a/apps/desktop/src/locales/eu/messages.json
+++ b/apps/desktop/src/locales/eu/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/fa/messages.json b/apps/desktop/src/locales/fa/messages.json
index 2d13b86c4a8..eecbd6dcb85 100644
--- a/apps/desktop/src/locales/fa/messages.json
+++ b/apps/desktop/src/locales/fa/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/fi/messages.json b/apps/desktop/src/locales/fi/messages.json
index 2da2b7dcf7a..8964e7cf982 100644
--- a/apps/desktop/src/locales/fi/messages.json
+++ b/apps/desktop/src/locales/fi/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Organisaation holvin vienti"
},
diff --git a/apps/desktop/src/locales/fil/messages.json b/apps/desktop/src/locales/fil/messages.json
index d54c5a21a87..ec1a2d0e281 100644
--- a/apps/desktop/src/locales/fil/messages.json
+++ b/apps/desktop/src/locales/fil/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/fr/messages.json b/apps/desktop/src/locales/fr/messages.json
index 431a70ef373..750b91adf57 100644
--- a/apps/desktop/src/locales/fr/messages.json
+++ b/apps/desktop/src/locales/fr/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Export du coffre-fort de l'organisation"
},
diff --git a/apps/desktop/src/locales/gl/messages.json b/apps/desktop/src/locales/gl/messages.json
index f93db44aa69..07404b37fcd 100644
--- a/apps/desktop/src/locales/gl/messages.json
+++ b/apps/desktop/src/locales/gl/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/he/messages.json b/apps/desktop/src/locales/he/messages.json
index 7f98ab977ae..34db4dd53ba 100644
--- a/apps/desktop/src/locales/he/messages.json
+++ b/apps/desktop/src/locales/he/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "מייצא כספת ארגון"
},
diff --git a/apps/desktop/src/locales/hi/messages.json b/apps/desktop/src/locales/hi/messages.json
index 90fed49de76..7cfbb08a7d4 100644
--- a/apps/desktop/src/locales/hi/messages.json
+++ b/apps/desktop/src/locales/hi/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/hr/messages.json b/apps/desktop/src/locales/hr/messages.json
index cb66437bedd..989faae1759 100644
--- a/apps/desktop/src/locales/hr/messages.json
+++ b/apps/desktop/src/locales/hr/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Izvest će se samo stavke i privici osobnog trezora povezanog s $EMAIL$. Stavke organizacijskog trezora neće biti uključene",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Izvoz organizacijskog trezora"
},
diff --git a/apps/desktop/src/locales/hu/messages.json b/apps/desktop/src/locales/hu/messages.json
index b9573428136..775ce2dd80c 100644
--- a/apps/desktop/src/locales/hu/messages.json
+++ b/apps/desktop/src/locales/hu/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Csak $EMAIL$ email címmel társított személyes széf elemek kerülnek exportálásra. Ebbe nem kerülnek be a szervezeti széf elemek.",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Szervezeti széf exportálása"
},
diff --git a/apps/desktop/src/locales/id/messages.json b/apps/desktop/src/locales/id/messages.json
index df9b6484778..0c46ff5e5ea 100644
--- a/apps/desktop/src/locales/id/messages.json
+++ b/apps/desktop/src/locales/id/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/it/messages.json b/apps/desktop/src/locales/it/messages.json
index ef5fa5ce381..f97b3135c9f 100644
--- a/apps/desktop/src/locales/it/messages.json
+++ b/apps/desktop/src/locales/it/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Esportando cassaforte dell'organizzazione"
},
diff --git a/apps/desktop/src/locales/ja/messages.json b/apps/desktop/src/locales/ja/messages.json
index e8ba0e8509b..58c4d866e42 100644
--- a/apps/desktop/src/locales/ja/messages.json
+++ b/apps/desktop/src/locales/ja/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "$EMAIL$ に関連付けられた個人用保管庫のアイテムのみが、添付ファイルを含めてエクスポートされます。組織用保管庫のアイテムは含まれません。",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "組織保管庫のエクスポート"
},
@@ -3539,7 +3548,7 @@
"message": "後で再通知"
},
"newDeviceVerificationNoticePageOneFormContent": {
- "message": "新しいメールアドレス $EMAIL$ はあなたが管理しているものですか?",
+ "message": "メールアドレス $EMAIL$ は、確実にアクセスできるものですか?",
"placeholders": {
"email": {
"content": "$1",
diff --git a/apps/desktop/src/locales/ka/messages.json b/apps/desktop/src/locales/ka/messages.json
index 96962e14ff5..3eb666c7d44 100644
--- a/apps/desktop/src/locales/ka/messages.json
+++ b/apps/desktop/src/locales/ka/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/km/messages.json b/apps/desktop/src/locales/km/messages.json
index f93db44aa69..07404b37fcd 100644
--- a/apps/desktop/src/locales/km/messages.json
+++ b/apps/desktop/src/locales/km/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/kn/messages.json b/apps/desktop/src/locales/kn/messages.json
index f9bb154b66e..c530ab799f7 100644
--- a/apps/desktop/src/locales/kn/messages.json
+++ b/apps/desktop/src/locales/kn/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/ko/messages.json b/apps/desktop/src/locales/ko/messages.json
index 44bc681f205..e5df2555531 100644
--- a/apps/desktop/src/locales/ko/messages.json
+++ b/apps/desktop/src/locales/ko/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/lt/messages.json b/apps/desktop/src/locales/lt/messages.json
index 40436c7ccda..7cf1bc463b3 100644
--- a/apps/desktop/src/locales/lt/messages.json
+++ b/apps/desktop/src/locales/lt/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/lv/messages.json b/apps/desktop/src/locales/lv/messages.json
index c519987fc72..b3fa396d811 100644
--- a/apps/desktop/src/locales/lv/messages.json
+++ b/apps/desktop/src/locales/lv/messages.json
@@ -1706,7 +1706,7 @@
"message": "Apstiprināt glabātavas satura izgūšanu"
},
"exportWarningDesc": {
- "message": "Šī izguve satur glabātavas datus nešifrētā veidā. Izdoto datni nevajadzētu glabāt vai sūtīt nedrošos veidos (piemēram, e-pastā). Tā ir jāizdzēš uzreiz pēc izmantošanas."
+ "message": "Šī izguve satur glabātavas datus nešifrētā veidā. Izgūto datni nevajadzētu glabāt vai sūtīt nedrošos veidos (piemēram, e-pastā). Tā ir jāizdzēš uzreiz pēc izmantošanas."
},
"encExportKeyWarningDesc": {
"message": "Šī izguve šifrē datus ar konta šifrēšanas atslēgu. Ja tā jebkad tiks mainīta, izvadi vajadzētu veikt vēlreiz, jo vairs nebūs iespējams atšifrēt šo datni."
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Tiks izdoti tikai atsevišķi glabātavas vienumi, tajā skaitā pielikumi, kas ir saistīti ar $EMAIL$. Apvienības glabātavas vienumi netiks iekļauti",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Izgūst apvienības glabātavu"
},
diff --git a/apps/desktop/src/locales/me/messages.json b/apps/desktop/src/locales/me/messages.json
index ea8defdc07c..99944c6e10c 100644
--- a/apps/desktop/src/locales/me/messages.json
+++ b/apps/desktop/src/locales/me/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/ml/messages.json b/apps/desktop/src/locales/ml/messages.json
index a4af9251191..79d36b99526 100644
--- a/apps/desktop/src/locales/ml/messages.json
+++ b/apps/desktop/src/locales/ml/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/mr/messages.json b/apps/desktop/src/locales/mr/messages.json
index f93db44aa69..07404b37fcd 100644
--- a/apps/desktop/src/locales/mr/messages.json
+++ b/apps/desktop/src/locales/mr/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/my/messages.json b/apps/desktop/src/locales/my/messages.json
index 493d6fdb5b9..8aa0327203b 100644
--- a/apps/desktop/src/locales/my/messages.json
+++ b/apps/desktop/src/locales/my/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/nb/messages.json b/apps/desktop/src/locales/nb/messages.json
index caf4d3da64b..d96eb92efb2 100644
--- a/apps/desktop/src/locales/nb/messages.json
+++ b/apps/desktop/src/locales/nb/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/ne/messages.json b/apps/desktop/src/locales/ne/messages.json
index 297708953df..79aa89aed90 100644
--- a/apps/desktop/src/locales/ne/messages.json
+++ b/apps/desktop/src/locales/ne/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/nl/messages.json b/apps/desktop/src/locales/nl/messages.json
index 1cfd5ff5523..29dddbf0f08 100644
--- a/apps/desktop/src/locales/nl/messages.json
+++ b/apps/desktop/src/locales/nl/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Exporteert alleen de persoonlijke kluis-items, inclusief attachments, gerelateerd aan $EMAIL$. Geen kluis-items van de organisatie",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Organisatiekluis exporteren"
},
diff --git a/apps/desktop/src/locales/nn/messages.json b/apps/desktop/src/locales/nn/messages.json
index 9195311cc67..753b3ba5524 100644
--- a/apps/desktop/src/locales/nn/messages.json
+++ b/apps/desktop/src/locales/nn/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/or/messages.json b/apps/desktop/src/locales/or/messages.json
index 6f15ed21991..b5c3d4eab46 100644
--- a/apps/desktop/src/locales/or/messages.json
+++ b/apps/desktop/src/locales/or/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/pl/messages.json b/apps/desktop/src/locales/pl/messages.json
index ef8cdc6eb9b..a8b5205a9d9 100644
--- a/apps/desktop/src/locales/pl/messages.json
+++ b/apps/desktop/src/locales/pl/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Eksportowanie sejfu organizacji"
},
diff --git a/apps/desktop/src/locales/pt_BR/messages.json b/apps/desktop/src/locales/pt_BR/messages.json
index e09ee6e16d2..539d254344d 100644
--- a/apps/desktop/src/locales/pt_BR/messages.json
+++ b/apps/desktop/src/locales/pt_BR/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exportando cofre da organização"
},
diff --git a/apps/desktop/src/locales/pt_PT/messages.json b/apps/desktop/src/locales/pt_PT/messages.json
index 2261357ba08..28ac0c82486 100644
--- a/apps/desktop/src/locales/pt_PT/messages.json
+++ b/apps/desktop/src/locales/pt_PT/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Apenas os itens individuais do cofre, incluindo os anexos associados a $EMAIL$, serão exportados. Os itens do cofre da organização não serão incluídos",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "A exportar o cofre da organização"
},
diff --git a/apps/desktop/src/locales/ro/messages.json b/apps/desktop/src/locales/ro/messages.json
index d148d90a4fd..b160bfc14e3 100644
--- a/apps/desktop/src/locales/ro/messages.json
+++ b/apps/desktop/src/locales/ro/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/ru/messages.json b/apps/desktop/src/locales/ru/messages.json
index ea5b8c6d526..73f52200e04 100644
--- a/apps/desktop/src/locales/ru/messages.json
+++ b/apps/desktop/src/locales/ru/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Будут экспортированы только отдельные элементы хранилища, включая вложения, связанные с $EMAIL$. Элементы хранилища организации включены не будут",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Экспорт хранилища организации"
},
diff --git a/apps/desktop/src/locales/si/messages.json b/apps/desktop/src/locales/si/messages.json
index cb837ea4f76..e2f23c7bc56 100644
--- a/apps/desktop/src/locales/si/messages.json
+++ b/apps/desktop/src/locales/si/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/sk/messages.json b/apps/desktop/src/locales/sk/messages.json
index 7eaa1026c00..0f32c9945ce 100644
--- a/apps/desktop/src/locales/sk/messages.json
+++ b/apps/desktop/src/locales/sk/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Exportované budú iba položky osobného trezora spojené s $EMAIL$. Položky trezora organizácie nebudú zahrnuté v exporte",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exportovanie trezora organizácie"
},
diff --git a/apps/desktop/src/locales/sl/messages.json b/apps/desktop/src/locales/sl/messages.json
index 3987587828a..4d50b4d9def 100644
--- a/apps/desktop/src/locales/sl/messages.json
+++ b/apps/desktop/src/locales/sl/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/sr/messages.json b/apps/desktop/src/locales/sr/messages.json
index 69b45469dc8..561e3d35ec2 100644
--- a/apps/desktop/src/locales/sr/messages.json
+++ b/apps/desktop/src/locales/sr/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Извоз сефа организације"
},
diff --git a/apps/desktop/src/locales/sv/messages.json b/apps/desktop/src/locales/sv/messages.json
index 1303243a8cc..f33339ea80d 100644
--- a/apps/desktop/src/locales/sv/messages.json
+++ b/apps/desktop/src/locales/sv/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/te/messages.json b/apps/desktop/src/locales/te/messages.json
index f93db44aa69..07404b37fcd 100644
--- a/apps/desktop/src/locales/te/messages.json
+++ b/apps/desktop/src/locales/te/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/th/messages.json b/apps/desktop/src/locales/th/messages.json
index cb9df027ad7..2bec157ec15 100644
--- a/apps/desktop/src/locales/th/messages.json
+++ b/apps/desktop/src/locales/th/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
},
diff --git a/apps/desktop/src/locales/tr/messages.json b/apps/desktop/src/locales/tr/messages.json
index 55b3b6059b7..974d27f4735 100644
--- a/apps/desktop/src/locales/tr/messages.json
+++ b/apps/desktop/src/locales/tr/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Yalnızca $EMAIL$ ile ilişkili kişisel kasadaki kayıtlar ve dosyalar dışa aktarılacaktır. Kuruluş kasasındaki kayıtlar dahil edilmeyecektir",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Kuruluş kasasını dışa aktarma"
},
diff --git a/apps/desktop/src/locales/uk/messages.json b/apps/desktop/src/locales/uk/messages.json
index d5f908e011c..6fb5c564f3a 100644
--- a/apps/desktop/src/locales/uk/messages.json
+++ b/apps/desktop/src/locales/uk/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Експортування сховища організації"
},
diff --git a/apps/desktop/src/locales/vi/messages.json b/apps/desktop/src/locales/vi/messages.json
index f6495e4f915..8b5f3250b85 100644
--- a/apps/desktop/src/locales/vi/messages.json
+++ b/apps/desktop/src/locales/vi/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "Đang xuất dữ liệu kho tổ chức"
},
diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json
index 6a12138b48f..e85b2606535 100644
--- a/apps/desktop/src/locales/zh_CN/messages.json
+++ b/apps/desktop/src/locales/zh_CN/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "仅会导出与 $EMAIL$ 关联的个人密码库项目(包括附件)。不包括组织密码库项目。",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "正在导出组织密码库"
},
diff --git a/apps/desktop/src/locales/zh_TW/messages.json b/apps/desktop/src/locales/zh_TW/messages.json
index 5da6c4a0b6e..ab09790dcd0 100644
--- a/apps/desktop/src/locales/zh_TW/messages.json
+++ b/apps/desktop/src/locales/zh_TW/messages.json
@@ -2490,6 +2490,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultTitle": {
"message": "正匯出組織密碼庫"
},
diff --git a/apps/desktop/src/scss/pages.scss b/apps/desktop/src/scss/pages.scss
index b9559e13a26..ecb36aae662 100644
--- a/apps/desktop/src/scss/pages.scss
+++ b/apps/desktop/src/scss/pages.scss
@@ -27,7 +27,6 @@
#accessibility-cookie-page,
#register-page,
#hint-page,
-#two-factor-page,
#update-temp-password-page,
#remove-password-page {
padding-top: 20px;
@@ -48,7 +47,6 @@
#accessibility-cookie-page,
#register-page,
#hint-page,
-#two-factor-page,
#lock-page,
#update-temp-password-page {
.content {
diff --git a/apps/web/src/app/auth/two-factor-options-v1.component.html b/apps/web/src/app/auth/two-factor-options-v1.component.html
deleted file mode 100644
index 43c054060ea..00000000000
--- a/apps/web/src/app/auth/two-factor-options-v1.component.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
- {{ "twoStepOptions" | i18n }}
-
-
-
-
-
-
-
-
-
{{ p.name }}
-
{{ p.description }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ "recoveryCodeTitle" | i18n }}
-
{{ "recoveryCodeDesc" | i18n }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/web/src/app/auth/two-factor-options-v1.component.ts b/apps/web/src/app/auth/two-factor-options-v1.component.ts
deleted file mode 100644
index 08665dcfcdd..00000000000
--- a/apps/web/src/app/auth/two-factor-options-v1.component.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { DialogRef } from "@angular/cdk/dialog";
-import { Component } from "@angular/core";
-import { Router } from "@angular/router";
-
-import { TwoFactorOptionsComponentV1 as BaseTwoFactorOptionsComponentV1 } from "@bitwarden/angular/auth/components/two-factor-options-v1.component";
-import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
-import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { DialogService } from "@bitwarden/components";
-
-export enum TwoFactorOptionsDialogResult {
- Provider = "Provider selected",
- Recover = "Recover selected",
-}
-
-export type TwoFactorOptionsDialogResultType = {
- result: TwoFactorOptionsDialogResult;
- type: TwoFactorProviderType;
-};
-
-@Component({
- selector: "app-two-factor-options",
- templateUrl: "two-factor-options-v1.component.html",
-})
-export class TwoFactorOptionsComponentV1 extends BaseTwoFactorOptionsComponentV1 {
- constructor(
- twoFactorService: TwoFactorService,
- router: Router,
- i18nService: I18nService,
- platformUtilsService: PlatformUtilsService,
- environmentService: EnvironmentService,
- private dialogRef: DialogRef,
- ) {
- super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
- }
-
- async choose(p: any) {
- await super.choose(p);
- this.dialogRef.close({ result: TwoFactorOptionsDialogResult.Provider, type: p.type });
- }
-
- async recover() {
- await super.recover();
- this.dialogRef.close({ result: TwoFactorOptionsDialogResult.Recover });
- }
-
- static open(dialogService: DialogService) {
- return dialogService.open(TwoFactorOptionsComponentV1);
- }
-}
diff --git a/apps/web/src/app/auth/two-factor-v1.component.html b/apps/web/src/app/auth/two-factor-v1.component.html
deleted file mode 100644
index b78747e04c2..00000000000
--- a/apps/web/src/app/auth/two-factor-v1.component.html
+++ /dev/null
@@ -1,106 +0,0 @@
-
diff --git a/apps/web/src/app/auth/two-factor-v1.component.ts b/apps/web/src/app/auth/two-factor-v1.component.ts
deleted file mode 100644
index 9a9fab02de3..00000000000
--- a/apps/web/src/app/auth/two-factor-v1.component.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Component, Inject, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
-import { FormBuilder, Validators } from "@angular/forms";
-import { ActivatedRoute, Router } from "@angular/router";
-import { Subject, takeUntil, lastValueFrom } from "rxjs";
-
-import { TwoFactorComponentV1 as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor-v1.component";
-import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
-import {
- LoginStrategyServiceAbstraction,
- LoginEmailServiceAbstraction,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
-import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.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 { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { DialogService, ToastService } from "@bitwarden/components";
-
-import {
- TwoFactorOptionsDialogResult,
- TwoFactorOptionsComponentV1,
- TwoFactorOptionsDialogResultType,
-} from "./two-factor-options-v1.component";
-
-@Component({
- selector: "app-two-factor",
- templateUrl: "two-factor-v1.component.html",
-})
-export class TwoFactorComponentV1 extends BaseTwoFactorComponent implements OnInit, OnDestroy {
- @ViewChild("twoFactorOptions", { read: ViewContainerRef, static: true })
- twoFactorOptionsModal: ViewContainerRef;
- formGroup = this.formBuilder.group({
- token: [
- "",
- {
- validators: [Validators.required],
- updateOn: "submit",
- },
- ],
- remember: [false],
- });
- private destroy$ = new Subject();
- constructor(
- loginStrategyService: LoginStrategyServiceAbstraction,
- router: Router,
- i18nService: I18nService,
- apiService: ApiService,
- platformUtilsService: PlatformUtilsService,
- stateService: StateService,
- environmentService: EnvironmentService,
- private dialogService: DialogService,
- route: ActivatedRoute,
- logService: LogService,
- twoFactorService: TwoFactorService,
- appIdService: AppIdService,
- loginEmailService: LoginEmailServiceAbstraction,
- userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
- ssoLoginService: SsoLoginServiceAbstraction,
- configService: ConfigService,
- masterPasswordService: InternalMasterPasswordServiceAbstraction,
- accountService: AccountService,
- toastService: ToastService,
- private formBuilder: FormBuilder,
- @Inject(WINDOW) protected win: Window,
- ) {
- super(
- loginStrategyService,
- router,
- i18nService,
- apiService,
- platformUtilsService,
- win,
- environmentService,
- stateService,
- route,
- logService,
- twoFactorService,
- appIdService,
- loginEmailService,
- userDecryptionOptionsService,
- ssoLoginService,
- configService,
- masterPasswordService,
- accountService,
- toastService,
- );
- this.onSuccessfulLoginNavigate = this.goAfterLogIn;
- }
- async ngOnInit() {
- await super.ngOnInit();
- this.formGroup.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
- this.token = value.token;
- this.remember = value.remember;
- });
- }
- submitForm = async () => {
- await this.submit();
- };
-
- async anotherMethod() {
- const dialogRef = TwoFactorOptionsComponentV1.open(this.dialogService);
- const response: TwoFactorOptionsDialogResultType = await lastValueFrom(dialogRef.closed);
- if (response.result === TwoFactorOptionsDialogResult.Provider) {
- this.selectedProviderType = response.type;
- await this.init();
- }
- }
-
- protected override handleMigrateEncryptionKey(result: AuthResult): boolean {
- if (!result.requiresEncryptionKeyMigration) {
- return false;
- }
- // 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(["migrate-legacy-encryption"]);
- return true;
- }
-
- goAfterLogIn = async () => {
- this.loginEmailService.clearValues();
- // 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([this.successRoute], {
- queryParams: {
- identifier: this.orgIdentifier,
- },
- });
- };
-
- private duoResultChannel: BroadcastChannel;
-
- protected override setupDuoResultListener() {
- if (!this.duoResultChannel) {
- this.duoResultChannel = new BroadcastChannel("duoResult");
- this.duoResultChannel.addEventListener("message", this.handleDuoResultMessage);
- }
- }
-
- private handleDuoResultMessage = async (msg: { data: { code: string; state: string } }) => {
- this.token = msg.data.code + "|" + msg.data.state;
- await this.submit();
- };
-
- async ngOnDestroy() {
- super.ngOnDestroy();
-
- if (this.duoResultChannel) {
- // clean up duo listener if it was initialized.
- this.duoResultChannel.removeEventListener("message", this.handleDuoResultMessage);
- this.duoResultChannel.close();
- }
- }
-}
diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts
index c531f358b34..0334519516a 100644
--- a/apps/web/src/app/oss-routing.module.ts
+++ b/apps/web/src/app/oss-routing.module.ts
@@ -2,7 +2,6 @@ import { NgModule } from "@angular/core";
import { Route, RouterModule, Routes } from "@angular/router";
import { AuthenticationTimeoutComponent } from "@bitwarden/angular/auth/components/authentication-timeout.component";
-import { unauthUiRefreshSwap } from "@bitwarden/angular/auth/functions/unauth-ui-refresh-route-swap";
import {
authGuard,
lockGuard,
@@ -65,7 +64,6 @@ import { AccountComponent } from "./auth/settings/account/account.component";
import { EmergencyAccessComponent } from "./auth/settings/emergency-access/emergency-access.component";
import { EmergencyAccessViewComponent } from "./auth/settings/emergency-access/view/emergency-access-view.component";
import { SecurityRoutingModule } from "./auth/settings/security/security-routing.module";
-import { TwoFactorComponentV1 } from "./auth/two-factor-v1.component";
import { UpdatePasswordComponent } from "./auth/update-password.component";
import { UpdateTempPasswordComponent } from "./auth/update-temp-password.component";
import { VerifyEmailTokenComponent } from "./auth/verify-email-token.component";
@@ -378,51 +376,28 @@ const routes: Routes = [
},
],
},
- ...unauthUiRefreshSwap(
- TwoFactorComponentV1,
- TwoFactorAuthComponent,
- {
- path: "2fa",
- canActivate: [unauthGuardFn()],
- children: [
- {
- path: "",
- component: TwoFactorComponentV1,
- },
- {
- path: "",
- component: EnvironmentSelectorComponent,
- outlet: "environment-selector",
- },
- ],
- data: {
- pageTitle: {
- key: "verifyYourIdentity",
- },
- } satisfies RouteDataProperties & AnonLayoutWrapperData,
- },
- {
- path: "2fa",
- canActivate: [unauthGuardFn(), TwoFactorAuthGuard],
- children: [
- {
- path: "",
- component: TwoFactorAuthComponent,
- },
- {
- path: "",
- component: EnvironmentSelectorComponent,
- outlet: "environment-selector",
- },
- ],
- data: {
- pageTitle: {
- key: "verifyYourIdentity",
- },
- titleAreaMaxWidth: "md",
- } satisfies RouteDataProperties & AnonLayoutWrapperData,
- },
- ),
+ {
+ path: "2fa",
+ component: TwoFactorAuthComponent,
+ canActivate: [unauthGuardFn(), TwoFactorAuthGuard],
+ children: [
+ {
+ path: "",
+ component: TwoFactorAuthComponent,
+ },
+ {
+ path: "",
+ component: EnvironmentSelectorComponent,
+ outlet: "environment-selector",
+ },
+ ],
+ data: {
+ pageTitle: {
+ key: "verifyYourIdentity",
+ },
+ titleAreaMaxWidth: "md",
+ } satisfies RouteDataProperties & AnonLayoutWrapperData,
+ },
{
path: "lock",
canActivate: [deepLinkGuard(), lockGuard()],
diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts
index f21a9338491..70dbf63f1f8 100644
--- a/apps/web/src/app/shared/loose-components.module.ts
+++ b/apps/web/src/app/shared/loose-components.module.ts
@@ -43,8 +43,6 @@ import { TwoFactorSetupComponent } from "../auth/settings/two-factor/two-factor-
import { TwoFactorVerifyComponent } from "../auth/settings/two-factor/two-factor-verify.component";
import { UserVerificationModule } from "../auth/shared/components/user-verification";
import { SsoComponentV1 } from "../auth/sso-v1.component";
-import { TwoFactorOptionsComponentV1 } from "../auth/two-factor-options-v1.component";
-import { TwoFactorComponentV1 } from "../auth/two-factor-v1.component";
import { UpdatePasswordComponent } from "../auth/update-password.component";
import { UpdateTempPasswordComponent } from "../auth/update-temp-password.component";
import { VerifyEmailTokenComponent } from "../auth/verify-email-token.component";
@@ -148,12 +146,10 @@ import { SharedModule } from "./shared.module";
SetPasswordComponent,
SponsoredFamiliesComponent,
SponsoringOrgRowComponent,
- TwoFactorComponentV1,
SsoComponentV1,
TwoFactorSetupAuthenticatorComponent,
TwoFactorSetupDuoComponent,
TwoFactorSetupEmailComponent,
- TwoFactorOptionsComponentV1,
TwoFactorRecoveryComponent,
TwoFactorSetupComponent,
TwoFactorVerifyComponent,
@@ -210,12 +206,10 @@ import { SharedModule } from "./shared.module";
SetPasswordComponent,
SponsoredFamiliesComponent,
SponsoringOrgRowComponent,
- TwoFactorComponentV1,
SsoComponentV1,
TwoFactorSetupAuthenticatorComponent,
TwoFactorSetupDuoComponent,
TwoFactorSetupEmailComponent,
- TwoFactorOptionsComponentV1,
TwoFactorSetupComponent,
TwoFactorVerifyComponent,
TwoFactorSetupWebAuthnComponent,
diff --git a/apps/web/src/locales/af/messages.json b/apps/web/src/locales/af/messages.json
index 3b9168b29b2..fa25494f4bf 100644
--- a/apps/web/src/locales/af/messages.json
+++ b/apps/web/src/locales/af/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/ar/messages.json b/apps/web/src/locales/ar/messages.json
index 13777f942de..4a289082039 100644
--- a/apps/web/src/locales/ar/messages.json
+++ b/apps/web/src/locales/ar/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/az/messages.json b/apps/web/src/locales/az/messages.json
index f092620b00a..dfafeab1877 100644
--- a/apps/web/src/locales/az/messages.json
+++ b/apps/web/src/locales/az/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Yalnız $EMAIL$ ilə əlaqələndirilmiş qoşmalar daxil olmaqla fərdi anbar elementləri xaricə köçürüləcək. Təşkilat anbar elementləri daxil edilməyəcək",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Yalnız $ORGANIZATION$ ilə əlaqələndirilmiş təşkilat seyfi xaricə köçürüləcək. Fərdi seyfdə və digər təşkilatlardakı elementlər daxil edilməyəcək.",
"placeholders": {
diff --git a/apps/web/src/locales/be/messages.json b/apps/web/src/locales/be/messages.json
index 2e5aeabff32..a22b463f4f2 100644
--- a/apps/web/src/locales/be/messages.json
+++ b/apps/web/src/locales/be/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Толькі сховішча арганізацыі, якія звязаны з $ORGANIZATION$ будуць экспартаваны. Элементы асабістага сховішча і элементы з іншых арганізацый не будуць уключаны.",
"placeholders": {
diff --git a/apps/web/src/locales/bg/messages.json b/apps/web/src/locales/bg/messages.json
index 04d4e25bb7c..0599d3a73f2 100644
--- a/apps/web/src/locales/bg/messages.json
+++ b/apps/web/src/locales/bg/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Ще бъдат изнесени само записите и прикачените файлове от личния трезор свързан с $EMAIL$. Записите в трезора на организацията няма да бъдат включени.",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Ще бъдат изнесени само записите от трезора свързан с $ORGANIZATION$. Записите в отделните лични трезори и тези в други организации няма да бъдат включени.",
"placeholders": {
diff --git a/apps/web/src/locales/bn/messages.json b/apps/web/src/locales/bn/messages.json
index 8c082c57e30..15ca72e1642 100644
--- a/apps/web/src/locales/bn/messages.json
+++ b/apps/web/src/locales/bn/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/bs/messages.json b/apps/web/src/locales/bs/messages.json
index 7efb47bd86c..2c0f177ad67 100644
--- a/apps/web/src/locales/bs/messages.json
+++ b/apps/web/src/locales/bs/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/ca/messages.json b/apps/web/src/locales/ca/messages.json
index a4f2aeb7f55..d394a75b70f 100644
--- a/apps/web/src/locales/ca/messages.json
+++ b/apps/web/src/locales/ca/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Només s'exportarà la caixa forta de l'organització associada a $ORGANIZATION$. No s'inclouran els elements de les caixes fortes individuals ni d'altres organitzacions.",
"placeholders": {
diff --git a/apps/web/src/locales/cs/messages.json b/apps/web/src/locales/cs/messages.json
index 46b510a6459..552a717ab82 100644
--- a/apps/web/src/locales/cs/messages.json
+++ b/apps/web/src/locales/cs/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Budou exportovány jen osobní položky trezoru včetně příloh spojené s účtem $EMAIL$. Nebudou zahrnuty položky trezoru v organizaci.",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Exportován bude jen trezor organizace přidružený k položce $ORGANIZATION$. Osobní položky trezoru a položky z jiných organizací nebudou zahrnuty.",
"placeholders": {
diff --git a/apps/web/src/locales/cy/messages.json b/apps/web/src/locales/cy/messages.json
index 2fd61e01526..ba8bd6bd8a4 100644
--- a/apps/web/src/locales/cy/messages.json
+++ b/apps/web/src/locales/cy/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/da/messages.json b/apps/web/src/locales/da/messages.json
index f8a335011e5..dddef79ddd0 100644
--- a/apps/web/src/locales/da/messages.json
+++ b/apps/web/src/locales/da/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Kun organisationsboksen tilknyttet $ORGANIZATION$ eksporteres. Emner i individuelle bokse eller andre organisationer medtages ikke.",
"placeholders": {
diff --git a/apps/web/src/locales/de/messages.json b/apps/web/src/locales/de/messages.json
index 135ab8af923..b5eeb9db7ce 100644
--- a/apps/web/src/locales/de/messages.json
+++ b/apps/web/src/locales/de/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Nur der mit $ORGANIZATION$ verbundene Organisationstresor wird exportiert. Einträge in persönlichen Tresoren oder anderen Organisationen werden nicht berücksichtigt.",
"placeholders": {
diff --git a/apps/web/src/locales/el/messages.json b/apps/web/src/locales/el/messages.json
index e20b5cc52a0..27e39f9798e 100644
--- a/apps/web/src/locales/el/messages.json
+++ b/apps/web/src/locales/el/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index b9ead1df44d..4133062a047 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -1456,18 +1456,6 @@
}
}
},
- "enterVerificationCodeApp": {
- "message": "Enter the 6 digit verification code from your authenticator app."
- },
- "enterVerificationCodeEmail": {
- "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.",
- "placeholders": {
- "email": {
- "content": "$1",
- "example": "example@gmail.com"
- }
- }
- },
"verificationCodeEmailSent": {
"message": "Verification email sent to $EMAIL$.",
"placeholders": {
@@ -1477,18 +1465,10 @@
}
}
},
- "rememberMe": {
- "message": "Remember me"
- },
+
"dontAskAgainOnThisDeviceFor30Days": {
"message": "Don't ask again on this device for 30 days"
},
- "sendVerificationCodeEmailAgain": {
- "message": "Send verification code email again"
- },
- "useAnotherTwoStepMethod": {
- "message": "Use another two-step login method"
- },
"selectAnotherMethod": {
"message": "Select another method",
"description": "Select another two-step login method"
@@ -1496,9 +1476,6 @@
"useYourRecoveryCode": {
"message": "Use your recovery code"
},
- "insertYubiKey": {
- "message": "Insert your YubiKey into your computer's USB port, then touch its button."
- },
"insertU2f": {
"message": "Insert your security key into your computer's USB port. If it has a button, touch it."
},
@@ -7273,9 +7250,6 @@
"duoHealthCheckResultsInNullAuthUrlError": {
"message": "Error connecting with the Duo service. Use a different two-step login method or contact Duo for assistance."
},
- "launchDuoAndFollowStepsToFinishLoggingIn": {
- "message": "Launch Duo and follow the steps to finish logging in."
- },
"duoRequiredByOrgForAccount": {
"message": "Duo two-step login is required for your account."
},
diff --git a/apps/web/src/locales/en_GB/messages.json b/apps/web/src/locales/en_GB/messages.json
index b211ec070ab..b4f0ace607a 100644
--- a/apps/web/src/locales/en_GB/messages.json
+++ b/apps/web/src/locales/en_GB/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organisation vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organisation vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organisations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/en_IN/messages.json b/apps/web/src/locales/en_IN/messages.json
index 6b4b6e11ab3..a8c4bfca62e 100644
--- a/apps/web/src/locales/en_IN/messages.json
+++ b/apps/web/src/locales/en_IN/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organisation vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organisation vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organisations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/eo/messages.json b/apps/web/src/locales/eo/messages.json
index ce40767f4c1..c31274e6198 100644
--- a/apps/web/src/locales/eo/messages.json
+++ b/apps/web/src/locales/eo/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/es/messages.json b/apps/web/src/locales/es/messages.json
index 1c71a29f48b..80b982bd928 100644
--- a/apps/web/src/locales/es/messages.json
+++ b/apps/web/src/locales/es/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/et/messages.json b/apps/web/src/locales/et/messages.json
index f9a5b810ded..a55fce63349 100644
--- a/apps/web/src/locales/et/messages.json
+++ b/apps/web/src/locales/et/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/eu/messages.json b/apps/web/src/locales/eu/messages.json
index d0e99c73e66..a8b64594065 100644
--- a/apps/web/src/locales/eu/messages.json
+++ b/apps/web/src/locales/eu/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/fa/messages.json b/apps/web/src/locales/fa/messages.json
index 04cddc65f2f..4657d4a9732 100644
--- a/apps/web/src/locales/fa/messages.json
+++ b/apps/web/src/locales/fa/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "فقط گاوصدوق سازمان مرتبط با $ORGANIZATION$ برون ریزی خواهد شد. موارد موجود در گاوصندوقهای فردی یا سایر سازمانها شامل نمیشوند.",
"placeholders": {
diff --git a/apps/web/src/locales/fi/messages.json b/apps/web/src/locales/fi/messages.json
index 9427a4e8e22..38671c12f79 100644
--- a/apps/web/src/locales/fi/messages.json
+++ b/apps/web/src/locales/fi/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Vain organisaatioon $ORGANIZATION$ liitetyn holvin kohteet viedään. Yksityisen holvin ja muiden organisaatioiden kohteita ei sisällytetä.",
"placeholders": {
diff --git a/apps/web/src/locales/fil/messages.json b/apps/web/src/locales/fil/messages.json
index 414bbda91d8..0a07cf17526 100644
--- a/apps/web/src/locales/fil/messages.json
+++ b/apps/web/src/locales/fil/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/fr/messages.json b/apps/web/src/locales/fr/messages.json
index 95aa573f14b..e26b5ef1250 100644
--- a/apps/web/src/locales/fr/messages.json
+++ b/apps/web/src/locales/fr/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Seuls les éléments individuels du coffre et les pièces jointes associées à $EMAIL$ seront exportés. Les éléments du coffre de l'organisation ne seront pas inclus",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Seul le coffre d'organisation associé à $ORGANIZATION$ sera exporté. Les éléments dans les coffres individuels ou d'autres organisations ne seront pas inclus.",
"placeholders": {
diff --git a/apps/web/src/locales/gl/messages.json b/apps/web/src/locales/gl/messages.json
index 38a94f9307f..6964a867768 100644
--- a/apps/web/src/locales/gl/messages.json
+++ b/apps/web/src/locales/gl/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/he/messages.json b/apps/web/src/locales/he/messages.json
index 4df39c8496f..115482c021b 100644
--- a/apps/web/src/locales/he/messages.json
+++ b/apps/web/src/locales/he/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "רק כספת הארגון המשויכת עם $ORGANIZATION$ תיוצא. פריטים בכספת אישית או ארגונים אחרים לא יכללו.",
"placeholders": {
diff --git a/apps/web/src/locales/hi/messages.json b/apps/web/src/locales/hi/messages.json
index 1cab0dc843b..bdd11c6561f 100644
--- a/apps/web/src/locales/hi/messages.json
+++ b/apps/web/src/locales/hi/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/hr/messages.json b/apps/web/src/locales/hr/messages.json
index 65c42a0cbf0..5ae2ddcfc0b 100644
--- a/apps/web/src/locales/hr/messages.json
+++ b/apps/web/src/locales/hr/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Izvest će se samo stavke i privici osobnog trezora povezanog s $EMAIL$. Stavke organizacijskog trezora neće biti uključene",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Izvest će se samo organizacijski trezor povezan s $ORGANIZATION$. Stavke iz osobnih trezora i stavke iz drugih organizacija neće biti uključene.",
"placeholders": {
diff --git a/apps/web/src/locales/hu/messages.json b/apps/web/src/locales/hu/messages.json
index 3d6a2e258a4..b7a51e5048b 100644
--- a/apps/web/src/locales/hu/messages.json
+++ b/apps/web/src/locales/hu/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Csak $EMAIL$ email címmel társított személyes széf elemek kerülnek exportálásra. Ebbe nem kerülnek be a szervezeti széf elemek.",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Csak$ORGANIZATION$ névvel társított szervezeti széf elemek kerülnek exportálásra. Ebbe nem kerülnek be a személyes és más szervezeti széf elemek.",
"placeholders": {
diff --git a/apps/web/src/locales/id/messages.json b/apps/web/src/locales/id/messages.json
index 22b4e3a6132..dc3ba77328f 100644
--- a/apps/web/src/locales/id/messages.json
+++ b/apps/web/src/locales/id/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/it/messages.json b/apps/web/src/locales/it/messages.json
index 0cbc425d588..853c580c82d 100644
--- a/apps/web/src/locales/it/messages.json
+++ b/apps/web/src/locales/it/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Solo la cassaforte dell'organizzazione associata a $ORGANIZATION$ sarà esportata. Elementi nelle casseforti individuali o in altre organizzazioni non saranno inclusi.",
"placeholders": {
diff --git a/apps/web/src/locales/ja/messages.json b/apps/web/src/locales/ja/messages.json
index 6860b30b360..d445184774c 100644
--- a/apps/web/src/locales/ja/messages.json
+++ b/apps/web/src/locales/ja/messages.json
@@ -474,7 +474,7 @@
"message": "フォルダーを編集"
},
"editWithName": {
- "message": "Edit $ITEM$: $NAME$",
+ "message": "$ITEM$: $NAME$ を編集",
"placeholders": {
"item": {
"content": "$1",
@@ -1202,7 +1202,7 @@
"message": "デバイスとは何ですか?"
},
"aDeviceIs": {
- "message": "A device is a unique installation of the Bitwarden app where you have logged in. Reinstalling, clearing app data, or clearing your cookies could result in a device appearing multiple times."
+ "message": "デバイスとは、あなたがログインしている Bitwarden アプリの一意なインストールです。 再インストールや、アプリデータの消去、 Cookie の消去をすると、同じデバイスが複数回表示される場合があります。"
},
"logInInitiated": {
"message": "ログイン開始"
@@ -1894,22 +1894,22 @@
"message": "新しいデバイスからのログイン"
},
"turnOffNewDeviceLoginProtection": {
- "message": "Turn off new device login protection"
+ "message": "新しいデバイスからのログイン保護をオフにする"
},
"turnOnNewDeviceLoginProtection": {
- "message": "Turn on new device login protection"
+ "message": "新しいデバイスからのログイン保護をオンにする"
},
"turnOffNewDeviceLoginProtectionModalDesc": {
- "message": "Proceed below to turn off the verification emails bitwarden sends when you login from a new device."
+ "message": "続行すると、新しいデバイスからログインしたときに Bitwarden が送信する認証メールをオフにします。"
},
"turnOnNewDeviceLoginProtectionModalDesc": {
- "message": "Proceed below to have bitwarden send you verification emails when you login from a new device."
+ "message": "続行すると、新しいデバイスからログインする際に Bitwarden から認証メールを送信します。"
},
"turnOffNewDeviceLoginProtectionWarning": {
- "message": "With new device login protection turned off, anyone with your master password can access your account from any device. To protect your account without verification emails, set up two-step login."
+ "message": "新しいデバイスからのログイン保護をオフにすると、マスターパスワードを持つ人は誰でも、どのデバイスからでもあなたのアカウントにアクセスできます。認証メールなしでアカウントを保護するには、2段階認証によるログインを設定してください。"
},
"accountNewDeviceLoginProtectionSaved": {
- "message": "New device login protection changes saved"
+ "message": "新しいデバイスからのログイン保護の変更が保存されました"
},
"sessionsDeauthorized": {
"message": "全てのセッションを無効化"
@@ -2175,7 +2175,7 @@
"message": "2段階認証を有効にすると Bitwarden アカウントから永久に閉め出されてしまうことがあります。リカバリーコードがあれば、通常の2段階認証プロバイダを使えなくなったとき (デバイスの紛失等) でもアカウントにアクセスできます。アカウントにアクセスできなくなっても Bitwarden はサポート出来ないため、リカバリーコードを書き出すか印刷し安全な場所で保管しておくことを推奨します。"
},
"yourSingleUseRecoveryCode": {
- "message": "Your single-use recovery code can be used to turn off two-step login in the event that you lose access to your two-step login provider. Bitwarden recommends you write down the recovery code and keep it in a safe place."
+ "message": "2段階認証プロバイダーへのアクセスを失った場合は、使い捨てのリカバリーコードを使用して2段階認証をオフにできます。 Bitwarden では、リカバリーコードを書き留めて安全な場所に保管することをお勧めしています。"
},
"viewRecoveryCode": {
"message": "リカバリーコードを確認"
@@ -2216,7 +2216,7 @@
"message": "管理"
},
"manageCollection": {
- "message": "Manage collection"
+ "message": "コレクションの管理"
},
"viewItems": {
"message": "アイテムを表示"
@@ -2429,7 +2429,7 @@
"message": "セキュリティキーの読み取り中に問題が発生しました。もう一度やり直して下さい。"
},
"twoFactorWebAuthnWarning1": {
- "message": "Due to platform limitations, WebAuthn cannot be used on all Bitwarden applications. You should set up another two-step login provider so that you can access your account when WebAuthn cannot be used."
+ "message": "プラットフォームの制限により、 WebAuthn は全ての Bitwarden アプリケーションで使用できるわけではありません。 WebAuthn が使用できない場合に備えて、他の2段階認証プロバイダーを設定しておくことをおすすめします。"
},
"twoFactorRecoveryYourCode": {
"message": "二段階認証のリカバリーコード"
@@ -3396,10 +3396,10 @@
}
},
"inviteSingleEmailDesc": {
- "message": "You have 1 invite remaining."
+ "message": "招待は残り 1 個です。"
},
"inviteZeroEmailDesc": {
- "message": "You have 0 invites remaining."
+ "message": "招待は残り 0 個です。"
},
"userUsingTwoStep": {
"message": "このユーザーはアカウントを保護するため二段階認証を利用しています。"
@@ -3853,7 +3853,7 @@
}
},
"unlinkedSso": {
- "message": "Unlinked SSO."
+ "message": "SSO のリンクを解除しました。"
},
"unlinkedSsoUser": {
"message": "ユーザー $ID$ にリンクされていない SSO",
@@ -3904,22 +3904,22 @@
"message": "デバイス"
},
"loginStatus": {
- "message": "Login status"
+ "message": "ログイン状態"
},
"firstLogin": {
- "message": "First login"
+ "message": "初回ログイン"
},
"trusted": {
- "message": "Trusted"
+ "message": "信頼済み"
},
"needsApproval": {
- "message": "Needs approval"
+ "message": "承認が必要"
},
"areYouTryingtoLogin": {
- "message": "Are you trying to log in?"
+ "message": "ログインしようとしていますか?"
},
"logInAttemptBy": {
- "message": "Login attempt by $EMAIL$",
+ "message": "$EMAIL$ によるログインの試行",
"placeholders": {
"email": {
"content": "$1",
@@ -3928,7 +3928,7 @@
}
},
"deviceType": {
- "message": "Device Type"
+ "message": "デバイスタイプ"
},
"ipAddress": {
"message": "IP アドレス"
@@ -3965,7 +3965,7 @@
"message": "たった今"
},
"requestedXMinutesAgo": {
- "message": "Requested $MINUTES$ minutes ago",
+ "message": "$MINUTES$ 分前に要求されました",
"placeholders": {
"minutes": {
"content": "$1",
@@ -4097,10 +4097,10 @@
"message": "サポートされていないブラウザを使用しています。ウェブ保管庫が正しく動作しないかもしれません。"
},
"youHaveAPendingLoginRequest": {
- "message": "You have a pending login request from another device."
+ "message": "別のデバイスからの保留中のログインリクエストがあります。"
},
"reviewLoginRequest": {
- "message": "Review login request"
+ "message": "ログインリクエストの内容を確認"
},
"freeTrialEndPromptCount": {
"message": "無料体験はあと $COUNT$ 日で終了します。",
@@ -4197,7 +4197,7 @@
"message": "もし通常の二段階認証の方法でアカウントにアクセスできなくなった場合、リカバリーコードにより全ての二段階認証プロバイダを無効化することができます。"
},
"logInBelowUsingYourSingleUseRecoveryCode": {
- "message": "Log in below using your single-use recovery code. This will turn off all two-step providers on your account."
+ "message": "使い捨てのリカバリーコードを使用して以下からログインしてください。これにより、アカウントのすべての2段階認証プロバイダーが無効になります。"
},
"recoverAccountTwoStep": {
"message": "二段階認証ログインの回復"
@@ -4509,7 +4509,7 @@
}
},
"reorderFieldUp": {
- "message": "$LABEL$ moved up, position $INDEX$ of $LENGTH$",
+ "message": "$LABEL$ を上に移動しました。$INDEX$ / $LENGTH$",
"placeholders": {
"label": {
"content": "$1",
@@ -4526,7 +4526,7 @@
}
},
"reorderFieldDown": {
- "message": "$LABEL$ moved down, position $INDEX$ of $LENGTH$",
+ "message": "$LABEL$ を下に移動しました。$INDEX$ / $LENGTH$",
"placeholders": {
"label": {
"content": "$1",
@@ -4814,7 +4814,7 @@
"message": "マスターパスワードの強度に最低要件を設定する。"
},
"passwordStrengthScore": {
- "message": "Password strength score $SCORE$",
+ "message": "パスワードの強度スコア $SCORE$",
"placeholders": {
"score": {
"content": "$1",
@@ -5103,14 +5103,14 @@
"message": "組織の所有者および管理者は、このポリシーの執行から除外されます。"
},
"limitSendViews": {
- "message": "Limit views"
+ "message": "表示の制限"
},
"limitSendViewsHint": {
- "message": "No one can view this Send after the limit is reached.",
+ "message": "上限に達すると、誰もこの Send を表示できなくなります。",
"description": "Displayed under the limit views field on Send"
},
"limitSendViewsCount": {
- "message": "$ACCESSCOUNT$ views left",
+ "message": "残り $ACCESSCOUNT$ 回",
"description": "Displayed under the limit views field on Send",
"placeholders": {
"accessCount": {
@@ -5120,11 +5120,11 @@
}
},
"sendDetails": {
- "message": "Send details",
+ "message": "Send の詳細",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendTypeTextToShare": {
- "message": "Text to share"
+ "message": "共有するテキスト"
},
"sendTypeFile": {
"message": "ファイル"
@@ -5133,7 +5133,7 @@
"message": "テキスト"
},
"sendPasswordDescV3": {
- "message": "Add an optional password for recipients to access this Send.",
+ "message": "必要に応じて、受信者がこの Send にアクセスするためのパスワードを追加します。",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"createSend": {
@@ -5161,14 +5161,14 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"deleteSendPermanentConfirmation": {
- "message": "Are you sure you want to permanently delete this Send?",
+ "message": "この Send を完全に削除してもよろしいですか?",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"deletionDate": {
"message": "削除日時"
},
"deletionDateDescV2": {
- "message": "The Send will be permanently deleted on this date.",
+ "message": "この Send はこの期間ののち、完全に削除されます。",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"expirationDate": {
@@ -5218,7 +5218,7 @@
"message": "保留中の削除"
},
"hideTextByDefault": {
- "message": "Hide text by default"
+ "message": "デフォルトでテキストを隠す"
},
"expired": {
"message": "期限切れ"
@@ -5689,7 +5689,7 @@
"message": "削除と有効期限の保存中にエラーが発生しました。"
},
"hideYourEmail": {
- "message": "Hide your email address from viewers."
+ "message": "閲覧者にメールアドレスを見せないようにします。"
},
"webAuthnFallbackMsg": {
"message": "二段階認証を確認するには、下のボタンをクリックしてください。"
@@ -5698,10 +5698,10 @@
"message": "WebAuthn の認証"
},
"readSecurityKey": {
- "message": "Read security key"
+ "message": "セキュリティキーの読み取り"
},
"awaitingSecurityKeyInteraction": {
- "message": "Awaiting security key interaction..."
+ "message": "セキュリティキーとの通信を待ち受け中…"
},
"webAuthnNotSupported": {
"message": "WebAuthn はこのブラウザではサポートされていません。"
@@ -5917,17 +5917,17 @@
"message": "エラー"
},
"decryptionError": {
- "message": "Decryption error"
+ "message": "復号エラー"
},
"couldNotDecryptVaultItemsBelow": {
- "message": "Bitwarden could not decrypt the vault item(s) listed below."
+ "message": "Bitwarden は以下の保管庫のアイテムを復号できませんでした。"
},
"contactCSToAvoidDataLossPart1": {
- "message": "Contact customer success",
+ "message": "カスタマーサクセスに問い合わせて、",
"description": "This is part of a larger sentence. The full sentence will read 'Contact customer success to avoid additional data loss.'"
},
"contactCSToAvoidDataLossPart2": {
- "message": "to avoid additional data loss.",
+ "message": "さらなるデータ損失を回避してください。",
"description": "This is part of a larger sentence. The full sentence will read 'Contact customer success to avoid additional data loss.'"
},
"accountRecoveryManageUsers": {
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "$EMAIL$ に関連付けられた個人用保管庫のアイテムのみが、添付ファイルを含めてエクスポートされます。組織用保管庫のアイテムは含まれません。",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "$ORGANIZATION$ に関連付けられた組織保管庫のみがエクスポートされます。個々の保管庫または他の組織にあるアイテムは含まれません。",
"placeholders": {
@@ -6845,7 +6854,7 @@
"message": "ドメインに設定されたキャッチオール受信トレイを使用します。"
},
"useThisEmail": {
- "message": "Use this email"
+ "message": "このメールアドレスを使う"
},
"random": {
"message": "ランダム",
@@ -6997,7 +7006,7 @@
}
},
"forwaderInvalidOperation": {
- "message": "$SERVICENAME$ refused your request. Please contact your service provider for assistance.",
+ "message": "$SERVICENAME$ はリクエストを拒否しました。サービスプロバイダーにお問い合わせください。",
"description": "Displayed when the user is forbidden from using the API by the forwarding service.",
"placeholders": {
"servicename": {
@@ -7007,7 +7016,7 @@
}
},
"forwaderInvalidOperationWithMessage": {
- "message": "$SERVICENAME$ refused your request: $ERRORMESSAGE$",
+ "message": "$SERVICENAME$ があなたのリクエストを拒否しました: $ERRORMESSAGE$",
"description": "Displayed when the user is forbidden from using the API by the forwarding service with an error message.",
"placeholders": {
"servicename": {
@@ -10159,7 +10168,7 @@
}
},
"userLeftOrganization": {
- "message": "User $ID$ left organization",
+ "message": "ユーザー $ID$ が組織から脱退しました",
"placeholders": {
"id": {
"content": "$1",
@@ -10168,7 +10177,7 @@
}
},
"suspendedOrganizationTitle": {
- "message": "The $ORGANIZATION$ is suspended",
+ "message": "$ORGANIZATION$ は一時停止されています",
"placeholders": {
"organization": {
"content": "$1",
@@ -10177,25 +10186,25 @@
}
},
"suspendedUserOrgMessage": {
- "message": "Contact your organization owner for assistance."
+ "message": "組織の所有者にお問い合わせください。"
},
"suspendedOwnerOrgMessage": {
- "message": "To regain access to your organization, add a payment method."
+ "message": "組織へのアクセスを取り戻すには、支払い方法を追加してください。"
},
"deleteMembers": {
- "message": "Delete members"
+ "message": "メンバーを削除"
},
"noSelectedMembersApplicable": {
- "message": "This action is not applicable to any of the selected members."
+ "message": "この操作は、選択されたメンバーには適用できません。"
},
"deletedSuccessfully": {
- "message": "Deleted successfully"
+ "message": "正常に削除されました"
},
"freeFamiliesSponsorship": {
- "message": "Remove Free Bitwarden Families sponsorship"
+ "message": "Bitwarden ファミリープランの無償利用へのスポンサーを解除"
},
"freeFamiliesSponsorshipPolicyDesc": {
- "message": "Do not allow members to redeem a Families plan through this organization."
+ "message": "メンバーがこの組織を通じてファミリープランを引き換えられないようにします。"
},
"verifyBankAccountWithStatementDescriptorWarning": {
"message": "Payment with a bank account is only available to customers in the United States. You will be required to verify your bank account. We will make a micro-deposit within the next 1-2 business days. Enter the statement descriptor code from this deposit on the organization's billing page to verify the bank account. Failure to verify the bank account will result in a missed payment and your subscription being suspended."
@@ -10545,6 +10554,6 @@
"message": "These events are examples only and do not reflect real events within your Bitwarden organization."
},
"cannotCreateCollection": {
- "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections."
+ "message": "無料版の組織ではコレクションは 2 つまでです。さらにコレクションを追加するには有料プランにアップグレードしてください。"
}
}
diff --git a/apps/web/src/locales/ka/messages.json b/apps/web/src/locales/ka/messages.json
index f5f4bfb3ae1..5ace08617ff 100644
--- a/apps/web/src/locales/ka/messages.json
+++ b/apps/web/src/locales/ka/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/km/messages.json b/apps/web/src/locales/km/messages.json
index f334131b69b..59eac9b372b 100644
--- a/apps/web/src/locales/km/messages.json
+++ b/apps/web/src/locales/km/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/kn/messages.json b/apps/web/src/locales/kn/messages.json
index dbf2cab3bb5..8132c9a2db5 100644
--- a/apps/web/src/locales/kn/messages.json
+++ b/apps/web/src/locales/kn/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/ko/messages.json b/apps/web/src/locales/ko/messages.json
index 1f3bbda3736..6e59f0ccf88 100644
--- a/apps/web/src/locales/ko/messages.json
+++ b/apps/web/src/locales/ko/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "$ORGANIZATION$ 조직과 연관된 조직 보관함만 내보내기됩니다. 개인 보관함이나 다른 조직의 항목은 포함되지 않습니다.",
"placeholders": {
diff --git a/apps/web/src/locales/lv/messages.json b/apps/web/src/locales/lv/messages.json
index 7c8c3b2831e..e59f6078bf5 100644
--- a/apps/web/src/locales/lv/messages.json
+++ b/apps/web/src/locales/lv/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Tiks izdoti tikai atsevišķi glabātavas vienumi, tajā skaitā pielikumi, kas ir saistīti ar $EMAIL$. Apvienības glabātavas vienumi netiks iekļauti",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Tiks izgūta tikai apvienības glabātava, kas ir saistīta ar $ORGANIZATION$. Atsevišķu glabātavu vai citu apvienību vienumi netiks iekļauti.",
"placeholders": {
diff --git a/apps/web/src/locales/ml/messages.json b/apps/web/src/locales/ml/messages.json
index 46ce3b62533..10ae27a2139 100644
--- a/apps/web/src/locales/ml/messages.json
+++ b/apps/web/src/locales/ml/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/mr/messages.json b/apps/web/src/locales/mr/messages.json
index f334131b69b..59eac9b372b 100644
--- a/apps/web/src/locales/mr/messages.json
+++ b/apps/web/src/locales/mr/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/my/messages.json b/apps/web/src/locales/my/messages.json
index f334131b69b..59eac9b372b 100644
--- a/apps/web/src/locales/my/messages.json
+++ b/apps/web/src/locales/my/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/nb/messages.json b/apps/web/src/locales/nb/messages.json
index 24285b8cb9f..bc36ba82ff1 100644
--- a/apps/web/src/locales/nb/messages.json
+++ b/apps/web/src/locales/nb/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/ne/messages.json b/apps/web/src/locales/ne/messages.json
index 8183efd5f9b..c947c0bb716 100644
--- a/apps/web/src/locales/ne/messages.json
+++ b/apps/web/src/locales/ne/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/nl/messages.json b/apps/web/src/locales/nl/messages.json
index 6b752b5a195..1bc731e3ceb 100644
--- a/apps/web/src/locales/nl/messages.json
+++ b/apps/web/src/locales/nl/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Exporteert alleen de persoonlijke kluis-items, inclusief attachments, gerelateerd aan $EMAIL$. Geen kluis-items van de organisatie",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Exporteert alleen de organisatiekluis van $ORGANIZATION$. Geen persoonlijke kluis-items of items van andere organisaties.",
"placeholders": {
diff --git a/apps/web/src/locales/nn/messages.json b/apps/web/src/locales/nn/messages.json
index 23d4d3b3089..ae64568bd79 100644
--- a/apps/web/src/locales/nn/messages.json
+++ b/apps/web/src/locales/nn/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/or/messages.json b/apps/web/src/locales/or/messages.json
index f334131b69b..59eac9b372b 100644
--- a/apps/web/src/locales/or/messages.json
+++ b/apps/web/src/locales/or/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/pl/messages.json b/apps/web/src/locales/pl/messages.json
index 9ef5c95bf86..f793b249148 100644
--- a/apps/web/src/locales/pl/messages.json
+++ b/apps/web/src/locales/pl/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Tylko poszczególne elementy sejfu łącznie z załącznikami powiązanymi z $EMAIL$ zostaną wyeksportowane. Elementy sejfu organizacji nie będą dołączone",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Tylko sejf organizacji powiązany z $ORGANIZATION$ zostanie wyeksportowany. Pozycje w poszczególnych sejfach lub innych organizacji nie będą uwzględnione.",
"placeholders": {
diff --git a/apps/web/src/locales/pt_BR/messages.json b/apps/web/src/locales/pt_BR/messages.json
index ea43fd4eae6..3ac5afa3110 100644
--- a/apps/web/src/locales/pt_BR/messages.json
+++ b/apps/web/src/locales/pt_BR/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Apenas o cofre da organização associado com $ORGANIZATION$ será exportado. Itens do cofre pessoal e itens de outras organizações não serão incluídos.",
"placeholders": {
diff --git a/apps/web/src/locales/pt_PT/messages.json b/apps/web/src/locales/pt_PT/messages.json
index 9bbda05c93f..1cd3f9c9b1b 100644
--- a/apps/web/src/locales/pt_PT/messages.json
+++ b/apps/web/src/locales/pt_PT/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Apenas os itens individuais do cofre, incluindo os anexos associados a $EMAIL$, serão exportados. Os itens do cofre da organização não serão incluídos",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Apenas o cofre da organização associado a $ORGANIZATION$ será exportado. Os itens em cofres individuais ou noutras organizações não serão incluídos.",
"placeholders": {
diff --git a/apps/web/src/locales/ro/messages.json b/apps/web/src/locales/ro/messages.json
index c57ad26d251..f67c9550655 100644
--- a/apps/web/src/locales/ro/messages.json
+++ b/apps/web/src/locales/ro/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/ru/messages.json b/apps/web/src/locales/ru/messages.json
index a31d13d227e..2bdaeb63206 100644
--- a/apps/web/src/locales/ru/messages.json
+++ b/apps/web/src/locales/ru/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Будут экспортированы только отдельные элементы хранилища, включая вложения, связанные с $EMAIL$. Элементы хранилища организации включены не будут",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Будет экспортировано только хранилище организации, связанное с $ORGANIZATION$. Элементы из личных хранилищ и из других организаций включены не будут.",
"placeholders": {
diff --git a/apps/web/src/locales/si/messages.json b/apps/web/src/locales/si/messages.json
index fc79da1352b..bbb01d1aa49 100644
--- a/apps/web/src/locales/si/messages.json
+++ b/apps/web/src/locales/si/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/sk/messages.json b/apps/web/src/locales/sk/messages.json
index fdf57456a4c..339a73bbffb 100644
--- a/apps/web/src/locales/sk/messages.json
+++ b/apps/web/src/locales/sk/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Exportované budú iba položy osobného trezora spojené s $EMAIL$. Položky trezora organizácie nebudú zahrnuté v exporte",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Exportované budú iba položky trezora organizácie spojené s $ORGANIZATION$. Položky osobného trezora a položky z iných organizácií nebudú zahrnuté.",
"placeholders": {
diff --git a/apps/web/src/locales/sl/messages.json b/apps/web/src/locales/sl/messages.json
index 1652841b650..d14b4f13ecc 100644
--- a/apps/web/src/locales/sl/messages.json
+++ b/apps/web/src/locales/sl/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/sr/messages.json b/apps/web/src/locales/sr/messages.json
index 005fa7602b5..2ac4a713189 100644
--- a/apps/web/src/locales/sr/messages.json
+++ b/apps/web/src/locales/sr/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Биће извезен само сеф организације повезан са $ORGANIZATION$. Ставке у појединачним сефовима или другим организацијама неће бити укључене.",
"placeholders": {
diff --git a/apps/web/src/locales/sr_CS/messages.json b/apps/web/src/locales/sr_CS/messages.json
index d141d8301fc..d84f3192dea 100644
--- a/apps/web/src/locales/sr_CS/messages.json
+++ b/apps/web/src/locales/sr_CS/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/sv/messages.json b/apps/web/src/locales/sv/messages.json
index f7d6414c36c..e4cc2cdeb67 100644
--- a/apps/web/src/locales/sv/messages.json
+++ b/apps/web/src/locales/sv/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/te/messages.json b/apps/web/src/locales/te/messages.json
index f334131b69b..59eac9b372b 100644
--- a/apps/web/src/locales/te/messages.json
+++ b/apps/web/src/locales/te/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/th/messages.json b/apps/web/src/locales/th/messages.json
index 7d2685807b3..3b05ffc9000 100644
--- a/apps/web/src/locales/th/messages.json
+++ b/apps/web/src/locales/th/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/tr/messages.json b/apps/web/src/locales/tr/messages.json
index 030fd0dd9b2..ef8701ce4b1 100644
--- a/apps/web/src/locales/tr/messages.json
+++ b/apps/web/src/locales/tr/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Yalnızca $EMAIL$ ile ilişkili kişisel kasadaki kayıtlar ve dosyalar dışa aktarılacaktır. Kuruluş kasasındaki kayıtlar dahil edilmeyecektir",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/uk/messages.json b/apps/web/src/locales/uk/messages.json
index 7d9eb316821..e175fe99db8 100644
--- a/apps/web/src/locales/uk/messages.json
+++ b/apps/web/src/locales/uk/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Буде експортовано лише сховище організації, пов'язане з $ORGANIZATION$. Записи особистих сховищ або інших організацій не будуть включені.",
"placeholders": {
diff --git a/apps/web/src/locales/vi/messages.json b/apps/web/src/locales/vi/messages.json
index f0a0215f823..f7e8f9f4037 100644
--- a/apps/web/src/locales/vi/messages.json
+++ b/apps/web/src/locales/vi/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"placeholders": {
diff --git a/apps/web/src/locales/zh_CN/messages.json b/apps/web/src/locales/zh_CN/messages.json
index 00bf9bc5973..6bb79aa1971 100644
--- a/apps/web/src/locales/zh_CN/messages.json
+++ b/apps/web/src/locales/zh_CN/messages.json
@@ -2958,7 +2958,7 @@
"description": "Past tense status of an invoice. ex. Paid or unpaid."
},
"unpaid": {
- "message": "待支付",
+ "message": "未支付",
"description": "Past tense status of an invoice. ex. Paid or unpaid."
},
"transactions": {
@@ -4799,7 +4799,7 @@
"message": "您必须至少选择一个集合。"
},
"couldNotChargeCardPayInvoice": {
- "message": "我们无法从您的支付卡中扣款。请查看并支付下面列出的待支付账单。"
+ "message": "我们无法从您的支付卡中扣款。请查看并支付下面列出的未支付账单。"
},
"minLength": {
"message": "最小长度"
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "仅会导出与 $EMAIL$ 关联的个人密码库项目(包括附件)。不包括组织密码库项目。",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "仅会导出与 $ORGANIZATION$ 关联的组织密码库数据。不包括个人密码库和其他组织中的项目。",
"placeholders": {
diff --git a/apps/web/src/locales/zh_TW/messages.json b/apps/web/src/locales/zh_TW/messages.json
index beca8f74485..c23def1464d 100644
--- a/apps/web/src/locales/zh_TW/messages.json
+++ b/apps/web/src/locales/zh_TW/messages.json
@@ -6741,6 +6741,15 @@
}
}
},
+ "exportingIndividualVaultWithAttachmentsDescription": {
+ "message": "Only the individual vault items including attachments associated with $EMAIL$ will be exported. Organization vault items will not be included",
+ "placeholders": {
+ "email": {
+ "content": "$1",
+ "example": "name@example.com"
+ }
+ }
+ },
"exportingOrganizationVaultDesc": {
"message": "僅匯出與 $ORGANIZATION$ 相關的組織密碼庫項目。個人密碼庫項目或其他組織中的項目將不包括在内。",
"placeholders": {
diff --git a/libs/angular/src/auth/components/two-factor-options-v1.component.ts b/libs/angular/src/auth/components/two-factor-options-v1.component.ts
deleted file mode 100644
index f02eabcc156..00000000000
--- a/libs/angular/src/auth/components/two-factor-options-v1.component.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { Directive, EventEmitter, OnInit, Output } from "@angular/core";
-import { Router } from "@angular/router";
-import { firstValueFrom } from "rxjs";
-
-import {
- TwoFactorProviderDetails,
- TwoFactorService,
-} from "@bitwarden/common/auth/abstractions/two-factor.service";
-import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-
-@Directive()
-export class TwoFactorOptionsComponentV1 implements OnInit {
- @Output() onProviderSelected = new EventEmitter();
- @Output() onRecoverSelected = new EventEmitter();
-
- providers: any[] = [];
-
- constructor(
- protected twoFactorService: TwoFactorService,
- protected router: Router,
- protected i18nService: I18nService,
- protected platformUtilsService: PlatformUtilsService,
- protected win: Window,
- protected environmentService: EnvironmentService,
- ) {}
-
- async ngOnInit() {
- this.providers = await this.twoFactorService.getSupportedProviders(this.win);
- }
-
- async choose(p: TwoFactorProviderDetails) {
- this.onProviderSelected.emit(p.type);
- }
-
- async recover() {
- const env = await firstValueFrom(this.environmentService.environment$);
- const webVault = env.getWebVaultUrl();
- this.platformUtilsService.launchUri(webVault + "/#/recover-2fa");
- this.onRecoverSelected.emit();
- }
-}
diff --git a/libs/angular/src/auth/components/two-factor-v1.component.spec.ts b/libs/angular/src/auth/components/two-factor-v1.component.spec.ts
deleted file mode 100644
index 47075acc758..00000000000
--- a/libs/angular/src/auth/components/two-factor-v1.component.spec.ts
+++ /dev/null
@@ -1,505 +0,0 @@
-import { Component } from "@angular/core";
-import { ComponentFixture, TestBed } from "@angular/core/testing";
-import { ActivatedRoute, convertToParamMap, Router } from "@angular/router";
-import { mock, MockProxy } from "jest-mock-extended";
-import { BehaviorSubject } from "rxjs";
-
-import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
-import {
- LoginStrategyServiceAbstraction,
- LoginEmailServiceAbstraction,
- FakeKeyConnectorUserDecryptionOption as KeyConnectorUserDecryptionOption,
- FakeTrustedDeviceUserDecryptionOption as TrustedDeviceUserDecryptionOption,
- FakeUserDecryptionOptions as UserDecryptionOptions,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
-import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
-import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
-import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { FakeMasterPasswordService } from "@bitwarden/common/key-management/master-password/services/fake-master-password.service";
-import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.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 { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
-import { UserId } from "@bitwarden/common/types/guid";
-import { ToastService } from "@bitwarden/components";
-
-import { TwoFactorComponentV1 } from "./two-factor-v1.component";
-
-// test component that extends the TwoFactorComponent
-@Component({})
-class TestTwoFactorComponent extends TwoFactorComponentV1 {}
-
-interface TwoFactorComponentProtected {
- trustedDeviceEncRoute: string;
- changePasswordRoute: string;
- forcePasswordResetRoute: string;
- successRoute: string;
-}
-
-describe("TwoFactorComponent", () => {
- let component: TestTwoFactorComponent;
- let _component: TwoFactorComponentProtected;
-
- let fixture: ComponentFixture;
- const userId = "userId" as UserId;
-
- // Mock Services
- let mockLoginStrategyService: MockProxy;
- let mockRouter: MockProxy;
- let mockI18nService: MockProxy;
- let mockApiService: MockProxy;
- let mockPlatformUtilsService: MockProxy;
- let mockWin: MockProxy;
- let mockEnvironmentService: MockProxy;
- let mockStateService: MockProxy;
- let mockLogService: MockProxy;
- let mockTwoFactorService: MockProxy;
- let mockAppIdService: MockProxy;
- let mockLoginEmailService: MockProxy;
- let mockUserDecryptionOptionsService: MockProxy;
- let mockSsoLoginService: MockProxy;
- let mockConfigService: MockProxy;
- let mockMasterPasswordService: FakeMasterPasswordService;
- let mockAccountService: FakeAccountService;
- let mockToastService: MockProxy;
-
- let mockUserDecryptionOpts: {
- noMasterPassword: UserDecryptionOptions;
- withMasterPassword: UserDecryptionOptions;
- withMasterPasswordAndTrustedDevice: UserDecryptionOptions;
- withMasterPasswordAndTrustedDeviceWithManageResetPassword: UserDecryptionOptions;
- withMasterPasswordAndKeyConnector: UserDecryptionOptions;
- noMasterPasswordWithTrustedDevice: UserDecryptionOptions;
- noMasterPasswordWithTrustedDeviceWithManageResetPassword: UserDecryptionOptions;
- noMasterPasswordWithKeyConnector: UserDecryptionOptions;
- };
-
- let selectedUserDecryptionOptions: BehaviorSubject;
- let authenticationSessionTimeoutSubject: BehaviorSubject;
-
- beforeEach(() => {
- authenticationSessionTimeoutSubject = new BehaviorSubject(false);
- mockLoginStrategyService = mock();
- mockLoginStrategyService.authenticationSessionTimeout$ = authenticationSessionTimeoutSubject;
- mockRouter = mock();
- mockI18nService = mock();
- mockApiService = mock();
- mockPlatformUtilsService = mock();
- mockWin = mock();
- mockEnvironmentService = mock();
- mockStateService = mock();
- mockLogService = mock();
- mockTwoFactorService = mock();
- mockAppIdService = mock();
- mockLoginEmailService = mock();
- mockUserDecryptionOptionsService = mock();
- mockSsoLoginService = mock();
- mockConfigService = mock();
- mockAccountService = mockAccountServiceWith(userId);
- mockToastService = mock();
- mockMasterPasswordService = new FakeMasterPasswordService();
-
- mockUserDecryptionOpts = {
- noMasterPassword: new UserDecryptionOptions({
- hasMasterPassword: false,
- trustedDeviceOption: undefined,
- keyConnectorOption: undefined,
- }),
- withMasterPassword: new UserDecryptionOptions({
- hasMasterPassword: true,
- trustedDeviceOption: undefined,
- keyConnectorOption: undefined,
- }),
- withMasterPasswordAndTrustedDevice: new UserDecryptionOptions({
- hasMasterPassword: true,
- trustedDeviceOption: new TrustedDeviceUserDecryptionOption(true, false, false, false),
- keyConnectorOption: undefined,
- }),
- withMasterPasswordAndTrustedDeviceWithManageResetPassword: new UserDecryptionOptions({
- hasMasterPassword: true,
- trustedDeviceOption: new TrustedDeviceUserDecryptionOption(true, false, true, false),
- keyConnectorOption: undefined,
- }),
- withMasterPasswordAndKeyConnector: new UserDecryptionOptions({
- hasMasterPassword: true,
- trustedDeviceOption: undefined,
- keyConnectorOption: new KeyConnectorUserDecryptionOption("http://example.com"),
- }),
- noMasterPasswordWithTrustedDevice: new UserDecryptionOptions({
- hasMasterPassword: false,
- trustedDeviceOption: new TrustedDeviceUserDecryptionOption(true, false, false, false),
- keyConnectorOption: undefined,
- }),
- noMasterPasswordWithTrustedDeviceWithManageResetPassword: new UserDecryptionOptions({
- hasMasterPassword: false,
- trustedDeviceOption: new TrustedDeviceUserDecryptionOption(true, false, true, false),
- keyConnectorOption: undefined,
- }),
- noMasterPasswordWithKeyConnector: new UserDecryptionOptions({
- hasMasterPassword: false,
- trustedDeviceOption: undefined,
- keyConnectorOption: new KeyConnectorUserDecryptionOption("http://example.com"),
- }),
- };
-
- selectedUserDecryptionOptions = new BehaviorSubject(
- mockUserDecryptionOpts.withMasterPassword,
- );
- mockUserDecryptionOptionsService.userDecryptionOptions$ = selectedUserDecryptionOptions;
-
- TestBed.configureTestingModule({
- declarations: [TestTwoFactorComponent],
- providers: [
- { provide: LoginStrategyServiceAbstraction, useValue: mockLoginStrategyService },
- { provide: Router, useValue: mockRouter },
- { provide: I18nService, useValue: mockI18nService },
- { provide: ApiService, useValue: mockApiService },
- { provide: PlatformUtilsService, useValue: mockPlatformUtilsService },
- { provide: WINDOW, useValue: mockWin },
- { provide: EnvironmentService, useValue: mockEnvironmentService },
- { provide: StateService, useValue: mockStateService },
- {
- provide: ActivatedRoute,
- useValue: {
- snapshot: {
- // Default to standard 2FA flow - not SSO + 2FA
- queryParamMap: convertToParamMap({ sso: "false" }),
- },
- },
- },
- { provide: LogService, useValue: mockLogService },
- { provide: TwoFactorService, useValue: mockTwoFactorService },
- { provide: AppIdService, useValue: mockAppIdService },
- { provide: LoginEmailServiceAbstraction, useValue: mockLoginEmailService },
- {
- provide: UserDecryptionOptionsServiceAbstraction,
- useValue: mockUserDecryptionOptionsService,
- },
- { provide: SsoLoginServiceAbstraction, useValue: mockSsoLoginService },
- { provide: ConfigService, useValue: mockConfigService },
- { provide: InternalMasterPasswordServiceAbstraction, useValue: mockMasterPasswordService },
- { provide: AccountService, useValue: mockAccountService },
- { provide: ToastService, useValue: mockToastService },
- ],
- });
-
- fixture = TestBed.createComponent(TestTwoFactorComponent);
- component = fixture.componentInstance;
- _component = component as any;
- });
-
- afterEach(() => {
- // Reset all mocks after each test
- jest.resetAllMocks();
- });
-
- it("should create", () => {
- expect(component).toBeTruthy();
- });
-
- // Shared tests
- const testChangePasswordOnSuccessfulLogin = () => {
- it("navigates to the component's defined change password route when user doesn't have a MP and key connector isn't enabled", async () => {
- // Act
- await component.doSubmit();
-
- // Assert
- expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
- expect(mockRouter.navigate).toHaveBeenCalledWith([_component.changePasswordRoute], {
- queryParams: {
- identifier: component.orgIdentifier,
- },
- });
- });
- };
-
- const testForceResetOnSuccessfulLogin = (reasonString: string) => {
- it(`navigates to the component's defined forcePasswordResetRoute route when response.forcePasswordReset is ${reasonString}`, async () => {
- // Act
- await component.doSubmit();
-
- // expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
- expect(mockRouter.navigate).toHaveBeenCalledWith([_component.forcePasswordResetRoute], {
- queryParams: {
- identifier: component.orgIdentifier,
- },
- });
- });
- };
-
- describe("Standard 2FA scenarios", () => {
- describe("doSubmit", () => {
- const token = "testToken";
- const remember = false;
- const captchaToken = "testCaptchaToken";
-
- beforeEach(() => {
- component.token = token;
- component.remember = remember;
- component.captchaToken = captchaToken;
-
- selectedUserDecryptionOptions.next(mockUserDecryptionOpts.withMasterPassword);
- });
-
- it("calls authService.logInTwoFactor with correct parameters when form is submitted", async () => {
- // Arrange
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
-
- // Act
- await component.doSubmit();
-
- // Assert
- expect(mockLoginStrategyService.logInTwoFactor).toHaveBeenCalledWith(
- new TokenTwoFactorRequest(component.selectedProviderType, token, remember),
- captchaToken,
- );
- });
-
- it("should return when handleCaptchaRequired returns true", async () => {
- // Arrange
- const captchaSiteKey = "testCaptchaSiteKey";
- const authResult = new AuthResult();
- authResult.captchaSiteKey = captchaSiteKey;
-
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
-
- // Note: the any casts are required b/c typescript cant recognize that
- // handleCaptureRequired is a method on TwoFactorComponent b/c it is inherited
- // from the CaptchaProtectedComponent
- const handleCaptchaRequiredSpy = jest
- .spyOn(component, "handleCaptchaRequired")
- .mockReturnValue(true);
-
- // Act
- const result = await component.doSubmit();
-
- // Assert
- expect(handleCaptchaRequiredSpy).toHaveBeenCalled();
- expect(result).toBeUndefined();
- });
-
- it("calls onSuccessfulLogin when defined", async () => {
- // Arrange
- component.onSuccessfulLogin = jest.fn().mockResolvedValue(undefined);
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
-
- // Act
- await component.doSubmit();
-
- // Assert
- expect(component.onSuccessfulLogin).toHaveBeenCalled();
- });
-
- it("calls loginEmailService.clearValues() when login is successful", async () => {
- // Arrange
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
- // spy on loginEmailService.clearValues
- const clearValuesSpy = jest.spyOn(mockLoginEmailService, "clearValues");
-
- // Act
- await component.doSubmit();
-
- // Assert
- expect(clearValuesSpy).toHaveBeenCalled();
- });
-
- describe("Set Master Password scenarios", () => {
- beforeEach(() => {
- const authResult = new AuthResult();
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
- });
-
- describe("Given user needs to set a master password", () => {
- beforeEach(() => {
- // Only need to test the case where the user has no master password to test the primary change mp flow here
- selectedUserDecryptionOptions.next(mockUserDecryptionOpts.noMasterPassword);
- });
-
- testChangePasswordOnSuccessfulLogin();
- });
-
- it("does not navigate to the change password route when the user has key connector even if user has no master password", async () => {
- selectedUserDecryptionOptions.next(
- mockUserDecryptionOpts.noMasterPasswordWithKeyConnector,
- );
-
- await component.doSubmit();
-
- expect(mockRouter.navigate).not.toHaveBeenCalledWith([_component.changePasswordRoute], {
- queryParams: {
- identifier: component.orgIdentifier,
- },
- });
- });
- });
-
- describe("Force Master Password Reset scenarios", () => {
- [
- ForceSetPasswordReason.AdminForcePasswordReset,
- ForceSetPasswordReason.WeakMasterPassword,
- ].forEach((forceResetPasswordReason) => {
- const reasonString = ForceSetPasswordReason[forceResetPasswordReason];
-
- beforeEach(() => {
- // use standard user with MP because this test is not concerned with password reset.
- selectedUserDecryptionOptions.next(mockUserDecryptionOpts.withMasterPassword);
-
- const authResult = new AuthResult();
- authResult.forcePasswordReset = forceResetPasswordReason;
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
- });
-
- testForceResetOnSuccessfulLogin(reasonString);
- });
- });
-
- it("calls onSuccessfulLoginNavigate when the callback is defined", async () => {
- // Arrange
- component.onSuccessfulLoginNavigate = jest.fn().mockResolvedValue(undefined);
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
-
- // Act
- await component.doSubmit();
-
- // Assert
- expect(component.onSuccessfulLoginNavigate).toHaveBeenCalled();
- });
-
- it("navigates to the component's defined success route when the login is successful and onSuccessfulLoginNavigate is undefined", async () => {
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
-
- // Act
- await component.doSubmit();
-
- // Assert
- expect(component.onSuccessfulLoginNavigate).not.toBeDefined();
-
- expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
- expect(mockRouter.navigate).toHaveBeenCalledWith([_component.successRoute], undefined);
- });
- });
- });
-
- describe("SSO > 2FA scenarios", () => {
- beforeEach(() => {
- const mockActivatedRoute = TestBed.inject(ActivatedRoute);
- mockActivatedRoute.snapshot.queryParamMap.get = jest.fn().mockReturnValue("true");
- });
-
- describe("doSubmit", () => {
- const token = "testToken";
- const remember = false;
- const captchaToken = "testCaptchaToken";
-
- beforeEach(() => {
- component.token = token;
- component.remember = remember;
- component.captchaToken = captchaToken;
- });
-
- describe("Trusted Device Encryption scenarios", () => {
- beforeEach(() => {
- mockConfigService.getFeatureFlag.mockResolvedValue(true);
- });
-
- describe("Given Trusted Device Encryption is enabled and user needs to set a master password", () => {
- beforeEach(() => {
- selectedUserDecryptionOptions.next(
- mockUserDecryptionOpts.noMasterPasswordWithTrustedDeviceWithManageResetPassword,
- );
-
- const authResult = new AuthResult();
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
- });
-
- it("navigates to the component's defined trusted device encryption route and sets correct flag when user doesn't have a MP and key connector isn't enabled", async () => {
- // Act
- await component.doSubmit();
-
- // Assert
- expect(mockMasterPasswordService.mock.setForceSetPasswordReason).toHaveBeenCalledWith(
- ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission,
- userId,
- );
-
- expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
- expect(mockRouter.navigate).toHaveBeenCalledWith(
- [_component.trustedDeviceEncRoute],
- undefined,
- );
- });
- });
-
- describe("Given Trusted Device Encryption is enabled, user doesn't need to set a MP, and forcePasswordReset is required", () => {
- [
- ForceSetPasswordReason.AdminForcePasswordReset,
- ForceSetPasswordReason.WeakMasterPassword,
- ].forEach((forceResetPasswordReason) => {
- const reasonString = ForceSetPasswordReason[forceResetPasswordReason];
-
- beforeEach(() => {
- // use standard user with MP because this test is not concerned with password reset.
- selectedUserDecryptionOptions.next(
- mockUserDecryptionOpts.withMasterPasswordAndTrustedDevice,
- );
-
- const authResult = new AuthResult();
- authResult.forcePasswordReset = forceResetPasswordReason;
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
- });
-
- testForceResetOnSuccessfulLogin(reasonString);
- });
- });
-
- describe("Given Trusted Device Encryption is enabled, user doesn't need to set a MP, and forcePasswordReset is not required", () => {
- let authResult;
- beforeEach(() => {
- selectedUserDecryptionOptions.next(
- mockUserDecryptionOpts.withMasterPasswordAndTrustedDevice,
- );
-
- authResult = new AuthResult();
- authResult.forcePasswordReset = ForceSetPasswordReason.None;
- mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
- });
-
- it("navigates to the component's defined trusted device encryption route when login is successful and onSuccessfulLoginTdeNavigate is undefined", async () => {
- await component.doSubmit();
-
- expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
- expect(mockRouter.navigate).toHaveBeenCalledWith(
- [_component.trustedDeviceEncRoute],
- undefined,
- );
- });
-
- it("calls onSuccessfulLoginTdeNavigate instead of router.navigate when the callback is defined", async () => {
- component.onSuccessfulLoginTdeNavigate = jest.fn().mockResolvedValue(undefined);
-
- await component.doSubmit();
-
- expect(mockRouter.navigate).not.toHaveBeenCalled();
- expect(component.onSuccessfulLoginTdeNavigate).toHaveBeenCalled();
- });
- });
- });
- });
- });
-
- it("navigates to the timeout route when timeout expires", async () => {
- authenticationSessionTimeoutSubject.next(true);
-
- expect(mockRouter.navigate).toHaveBeenCalledWith(["authentication-timeout"]);
- });
-});
diff --git a/libs/angular/src/auth/components/two-factor-v1.component.ts b/libs/angular/src/auth/components/two-factor-v1.component.ts
deleted file mode 100644
index 3fda2685f5e..00000000000
--- a/libs/angular/src/auth/components/two-factor-v1.component.ts
+++ /dev/null
@@ -1,514 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Directive, Inject, OnInit, OnDestroy } from "@angular/core";
-import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
-import { ActivatedRoute, NavigationExtras, Router } from "@angular/router";
-import { firstValueFrom } from "rxjs";
-import { first } from "rxjs/operators";
-
-import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
-import {
- LoginStrategyServiceAbstraction,
- LoginEmailServiceAbstraction,
- TrustedDeviceUserDecryptionOption,
- UserDecryptionOptions,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
-import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
-import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
-import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
-import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
-import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
-import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
-import { TwoFactorProviders } from "@bitwarden/common/auth/services/two-factor.service";
-import { WebAuthnIFrame } from "@bitwarden/common/auth/webauthn-iframe";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.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 { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { ToastService } from "@bitwarden/components";
-
-import { CaptchaProtectedComponent } from "./captcha-protected.component";
-
-@Directive()
-export class TwoFactorComponentV1 extends CaptchaProtectedComponent implements OnInit, OnDestroy {
- token = "";
- remember = false;
- webAuthnReady = false;
- webAuthnNewTab = false;
- providers = TwoFactorProviders;
- providerType = TwoFactorProviderType;
- selectedProviderType: TwoFactorProviderType = TwoFactorProviderType.Authenticator;
- webAuthnSupported = false;
- webAuthn: WebAuthnIFrame = null;
- title = "";
- twoFactorEmail: string = null;
- formPromise: Promise;
- emailPromise: Promise;
- orgIdentifier: string = null;
-
- duoFramelessUrl: string = null;
- duoResultListenerInitialized = false;
-
- onSuccessfulLogin: () => Promise;
- onSuccessfulLoginNavigate: () => Promise;
-
- onSuccessfulLoginTde: () => Promise;
- onSuccessfulLoginTdeNavigate: () => Promise;
-
- protected loginRoute = "login";
-
- protected trustedDeviceEncRoute = "login-initiated";
- protected changePasswordRoute = "set-password";
- protected forcePasswordResetRoute = "update-temp-password";
- protected successRoute = "vault";
- protected twoFactorTimeoutRoute = "authentication-timeout";
-
- get isDuoProvider(): boolean {
- return (
- this.selectedProviderType === TwoFactorProviderType.Duo ||
- this.selectedProviderType === TwoFactorProviderType.OrganizationDuo
- );
- }
-
- constructor(
- protected loginStrategyService: LoginStrategyServiceAbstraction,
- protected router: Router,
- protected i18nService: I18nService,
- protected apiService: ApiService,
- protected platformUtilsService: PlatformUtilsService,
- @Inject(WINDOW) protected win: Window,
- protected environmentService: EnvironmentService,
- protected stateService: StateService,
- protected route: ActivatedRoute,
- protected logService: LogService,
- protected twoFactorService: TwoFactorService,
- protected appIdService: AppIdService,
- protected loginEmailService: LoginEmailServiceAbstraction,
- protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
- protected ssoLoginService: SsoLoginServiceAbstraction,
- protected configService: ConfigService,
- protected masterPasswordService: InternalMasterPasswordServiceAbstraction,
- protected accountService: AccountService,
- protected toastService: ToastService,
- ) {
- super(environmentService, i18nService, platformUtilsService, toastService);
-
- this.webAuthnSupported = this.platformUtilsService.supportsWebAuthn(win);
-
- // Add subscription to authenticationSessionTimeout$ and navigate to twoFactorTimeoutRoute if expired
- this.loginStrategyService.authenticationSessionTimeout$
- .pipe(takeUntilDestroyed())
- .subscribe(async (expired) => {
- if (!expired) {
- return;
- }
-
- try {
- await this.router.navigate([this.twoFactorTimeoutRoute]);
- } catch (err) {
- this.logService.error(`Failed to navigate to ${this.twoFactorTimeoutRoute} route`, err);
- }
- });
- }
-
- async ngOnInit() {
- if (!(await this.authing()) || (await this.twoFactorService.getProviders()) == null) {
- // 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([this.loginRoute]);
- return;
- }
-
- this.route.queryParams.pipe(first()).subscribe((qParams) => {
- if (qParams.identifier != null) {
- this.orgIdentifier = qParams.identifier;
- }
- });
-
- if (await this.needsLock()) {
- this.successRoute = "lock";
- }
-
- if (this.win != null && this.webAuthnSupported) {
- const env = await firstValueFrom(this.environmentService.environment$);
- const webVaultUrl = env.getWebVaultUrl();
- this.webAuthn = new WebAuthnIFrame(
- this.win,
- webVaultUrl,
- this.webAuthnNewTab,
- this.platformUtilsService,
- this.i18nService,
- (token: string) => {
- this.token = token;
- // 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.submit();
- },
- (error: string) => {
- this.toastService.showToast({
- variant: "error",
- title: this.i18nService.t("errorOccurred"),
- message: this.i18nService.t("webauthnCancelOrTimeout"),
- });
- },
- (info: string) => {
- if (info === "ready") {
- this.webAuthnReady = true;
- }
- },
- );
- }
-
- this.selectedProviderType = await this.twoFactorService.getDefaultProvider(
- this.webAuthnSupported,
- );
- await this.init();
- }
-
- ngOnDestroy(): void {
- this.cleanupWebAuthn();
- this.webAuthn = null;
- }
-
- async init() {
- if (this.selectedProviderType == null) {
- this.title = this.i18nService.t("loginUnavailable");
- return;
- }
-
- this.cleanupWebAuthn();
- this.title = (TwoFactorProviders as any)[this.selectedProviderType].name;
- const providerData = await this.twoFactorService.getProviders().then((providers) => {
- return providers.get(this.selectedProviderType);
- });
- switch (this.selectedProviderType) {
- case TwoFactorProviderType.WebAuthn:
- if (!this.webAuthnNewTab) {
- setTimeout(async () => {
- await this.authWebAuthn();
- }, 500);
- }
- break;
- case TwoFactorProviderType.Duo:
- case TwoFactorProviderType.OrganizationDuo:
- // Setup listener for duo-redirect.ts connector to send back the code
- if (!this.duoResultListenerInitialized) {
- // setup client specific duo result listener
- this.setupDuoResultListener();
- this.duoResultListenerInitialized = true;
- }
- // flow must be launched by user so they can choose to remember the device or not.
- this.duoFramelessUrl = providerData.AuthUrl;
- break;
- case TwoFactorProviderType.Email:
- this.twoFactorEmail = providerData.Email;
- if ((await this.twoFactorService.getProviders()).size > 1) {
- await this.sendEmail(false);
- }
- break;
- default:
- break;
- }
- }
-
- async submit() {
- await this.setupCaptcha();
-
- if (this.token == null || this.token === "") {
- this.toastService.showToast({
- variant: "error",
- title: this.i18nService.t("errorOccurred"),
- message: this.i18nService.t("verificationCodeRequired"),
- });
- return;
- }
-
- if (this.selectedProviderType === TwoFactorProviderType.WebAuthn) {
- if (this.webAuthn != null) {
- this.webAuthn.stop();
- } else {
- return;
- }
- } else if (
- this.selectedProviderType === TwoFactorProviderType.Email ||
- this.selectedProviderType === TwoFactorProviderType.Authenticator
- ) {
- this.token = this.token.replace(" ", "").trim();
- }
-
- await this.doSubmit();
- if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && this.webAuthn != null) {
- this.webAuthn.start();
- }
- }
-
- async doSubmit() {
- this.formPromise = this.loginStrategyService.logInTwoFactor(
- new TokenTwoFactorRequest(this.selectedProviderType, this.token, this.remember),
- this.captchaToken,
- );
- const authResult: AuthResult = await this.formPromise;
-
- await this.handleLoginResponse(authResult);
- }
-
- protected handleMigrateEncryptionKey(result: AuthResult): boolean {
- if (!result.requiresEncryptionKeyMigration) {
- return false;
- }
-
- this.toastService.showToast({
- variant: "error",
- title: this.i18nService.t("errorOccured"),
- message: this.i18nService.t("encryptionKeyMigrationRequired"),
- });
- return true;
- }
-
- // Each client will have own implementation
- protected setupDuoResultListener(): void {}
-
- private async handleLoginResponse(authResult: AuthResult) {
- if (this.handleCaptchaRequired(authResult)) {
- return;
- } else if (this.handleMigrateEncryptionKey(authResult)) {
- return;
- }
-
- // Save off the OrgSsoIdentifier for use in the TDE flows
- // - TDE login decryption options component
- // - Browser SSO on extension open
- const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id;
- await this.ssoLoginService.setActiveUserOrganizationSsoIdentifier(this.orgIdentifier, userId);
- this.loginEmailService.clearValues();
-
- // note: this flow affects both TDE & standard users
- if (this.isForcePasswordResetRequired(authResult)) {
- return await this.handleForcePasswordReset(this.orgIdentifier);
- }
-
- const userDecryptionOpts = await firstValueFrom(
- this.userDecryptionOptionsService.userDecryptionOptions$,
- );
-
- const tdeEnabled = await this.isTrustedDeviceEncEnabled(userDecryptionOpts.trustedDeviceOption);
-
- if (tdeEnabled) {
- return await this.handleTrustedDeviceEncryptionEnabled(
- authResult,
- this.orgIdentifier,
- userDecryptionOpts,
- );
- }
-
- // User must set password if they don't have one and they aren't using either TDE or key connector.
- const requireSetPassword =
- !userDecryptionOpts.hasMasterPassword && userDecryptionOpts.keyConnectorOption === undefined;
-
- if (requireSetPassword || authResult.resetMasterPassword) {
- // Change implies going no password -> password in this case
- return await this.handleChangePasswordRequired(this.orgIdentifier);
- }
-
- return await this.handleSuccessfulLogin();
- }
-
- private async isTrustedDeviceEncEnabled(
- trustedDeviceOption: TrustedDeviceUserDecryptionOption,
- ): Promise {
- const ssoTo2faFlowActive = this.route.snapshot.queryParamMap.get("sso") === "true";
-
- return ssoTo2faFlowActive && trustedDeviceOption !== undefined;
- }
-
- private async handleTrustedDeviceEncryptionEnabled(
- authResult: AuthResult,
- orgIdentifier: string,
- userDecryptionOpts: UserDecryptionOptions,
- ): Promise {
- // If user doesn't have a MP, but has reset password permission, they must set a MP
- if (
- !userDecryptionOpts.hasMasterPassword &&
- userDecryptionOpts.trustedDeviceOption.hasManageResetPasswordPermission
- ) {
- // Set flag so that auth guard can redirect to set password screen after decryption (trusted or untrusted device)
- // Note: we cannot directly navigate to the set password screen in this scenario as we are in a pre-decryption state, and
- // if you try to set a new MP before decrypting, you will invalidate the user's data by making a new user key.
- const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id;
- await this.masterPasswordService.setForceSetPasswordReason(
- ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission,
- userId,
- );
- }
-
- if (this.onSuccessfulLoginTde != null) {
- // Note: awaiting this will currently cause a hang on desktop & browser as they will wait for a full sync to complete
- // before navigating to the success route.
- // 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.onSuccessfulLoginTde();
- }
-
- // 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.navigateViaCallbackOrRoute(
- this.onSuccessfulLoginTdeNavigate,
- // Navigate to TDE page (if user was on trusted device and TDE has decrypted
- // their user key, the login-initiated guard will redirect them to the vault)
- [this.trustedDeviceEncRoute],
- );
- }
-
- private async handleChangePasswordRequired(orgIdentifier: string) {
- await this.router.navigate([this.changePasswordRoute], {
- queryParams: {
- identifier: orgIdentifier,
- },
- });
- }
-
- /**
- * Determines if a user needs to reset their password based on certain conditions.
- * Users can be forced to reset their password via an admin or org policy disallowing weak passwords.
- * Note: this is different from the SSO component login flow as a user can
- * login with MP and then have to pass 2FA to finish login and we can actually
- * evaluate if they have a weak password at that time.
- *
- * @param {AuthResult} authResult - The authentication result.
- * @returns {boolean} Returns true if a password reset is required, false otherwise.
- */
- private isForcePasswordResetRequired(authResult: AuthResult): boolean {
- const forceResetReasons = [
- ForceSetPasswordReason.AdminForcePasswordReset,
- ForceSetPasswordReason.WeakMasterPassword,
- ];
-
- return forceResetReasons.includes(authResult.forcePasswordReset);
- }
-
- private async handleForcePasswordReset(orgIdentifier: string) {
- // 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([this.forcePasswordResetRoute], {
- queryParams: {
- identifier: orgIdentifier,
- },
- });
- }
-
- private async handleSuccessfulLogin() {
- if (this.onSuccessfulLogin != null) {
- // Note: awaiting this will currently cause a hang on desktop & browser as they will wait for a full sync to complete
- // before navigating to the success route.
- // 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.onSuccessfulLogin();
- }
- await this.navigateViaCallbackOrRoute(this.onSuccessfulLoginNavigate, [this.successRoute]);
- }
-
- private async navigateViaCallbackOrRoute(
- callback: () => Promise,
- commands: unknown[],
- extras?: NavigationExtras,
- ): Promise {
- if (callback) {
- await callback();
- } else {
- await this.router.navigate(commands, extras);
- }
- }
-
- async sendEmail(doToast: boolean) {
- if (this.selectedProviderType !== TwoFactorProviderType.Email) {
- return;
- }
-
- if (this.emailPromise != null) {
- return;
- }
-
- if ((await this.loginStrategyService.getEmail()) == null) {
- this.toastService.showToast({
- variant: "error",
- title: this.i18nService.t("errorOccurred"),
- message: this.i18nService.t("sessionTimeout"),
- });
- return;
- }
-
- try {
- const request = new TwoFactorEmailRequest();
- request.email = await this.loginStrategyService.getEmail();
- request.masterPasswordHash = await this.loginStrategyService.getMasterPasswordHash();
- request.ssoEmail2FaSessionToken =
- await this.loginStrategyService.getSsoEmail2FaSessionToken();
- request.deviceIdentifier = await this.appIdService.getAppId();
- request.authRequestAccessCode = await this.loginStrategyService.getAccessCode();
- request.authRequestId = await this.loginStrategyService.getAuthRequestId();
- this.emailPromise = this.apiService.postTwoFactorEmail(request);
- await this.emailPromise;
- if (doToast) {
- this.toastService.showToast({
- variant: "success",
- title: null,
- message: this.i18nService.t("verificationCodeEmailSent", this.twoFactorEmail),
- });
- }
- } catch (e) {
- this.logService.error(e);
- }
-
- this.emailPromise = null;
- }
-
- async authWebAuthn() {
- const providerData = await this.twoFactorService.getProviders().then((providers) => {
- return providers.get(this.selectedProviderType);
- });
-
- if (!this.webAuthnSupported || this.webAuthn == null) {
- return;
- }
-
- this.webAuthn.init(providerData);
- }
-
- private cleanupWebAuthn() {
- if (this.webAuthn != null) {
- this.webAuthn.stop();
- this.webAuthn.cleanup();
- }
- }
-
- private async authing(): Promise {
- return (await firstValueFrom(this.loginStrategyService.currentAuthType$)) !== null;
- }
-
- private async needsLock(): Promise {
- const authType = await firstValueFrom(this.loginStrategyService.currentAuthType$);
- return authType == AuthenticationType.Sso || authType == AuthenticationType.UserApiKey;
- }
-
- async launchDuoFrameless() {
- if (this.duoFramelessUrl === null) {
- this.toastService.showToast({
- variant: "error",
- title: null,
- message: this.i18nService.t("duoHealthCheckResultsInNullAuthUrlError"),
- });
- return;
- }
-
- this.platformUtilsService.launchUri(this.duoFramelessUrl);
- }
-}
diff --git a/libs/angular/src/auth/functions/unauth-ui-refresh-route-swap.ts b/libs/angular/src/auth/functions/unauth-ui-refresh-route-swap.ts
deleted file mode 100644
index b19e73a7412..00000000000
--- a/libs/angular/src/auth/functions/unauth-ui-refresh-route-swap.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Type, inject } from "@angular/core";
-import { Route, Routes } from "@angular/router";
-
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-
-import { componentRouteSwap } from "../../utils/component-route-swap";
-
-/**
- * Helper function to swap between two components based on the UnauthenticatedExtensionUIRefresh feature flag.
- * We need this because the auth teams's authenticated UI will be refreshed as part of the MVP but the
- * unauthenticated UIs will not necessarily make the cut.
- * Note: Even though this is primarily an extension refresh initiative, this will be used across clients
- * as we are consolidating the unauthenticated UIs into single libs/auth components which affects all clients.
- * @param defaultComponent - The current non-refreshed component to render.
- * @param refreshedComponent - The new refreshed component to render.
- * @param options - The shared route options to apply to both components.
- * @param altOptions - The alt route options to apply to the alt component. If not provided, the base options will be used.
- */
-export function unauthUiRefreshSwap(
- defaultComponent: Type,
- refreshedComponent: Type,
- options: Route,
- altOptions?: Route,
-): Routes {
- return componentRouteSwap(
- defaultComponent,
- refreshedComponent,
- async () => {
- const configService = inject(ConfigService);
- return configService.getFeatureFlag(FeatureFlag.UnauthenticatedExtensionUIRefresh);
- },
- options,
- altOptions,
- );
-}
diff --git a/libs/auth/src/angular/anon-layout/anon-layout.component.html b/libs/auth/src/angular/anon-layout/anon-layout.component.html
index 4120ea59002..f31a5500b43 100644
--- a/libs/auth/src/angular/anon-layout/anon-layout.component.html
+++ b/libs/auth/src/angular/anon-layout/anon-layout.component.html
@@ -17,7 +17,7 @@
class="tw-text-center tw-mb-4 sm:tw-mb-6"
[ngClass]="{ 'tw-max-w-md tw-mx-auto': titleAreaMaxWidth === 'md' }"
>
-
+
diff --git a/libs/auth/src/angular/anon-layout/anon-layout.component.ts b/libs/auth/src/angular/anon-layout/anon-layout.component.ts
index 05ddb9614f1..1ca4ccd2432 100644
--- a/libs/auth/src/angular/anon-layout/anon-layout.component.ts
+++ b/libs/auth/src/angular/anon-layout/anon-layout.component.ts
@@ -39,6 +39,7 @@ export class AnonLayoutComponent implements OnInit, OnChanges {
@Input() showReadonlyHostname: boolean;
@Input() hideLogo: boolean = false;
@Input() hideFooter: boolean = false;
+ @Input() hideIcon: boolean = false;
/**
* Max width of the title area content
diff --git a/libs/auth/src/angular/anon-layout/anon-layout.stories.ts b/libs/auth/src/angular/anon-layout/anon-layout.stories.ts
index c7e15d9dcfa..34d561d5210 100644
--- a/libs/auth/src/angular/anon-layout/anon-layout.stories.ts
+++ b/libs/auth/src/angular/anon-layout/anon-layout.stories.ts
@@ -163,6 +163,22 @@ export const WithCustomIcon: Story = {
}),
};
+export const HideIcon: Story = {
+ render: (args) => ({
+ props: args,
+ template:
+ // Projected content (the
) and styling is just a sample and can be replaced with any content/styling.
+ `
+
+
+
Primary Projected Content Area (customizable)
+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Necessitatibus illum vero, placeat recusandae esse ratione eius minima veniam nemo, quas beatae! Impedit molestiae alias sapiente explicabo. Sapiente corporis ipsa numquam?
+
+
+ `,
+ }),
+};
+
export const HideLogo: Story = {
render: (args) => ({
props: args,
diff --git a/libs/common/src/platform/scheduling/task-scheduler.service.ts b/libs/common/src/platform/scheduling/task-scheduler.service.ts
index 35a577dda7d..3ea80c3ee0a 100644
--- a/libs/common/src/platform/scheduling/task-scheduler.service.ts
+++ b/libs/common/src/platform/scheduling/task-scheduler.service.ts
@@ -11,7 +11,7 @@ import { ScheduledTaskName } from "./scheduled-task-name.enum";
* in the future but the task that is ran is NOT the remainder of your RXJS pipeline. The
* task you want ran must instead be registered in a location reachable on a service worker
* startup (on browser). An example of an acceptible location is the constructor of a service
- * you know is created in `MainBackground`. Uses of this API is other clients _can_ have the
+ * you know is created in `MainBackground`. Uses of this API in other clients _can_ have the
* `registerTaskHandler` call in more places, but in order to have it work across clients
* it is recommended to register it according to the rules of browser.
*
diff --git a/libs/common/src/vault/services/cipher.service.spec.ts b/libs/common/src/vault/services/cipher.service.spec.ts
index def0c04dd16..dd7faea8e8a 100644
--- a/libs/common/src/vault/services/cipher.service.spec.ts
+++ b/libs/common/src/vault/services/cipher.service.spec.ts
@@ -305,51 +305,86 @@ describe("Cipher Service", () => {
});
describe("cipher.key", () => {
- it("is null when feature flag is false", async () => {
- configService.getFeatureFlag.mockResolvedValue(false);
-
+ beforeEach(() => {
keyService.getOrgKey.mockReturnValue(
Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
+ });
+
+ it("is null when feature flag is false", async () => {
+ configService.getFeatureFlag.mockResolvedValue(false);
const cipher = await cipherService.encrypt(cipherView, userId);
expect(cipher.key).toBeNull();
});
- it("is defined when feature flag flag is true", async () => {
- configService.getFeatureFlag.mockResolvedValue(true);
+ describe("when feature flag is true", () => {
+ beforeEach(() => {
+ configService.getFeatureFlag.mockResolvedValue(true);
+ });
- const cipher = await cipherService.encrypt(cipherView, userId);
+ it("is null when the cipher is not viewPassword", async () => {
+ cipherView.viewPassword = false;
- expect(cipher.key).toBeDefined();
+ const cipher = await cipherService.encrypt(cipherView, userId);
+
+ expect(cipher.key).toBeNull();
+ });
+
+ it("is defined when the cipher is viewPassword", async () => {
+ cipherView.viewPassword = true;
+
+ const cipher = await cipherService.encrypt(cipherView, userId);
+
+ expect(cipher.key).toBeDefined();
+ });
});
});
describe("encryptWithCipherKey", () => {
beforeEach(() => {
jest.spyOn(cipherService, "encryptCipherWithCipherKey");
+ keyService.getOrgKey.mockReturnValue(
+ Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
+ );
});
it("is not called when feature flag is false", async () => {
configService.getFeatureFlag.mockResolvedValue(false);
- keyService.getOrgKey.mockReturnValue(
- Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
- );
await cipherService.encrypt(cipherView, userId);
expect(cipherService["encryptCipherWithCipherKey"]).not.toHaveBeenCalled();
});
- it("is called when feature flag is true", async () => {
- configService.getFeatureFlag.mockResolvedValue(true);
- keyService.getOrgKey.mockReturnValue(
- Promise.resolve(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
- );
+ describe("when feature flag is true", () => {
+ beforeEach(() => {
+ configService.getFeatureFlag.mockResolvedValue(true);
+ });
- await cipherService.encrypt(cipherView, userId);
+ it("is called when cipher viewPassword is true", async () => {
+ cipherView.viewPassword = true;
- expect(cipherService["encryptCipherWithCipherKey"]).toHaveBeenCalled();
+ await cipherService.encrypt(cipherView, userId);
+
+ expect(cipherService["encryptCipherWithCipherKey"]).toHaveBeenCalled();
+ });
+
+ it("is not called when cipher viewPassword is false and original cipher has no key", async () => {
+ cipherView.viewPassword = false;
+
+ await cipherService.encrypt(cipherView, userId, undefined, undefined, new Cipher());
+
+ expect(cipherService["encryptCipherWithCipherKey"]).not.toHaveBeenCalled();
+ });
+
+ it("is called when cipher viewPassword is false and original cipher has a key", async () => {
+ cipherView.viewPassword = false;
+
+ await cipherService.encrypt(cipherView, userId, undefined, undefined, cipherObj);
+
+ expect(cipherService["encryptCipherWithCipherKey"]).toHaveBeenCalled();
+ });
});
});
});
diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts
index 4876a755ed8..bb5ae710cfb 100644
--- a/libs/common/src/vault/services/cipher.service.ts
+++ b/libs/common/src/vault/services/cipher.service.ts
@@ -222,7 +222,11 @@ export class CipherService implements CipherServiceAbstraction {
cipher.reprompt = model.reprompt;
cipher.edit = model.edit;
- if (await this.getCipherKeyEncryptionEnabled()) {
+ if (
+ // prevent unprivileged users from migrating to cipher key encryption
+ (model.viewPassword || originalCipher?.key) &&
+ (await this.getCipherKeyEncryptionEnabled())
+ ) {
cipher.key = originalCipher?.key ?? null;
const userOrOrgKey = await this.getKeyForCipherKeyDecryption(cipher, userId);
// The keyForEncryption is only used for encrypting the cipher key, not the cipher itself, since cipher key encryption is enabled.
diff --git a/libs/common/src/vault/services/vault-settings/vault-settings.service.ts b/libs/common/src/vault/services/vault-settings/vault-settings.service.ts
index 85ab3914158..423acba8fff 100644
--- a/libs/common/src/vault/services/vault-settings/vault-settings.service.ts
+++ b/libs/common/src/vault/services/vault-settings/vault-settings.service.ts
@@ -1,4 +1,4 @@
-import { Observable, map } from "rxjs";
+import { Observable, map, shareReplay } from "rxjs";
import { ActiveUserState, GlobalState, StateProvider } from "../../../platform/state";
import { VaultSettingsService as VaultSettingsServiceAbstraction } from "../../abstractions/vault-settings/vault-settings.service";
@@ -46,7 +46,10 @@ export class VaultSettingsService implements VaultSettingsServiceAbstraction {
* {@link VaultSettingsServiceAbstraction.clickItemsToAutofillVaultView$$}
*/
readonly clickItemsToAutofillVaultView$: Observable =
- this.clickItemsToAutofillVaultViewState.state$.pipe(map((x) => x ?? false));
+ this.clickItemsToAutofillVaultViewState.state$.pipe(
+ map((x) => x ?? false),
+ shareReplay({ bufferSize: 1, refCount: false }),
+ );
constructor(private stateProvider: StateProvider) {}
diff --git a/libs/platform/src/background-sync/background-sync.service.spec.ts b/libs/platform/src/background-sync/background-sync.service.spec.ts
new file mode 100644
index 00000000000..1deb907b151
--- /dev/null
+++ b/libs/platform/src/background-sync/background-sync.service.spec.ts
@@ -0,0 +1,107 @@
+import { mock, MockProxy } from "jest-mock-extended";
+
+import { TaskSchedulerService, ScheduledTaskNames } from "@bitwarden/common/platform/scheduling";
+
+import { BackgroundSyncService, DEFAULT_SYNC_INTERVAL_MS } from "./background-sync.service";
+
+describe("BackgroundSyncService", () => {
+ let taskSchedulerService: MockProxy;
+ let backgroundSyncService: BackgroundSyncService;
+
+ beforeEach(() => {
+ taskSchedulerService = mock();
+ backgroundSyncService = new BackgroundSyncService(taskSchedulerService);
+ });
+
+ describe("register", () => {
+ it("registers a task handler with the correct task name", () => {
+ // Arrange
+ const syncCallback = jest.fn().mockResolvedValue(undefined);
+
+ // Act
+ backgroundSyncService.register(syncCallback);
+
+ // Assert
+ expect(taskSchedulerService.registerTaskHandler).toHaveBeenCalledTimes(1);
+ expect(taskSchedulerService.registerTaskHandler).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ syncCallback,
+ );
+ });
+ });
+
+ describe("init", () => {
+ it("schedules the sync interval task with default interval", () => {
+ // Act
+ backgroundSyncService.init();
+
+ // Assert
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledTimes(1);
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ DEFAULT_SYNC_INTERVAL_MS,
+ );
+ });
+
+ it("schedules the sync interval task with custom interval", () => {
+ // Arrange
+ const customInterval = 60000; // 1 minute
+
+ // Act
+ backgroundSyncService.init(customInterval);
+
+ // Assert
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledTimes(1);
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ customInterval,
+ );
+ });
+
+ it("correctly handles zero interval by using default", () => {
+ // Act
+ backgroundSyncService.init(0);
+
+ // Assert
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledTimes(1);
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ DEFAULT_SYNC_INTERVAL_MS,
+ );
+ });
+
+ it("correctly handles negative interval by using default", () => {
+ // Act
+ backgroundSyncService.init(-1000);
+
+ // Assert
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledTimes(1);
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ DEFAULT_SYNC_INTERVAL_MS,
+ );
+ });
+ });
+
+ describe("full integration", () => {
+ it("registers and initializes correctly in sequence", () => {
+ // Arrange
+ const syncCallback = jest.fn().mockResolvedValue(undefined);
+ const customInterval = 45000; // 45 seconds
+
+ // Act
+ backgroundSyncService.register(syncCallback);
+ backgroundSyncService.init(customInterval);
+
+ // Assert
+ expect(taskSchedulerService.registerTaskHandler).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ syncCallback,
+ );
+ expect(taskSchedulerService.setInterval).toHaveBeenCalledWith(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ customInterval,
+ );
+ });
+ });
+});
diff --git a/libs/platform/src/background-sync/background-sync.service.ts b/libs/platform/src/background-sync/background-sync.service.ts
new file mode 100644
index 00000000000..dc1b49d399e
--- /dev/null
+++ b/libs/platform/src/background-sync/background-sync.service.ts
@@ -0,0 +1,44 @@
+import { TaskSchedulerService, ScheduledTaskNames } from "@bitwarden/common/platform/scheduling";
+
+/**
+ * The default interval between background syncs.
+ * 300,000ms = 5 minutes
+ */
+export const DEFAULT_SYNC_INTERVAL_MS = 300000;
+
+/**
+ * Service responsible for registering and managing background synchronization for the browser extension.
+ * Handles scheduling of periodic sync operations using the task scheduler infrastructure.
+ */
+
+export class BackgroundSyncService {
+ /**
+ * Creates a new instance of BackgroundSyncService.
+ * @param taskSchedulerService - Service that handles scheduling and execution of periodic tasks
+ */
+ constructor(private taskSchedulerService: TaskSchedulerService) {}
+
+ /**
+ * Registers a callback function to be executed when the sync interval task is triggered.
+ * This associates the sync task name with the provided callback in the task scheduler.
+ *
+ * @param syncCallback - The function to execute when the sync task is triggered
+ */
+ register(syncCallback: () => Promise) {
+ this.taskSchedulerService.registerTaskHandler(
+ ScheduledTaskNames.scheduleNextSyncInterval,
+ syncCallback,
+ );
+ }
+
+ /**
+ * Initializes the background sync service by scheduling the sync interval task.
+ * This sets up a recurring timer that triggers the registered sync callback at regular intervals.
+ *
+ * @param intervalMs - The interval in milliseconds between sync operations (defaults to 300000ms/5 minutes)
+ */
+ init(intervalMs: number = DEFAULT_SYNC_INTERVAL_MS) {
+ intervalMs = intervalMs < 1 ? DEFAULT_SYNC_INTERVAL_MS : intervalMs;
+ this.taskSchedulerService.setInterval(ScheduledTaskNames.scheduleNextSyncInterval, intervalMs);
+ }
+}
diff --git a/libs/platform/src/background-sync/index.ts b/libs/platform/src/background-sync/index.ts
new file mode 100644
index 00000000000..adfeec608be
--- /dev/null
+++ b/libs/platform/src/background-sync/index.ts
@@ -0,0 +1 @@
+export * from "./background-sync.service";
diff --git a/libs/platform/src/index.ts b/libs/platform/src/index.ts
index f11ec102845..3fabe3fad1a 100644
--- a/libs/platform/src/index.ts
+++ b/libs/platform/src/index.ts
@@ -1 +1,2 @@
export * from "./services/browser-service";
+export * from "./background-sync";
diff --git a/libs/platform/tsconfig.json b/libs/platform/tsconfig.json
index eaa021247d8..898f9e41c6a 100644
--- a/libs/platform/tsconfig.json
+++ b/libs/platform/tsconfig.json
@@ -1,7 +1,9 @@
{
"extends": "../shared/tsconfig",
"compilerOptions": {
- "paths": {}
+ "paths": {
+ "@bitwarden/common/*": ["../common/src/*"]
+ }
},
"include": ["src", "spec"],
"exclude": ["node_modules", "dist"]
diff --git a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts
index 0fc1f336b90..765de042d32 100644
--- a/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts
+++ b/libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts
@@ -81,7 +81,7 @@ export class IndividualVaultExportService
return {
type: "text/plain",
data: await this.buildPasswordExport(exportVault.data, password),
- fileName: ExportHelper.getFileName("json"),
+ fileName: ExportHelper.getFileName("", "encrypted_json"),
} as ExportedVaultAsString;
}
@@ -126,7 +126,7 @@ export class IndividualVaultExportService
return {
type: "application/zip",
data: blobData,
- fileName: ExportHelper.getFileName("json"),
+ fileName: ExportHelper.getFileName("", "json"),
} as ExportedVaultAsBlob;
}
@@ -185,14 +185,14 @@ export class IndividualVaultExportService
return {
type: "text/plain",
data: this.buildCsvExport(decFolders, decCiphers),
- fileName: ExportHelper.getFileName("csv"),
+ fileName: ExportHelper.getFileName("", "csv"),
} as ExportedVaultAsString;
}
return {
type: "text/plain",
data: this.buildJsonExport(decFolders, decCiphers),
- fileName: ExportHelper.getFileName("json"),
+ fileName: ExportHelper.getFileName("", "json"),
} as ExportedVaultAsString;
}
@@ -250,7 +250,7 @@ export class IndividualVaultExportService
return {
type: "text/plain",
data: JSON.stringify(jsonDoc, null, " "),
- fileName: ExportHelper.getFileName("json"),
+ fileName: ExportHelper.getFileName("", "json"),
} as ExportedVaultAsString;
}
diff --git a/libs/vault/src/cipher-form/cipher-form.mdx b/libs/vault/src/cipher-form/cipher-form.mdx
index ed2e799b9f3..658fcd38d11 100644
--- a/libs/vault/src/cipher-form/cipher-form.mdx
+++ b/libs/vault/src/cipher-form/cipher-form.mdx
@@ -12,6 +12,9 @@ It is configured via a `CipherFormConfig` object that is passed to the component
create it. A default implementation of the `CipherFormConfigService` exists in the
`@bitwarden/vault` library.
+The cipher form has a slot for `attachment-button`, which should be included when the form is in
+`edit` mode.
+
diff --git a/libs/vault/src/cipher-form/cipher-form.stories.ts b/libs/vault/src/cipher-form/cipher-form.stories.ts
index 5d6464b4c79..52d70e8652a 100644
--- a/libs/vault/src/cipher-form/cipher-form.stories.ts
+++ b/libs/vault/src/cipher-form/cipher-form.stories.ts
@@ -29,7 +29,7 @@ import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
-import { AsyncActionsModule, ButtonModule, ToastService } from "@bitwarden/components";
+import { AsyncActionsModule, ButtonModule, ItemModule, ToastService } from "@bitwarden/components";
import {
CipherFormConfig,
CipherFormGenerationService,
@@ -131,7 +131,7 @@ export default {
component: CipherFormComponent,
decorators: [
moduleMetadata({
- imports: [CipherFormModule, AsyncActionsModule, ButtonModule],
+ imports: [CipherFormModule, AsyncActionsModule, ButtonModule, ItemModule],
providers: [
{
provide: CipherFormService,
@@ -246,7 +246,7 @@ export default {
type Story = StoryObj;
-export const Default: Story = {
+export const Add: Story = {
render: (args) => {
return {
props: {
@@ -254,15 +254,28 @@ export const Default: Story = {
...args,
},
template: /*html*/ `
-
-
+
`,
};
},
};
export const Edit: Story = {
- ...Default,
+ render: (args) => {
+ return {
+ props: {
+ onSave: actionsData.onSave,
+ ...args,
+ },
+ template: /*html*/ `
+
+
+
+
+
+ `,
+ };
+ },
args: {
config: {
...defaultConfig,
@@ -273,7 +286,7 @@ export const Edit: Story = {
};
export const PartialEdit: Story = {
- ...Default,
+ ...Add,
args: {
config: {
...defaultConfig,
@@ -284,7 +297,7 @@ export const PartialEdit: Story = {
};
export const Clone: Story = {
- ...Default,
+ ...Add,
args: {
config: {
...defaultConfig,
@@ -294,8 +307,27 @@ export const Clone: Story = {
},
};
+export const WithSubmitButton: Story = {
+ render: (args) => {
+ return {
+ props: {
+ onSave: actionsData.onSave,
+ ...args,
+ },
+ template: /*html*/ `
+