From 356a20a4bce174cecf98ee6545b569bc2439414e Mon Sep 17 00:00:00 2001 From: Todd Martin <106564991+trmartin4@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:55:01 -0400 Subject: [PATCH 01/14] fix(login): [PM-20174] Do not show validation errors on email input on LoginComponent * Do not show validation errors on input * Removed one-line function. * Removed awaits --- .../auth/src/angular/login/login.component.ts | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/libs/auth/src/angular/login/login.component.ts b/libs/auth/src/angular/login/login.component.ts index 55c282be55c..8a198663e06 100644 --- a/libs/auth/src/angular/login/login.component.ts +++ b/libs/auth/src/angular/login/login.component.ts @@ -400,12 +400,6 @@ export class LoginComponent implements OnInit, OnDestroy { await this.router.navigate(["/login-with-device"]); } - protected async emailIsValid(): Promise { - this.formGroup.controls.email.markAsTouched(); - this.formGroup.controls.email.updateValueAndValidity({ onlySelf: true, emitEvent: true }); - return this.formGroup.controls.email.valid; - } - protected async toggleLoginUiState(value: LoginUiState): Promise { this.loginUiState = value; @@ -474,7 +468,7 @@ export class LoginComponent implements OnInit, OnDestroy { * Continue to the master password entry state (only if email is validated) */ protected async continue(): Promise { - const isEmailValid = await this.emailIsValid(); + const isEmailValid = this.validateEmail(); if (isEmailValid) { await this.toggleLoginUiState(LoginUiState.MASTER_PASSWORD_ENTRY); @@ -496,7 +490,7 @@ export class LoginComponent implements OnInit, OnDestroy { */ async handleSsoClick() { // Make sure the email is valid - const isEmailValid = await this.emailIsValid(); + const isEmailValid = this.validateEmail(); if (!isEmailValid) { return; } @@ -594,11 +588,21 @@ export class LoginComponent implements OnInit, OnDestroy { } }; + /** + * Validates the email and displays any validation errors. + * @returns true if the email is valid, false otherwise. + */ + protected validateEmail(): boolean { + this.formGroup.controls.email.markAsTouched(); + this.formGroup.controls.email.updateValueAndValidity({ onlySelf: true, emitEvent: true }); + return this.formGroup.controls.email.valid; + } + /** * Persist the entered email address and the user's choice to remember it to state. */ private async persistEmailIfValid(): Promise { - if (await this.emailIsValid()) { + if (this.formGroup.controls.email.valid) { const email = this.formGroup.value.email; const rememberEmail = this.formGroup.value.rememberEmail ?? false; if (!email) { @@ -613,7 +617,7 @@ export class LoginComponent implements OnInit, OnDestroy { } /** - * Set the email value from the input field. + * Set the email value from the input field and persists to state if valid. * We only update the form controls onSubmit instead of onBlur because we don't want to show validation errors until * the user submits. This is because currently our validation errors are shown below the input fields, and * displaying them causes the screen to "jump". @@ -626,7 +630,7 @@ export class LoginComponent implements OnInit, OnDestroy { } /** - * Set the Remember Email value from the input field. + * Set the Remember Email value from the input field and persists to state if valid. * We only update the form controls onSubmit instead of onBlur because we don't want to show validation errors until * the user submits. This is because currently our validation errors are shown below the input fields, and * displaying them causes the screen to "jump". From 938e9454e140668d51dd03e81fac58c0a9c53d3a Mon Sep 17 00:00:00 2001 From: Todd Martin <106564991+trmartin4@users.noreply.github.com> Date: Mon, 14 Apr 2025 21:33:51 -0400 Subject: [PATCH 02/14] fix(workflow): [PM-19254] Update image tag generation for builds from forked PRs * Added fork name to tag * Added logging. * Added pull_request_target * Added repository name if on fork. * Limited characters * Added sanitization * Moved to env var for extra security. --- .github/workflows/build-web.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 12748a47748..3da524702fe 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -45,7 +45,7 @@ on: env: _AZ_REGISTRY: bitwardenprod.azurecr.io - + _GITHUB_PR_REPO_NAME: ${{ github.event.pull_request.head.repo.full_name }} jobs: setup: @@ -190,12 +190,18 @@ jobs: - name: Generate container image tag id: tag run: | - if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then - IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g") + if [[ "${GITHUB_EVENT_NAME}" == "pull_request" || "${GITHUB_EVENT_NAME}" == "pull_request_target" ]]; then + IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s/[^a-zA-Z0-9]/-/g") # Sanitize branch name to alphanumeric only else IMAGE_TAG=$(echo "${GITHUB_REF_NAME}" | sed "s#/#-#g") fi + if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then + SANITIZED_REPO_NAME=$(echo "$_GITHUB_PR_REPO_NAME" | sed "s/[^a-zA-Z0-9]/-/g") # Sanitize repo name to alphanumeric only + IMAGE_TAG=$SANITIZED_REPO_NAME-$IMAGE_TAG # Add repo name to the tag + IMAGE_TAG=${IMAGE_TAG:0:128} # Limit to 128 characters, as that's the max length for Docker image tags + fi + if [[ "$IMAGE_TAG" == "main" ]]; then IMAGE_TAG=dev fi From eb9812091cc376dc38cb33339d82d09f0f482521 Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:59:48 +0200 Subject: [PATCH 03/14] Autosync the updated translations (#14234) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/web/src/locales/af/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ar/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/az/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/be/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/bg/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/bn/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/bs/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ca/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/cs/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/cy/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/da/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/de/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/el/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/en_GB/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/en_IN/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/eo/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/es/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/et/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/eu/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/fa/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/fi/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/fil/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/fr/messages.json | 78 +++++++++++++++++++++- apps/web/src/locales/gl/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/he/messages.json | 74 ++++++++++++++++++++- apps/web/src/locales/hi/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/hr/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/hu/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/id/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/it/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ja/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ka/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/km/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/kn/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ko/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/lv/messages.json | 76 +++++++++++++++++++++- apps/web/src/locales/ml/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/mr/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/my/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/nb/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ne/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/nl/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/nn/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/or/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/pl/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/pt_BR/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/pt_PT/messages.json | 76 +++++++++++++++++++++- apps/web/src/locales/ro/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/ru/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/si/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/sk/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/sl/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/sr/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/sr_CS/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/sv/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/te/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/th/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/tr/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/uk/messages.json | 74 ++++++++++++++++++++- apps/web/src/locales/vi/messages.json | 72 +++++++++++++++++++++ apps/web/src/locales/zh_CN/messages.json | 82 ++++++++++++++++++++++-- apps/web/src/locales/zh_TW/messages.json | 72 +++++++++++++++++++++ 62 files changed, 4478 insertions(+), 14 deletions(-) diff --git a/apps/web/src/locales/af/messages.json b/apps/web/src/locales/af/messages.json index 29eb76a1069..56eabc34863 100644 --- a/apps/web/src/locales/af/messages.json +++ b/apps/web/src/locales/af/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "U kan die eksterne ID as verwysing gebruik of om hierdie hulpbron aan ’n eksterne stelsel soos ’n gebruikersgids te koppel." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn is suksesvol bevestig! U kan hierdie oortjie sluit." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "U wagwoordwenk kan nie dieselfde as u wagwoord wees nie." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Vingerafdruk" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Verwyder gebruikers" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ar/messages.json b/apps/web/src/locales/ar/messages.json index f12f59b8fba..9ebd9873655 100644 --- a/apps/web/src/locales/ar/messages.json +++ b/apps/web/src/locales/ar/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/az/messages.json b/apps/web/src/locales/az/messages.json index 069986361ca..0117fa37ae4 100644 --- a/apps/web/src/locales/az/messages.json +++ b/apps/web/src/locales/az/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Xarici kimlik, referans olaraq və ya bu mənbəni istifadəçi kataloqu kimi xarici bir sistemə bağlamaq üçün istifadə edilir." }, + "ssoExternalId": { + "message": "SSO Xarici Kimlik" + }, + "ssoExternalIdDesc": { + "message": "SSO Xarici Kimlik, Bitwarden və konfiqurasiya edilmiş SSO provayderiniz arasında şifrələnməmiş referansdır." + }, "nestCollectionUnder": { "message": "Kolleksiyanı bunun altında yerləşdir" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn kimliyi doğrulaması uğurlu oldu! Bu vərəqi bağlaya bilərsiniz." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Yeni parolunuz hazırkı parolunuzla eyni ola bilməz." + }, "hintEqualsPassword": { "message": "Parol məsləhəti, parolunuzla eyni ola bilməz." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Barmaq izi" }, + "fingerprintPhrase": { + "message": "Barmaq izi ifadəsi:" + }, "removeUsers": { "message": "İstifadəçiləri çıxart" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Təşkilat adı 50 xarakterdən çox ola bilməz." }, + "rotationCompletedTitle": { + "message": "Açar döndərmə uğurludur" + }, + "rotationCompletedDesc": { + "message": "Ana parol və şifrələmə açarınız güncəllənib. Digər cihazlarınızda hesabdan çıxış edildi." + }, + "trustUserEmergencyAccess": { + "message": "İstifadəçiyə güvən və təsdiqlə" + }, + "trustOrganization": { + "message": "Təşkilata güvən" + }, + "trust": { + "message": "Güvən" + }, + "doNotTrust": { + "message": "Güvənmə" + }, + "emergencyAccessTrustWarning": { + "message": "Hesabınızın təhlükəsizliyi üçün yalnız bu istifadəçiyə fövqəladə hal müraciəti icazəsini verdiyinizi və onun barmaq izinin hesabında görünən barmaq izi ilə uyuşduğunu təsdiqləyin" + }, + "orgTrustWarning": { + "message": "Hesabınızın təhlükəsizliyi üçün yalnız bu təşkilatın üzvüsünüzsə, hesab geri qaytarma fəaldırsa və aşağıda görünən barmaq izi təşkilatın barmaq izi ilə uyuşursa davam edin." + }, + "trustUser": { + "message": "İstifadəçiyə güvən" + }, "sshKeyWrongPassword": { "message": "Daxil etdiyiniz parol yanlışdır." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Təyin edilmiş yer sayı, boş yer sayından çoxdur." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fövqəladə hal müraciətini fəallaşdırdığınız $NUM_USERS$ kontakt üçün barmaq izi ifadəsi.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Hesab geri qaytarma seçimini fəallaşdırdığınız $ORG_NAME$ təşkilatı üçün barmaq izi ifadəsi.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Şifrələmə açarlarını döndərmək, sizdən hesabınızı geri qaytara biləcək istənilən təşkilatın açarlarına və fövqəladə hal müraciətini fəallaşdırdığınız istənilən kontakta güvənməyinizi tələb edəcək. Davam etmək üçün əmin olun ki, aşağıdakıları doğrulaya bilirsiniz:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Güvənilməyən şifrələmə açarları" + }, "changeAtRiskPassword": { "message": "Riskli parolları dəyişdir" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Ödənişsiz təşkilatların ən çox 2 kolleksiyası ola bilər. Daha çox kolleksiya əlavə etmək üçün ödənişli bir plana yüksəldin." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/be/messages.json b/apps/web/src/locales/be/messages.json index 9bb0336777a..0b0b405721f 100644 --- a/apps/web/src/locales/be/messages.json +++ b/apps/web/src/locales/be/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Знешні ідэнтыфікатар можа быць выкарыстаны ў якасці спасылкі для сувязі гэтага рэсурсу са знешняй сістэмай, такой як каталог карыстальніка." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Размясціць калекцыю пад" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn паспяхова правераны! Вы можаце закрыць гэту ўкладку." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Падказка для пароля не можа супадаць з паролем." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Адбітак" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Выдаліць карыстальнiкаў" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/bg/messages.json b/apps/web/src/locales/bg/messages.json index 87396ddfcdc..de23b298710 100644 --- a/apps/web/src/locales/bg/messages.json +++ b/apps/web/src/locales/bg/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Външните идентификатори указват връзката на този елемент с друга система, напр. директорийна услуга с потребители и групи." }, + "ssoExternalId": { + "message": "Външен ИД за еднократно удостоверяване" + }, + "ssoExternalIdDesc": { + "message": "Външният ИД за еднократно удостоверяване е нешифрована връзка между Битуорден и настроеният доставчик на еднократно удостоверяване." + }, "nestCollectionUnder": { "message": "Влагане на колекцията под" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "Успешно удостоверяване чрез WebAuthn!
Можете да затворите този раздел." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Новата парола не може да бъде същата като текущата." + }, "hintEqualsPassword": { "message": "Подсказването за паролата не може да съвпада с нея." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Отпечатък" }, + "fingerprintPhrase": { + "message": "Уникална фраза:" + }, "removeUsers": { "message": "Премахване на потребителите" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Името на организацията не може да бъде по-дълго от 50 знака." }, + "rotationCompletedTitle": { + "message": "Успешна промяна на ключа" + }, + "rotationCompletedDesc": { + "message": "Вашата главна парола и шифриращи ключове бяха променени. Бяхте отписан(а) на другите си устройства." + }, + "trustUserEmergencyAccess": { + "message": "Даване на доверие и потвърждаване на потребителя" + }, + "trustOrganization": { + "message": "Даване на доверие на организацията" + }, + "trust": { + "message": "Даване на доверие" + }, + "doNotTrust": { + "message": "Да не се дава доверие" + }, + "emergencyAccessTrustWarning": { + "message": "С оглед на сигурността на акаунта Ви, потвърдете само, ако сте дали на този потребител достъп за спешни случаи и ако отпечатъкът му съвпада с това, което се вижда в акаунта му" + }, + "orgTrustWarning": { + "message": "С оглед на сигурността на акаунта Ви, продължете само, ако сте член на тази организация, ако възстановяването на акаунта Ви е включено и ако отпечатъкът показан по-долу съвпада с този на организацията." + }, + "trustUser": { + "message": "Даване на доверие на потребителя" + }, "sshKeyWrongPassword": { "message": "Въведената парола е неправилна." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Назначените места превишават наличния брой." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Уникална фраза за $NUM_USERS$ контакти, за които сте включили достъпа за спешни случаи.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Уникална фраза за организацията $ORG_NAME$, за която сте включили възстановяването на акаунти.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Промяната на шифроващите ключове ще изисква да се доверите на ключовете на всяка организация, която може да възстанови акаунта Ви, и на всички контакти, на които сте дали достъп за спешни случаи. За да продължите, уверете се, че можете да потвърдите следното:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Недоверени шифроващи ключове" + }, "changeAtRiskPassword": { "message": "Промяна на парола в риск" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Безплатните организации могат да имат не повече от 2 колекции. Надградете до платен план, ако искате да имате повече колекции." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/bn/messages.json b/apps/web/src/locales/bn/messages.json index 67b602fe256..dc879696b3c 100644 --- a/apps/web/src/locales/bn/messages.json +++ b/apps/web/src/locales/bn/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/bs/messages.json b/apps/web/src/locales/bs/messages.json index 58077510f1e..aea556cde36 100644 --- a/apps/web/src/locales/bs/messages.json +++ b/apps/web/src/locales/bs/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ca/messages.json b/apps/web/src/locales/ca/messages.json index 6ea513b4490..93fa6e5793b 100644 --- a/apps/web/src/locales/ca/messages.json +++ b/apps/web/src/locales/ca/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "L'identificador extern es pot utilitzar com a referència o enllaçar aquest recurs a un sistema extern, com ara un directori d'usuari." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Anida col·lecció sota" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn s'ha verificat correctament! Podeu tancar aquesta pestanya." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "El vostre suggeriment de contrasenya no pot ser el mateix que la vostra contrasenya." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Empremta digital" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Suprimeix usuaris" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Unitat de negoci" + }, + "businessUnits": { + "message": "Unitats de negoci" + }, + "newBusinessUnit": { + "message": "Unitat de negoci nova" } } diff --git a/apps/web/src/locales/cs/messages.json b/apps/web/src/locales/cs/messages.json index fe431b3a1f0..35b0904bda2 100644 --- a/apps/web/src/locales/cs/messages.json +++ b/apps/web/src/locales/cs/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Externí ID je nešifrovaná reference použitá adresářovým konektorem Bitwardenu a API." }, + "ssoExternalId": { + "message": "Externí SSO ID" + }, + "ssoExternalIdDesc": { + "message": "Externí SSO ID je nešifrovaná reference mezi Bitwardenem a Vaším nastaveným poskytovatelem SSO." + }, "nestCollectionUnder": { "message": "Vnořit kolekci pod" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn byl úspěšně ověřen! Můžete zavřít tuto kartu." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Vaše nové heslo nemůže být stejné jako Vaše současné heslo." + }, "hintEqualsPassword": { "message": "Nápověda k Vašemu heslu nemůže být stejná jako Vaše heslo." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Otisk prstu" }, + "fingerprintPhrase": { + "message": "Fráze otisku prstu:" + }, "removeUsers": { "message": "Odebrat uživatele" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Název organizace nesmí přesáhnout 50 znaků." }, + "rotationCompletedTitle": { + "message": "Úspěšná rotace klíče" + }, + "rotationCompletedDesc": { + "message": "Vaše hlavní heslo a šifrovací klíče byly aktualizovány. Vaše další zařízení byla odhlášena." + }, + "trustUserEmergencyAccess": { + "message": "Důvěřovat a potvrdit uživatele" + }, + "trustOrganization": { + "message": "Důvěřovat organizaci" + }, + "trust": { + "message": "Důvěřovat" + }, + "doNotTrust": { + "message": "Nedůvěřovat" + }, + "emergencyAccessTrustWarning": { + "message": "Pro zabezpečení Vašeho účtu potvrďte jen v případě, že jste tomuto uživateli udělili nouzový přístup a jeho otisk prstu odpovídá tomu, co je zobrazeno v jeho účtu." + }, + "orgTrustWarning": { + "message": "Pro zabezpečení Vašeho účtu pokračujte jen v případě, že jste členem této organizace, máte povoleno obnovení účtu a zobrazený otisk prstu níže odpovídá otisku prstu organizace." + }, + "trustUser": { + "message": "Důvěřovat uživateli" + }, "sshKeyWrongPassword": { "message": "Zadané heslo není správné." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Přiřazení uživatelé překračují dostupné uživatele." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fráze otisku prstu pro $NUM_USERS$ kontaktů, pro které jste povolili nouzový přístup.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fráze otisku prstu pro organizaci $ORG_NAME$ , pro kterou jste povolili obnovení účtu.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotace šifrovacích klíčů bude vyžadovat důvěru klíčů všech organizací, které mohou obnovit Váš účet, a všechny kontakty, pro které můžete povolit nouzový přístup. Chcete-li pokračovat, ujistěte se, že můžete ověřit následující:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Nedůvěryhodné šifrovací klíče" + }, "changeAtRiskPassword": { "message": "Změnit ohrožené heslo" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Bezplatné organizace mohou mít až 2 kolekce. Chcete-li přidat více kolekcí, přejděte na placený tarif." + }, + "businessUnit": { + "message": "Obchodní jednotka" + }, + "businessUnits": { + "message": "Obchodní jednotky" + }, + "newBusinessUnit": { + "message": "Nová obchodní jednotka" } } diff --git a/apps/web/src/locales/cy/messages.json b/apps/web/src/locales/cy/messages.json index 4fcd523f0db..69217c7f17b 100644 --- a/apps/web/src/locales/cy/messages.json +++ b/apps/web/src/locales/cy/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/da/messages.json b/apps/web/src/locales/da/messages.json index 525ed048c44..9999432c50d 100644 --- a/apps/web/src/locales/da/messages.json +++ b/apps/web/src/locales/da/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Eksternt ID er en ikke-krypteret reference brugt af Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Placér samling under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn bekræftet Du kan lukke denne fane." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Adgangskodetip og adgangskode må ikke være identiske." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingeraftryk" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Fjern brugere" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organisationsnavn må ikke overstige 50 tegn." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/de/messages.json b/apps/web/src/locales/de/messages.json index edf253fac8b..a517629a5b4 100644 --- a/apps/web/src/locales/de/messages.json +++ b/apps/web/src/locales/de/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Die externe ID ist eine unverschlüsselte Referenz, die vom Bitwarden Directory Connector und der API verwendet wird." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Sammlung verschachteln unter" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn erfolgreich verifiziert! Du kannst diesen Tab nun schließen." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Dein neues Passwort darf nicht dasselbe sein wie dein aktuelles Passwort." + }, "hintEqualsPassword": { "message": "Dein Passwort-Hinweis darf nicht identisch mit deinem Passwort sein." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerabdruck" }, + "fingerprintPhrase": { + "message": "Fingerabdruck-Phrase:" + }, "removeUsers": { "message": "Benutzer entfernen" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Der Name der Organisation darf 50 Zeichen nicht überschreiten." }, + "rotationCompletedTitle": { + "message": "Schlüsselrotation erfolgreich" + }, + "rotationCompletedDesc": { + "message": "Dein Master-Passwort und Verschlüsselungsschlüssel wurden aktualisiert. Deine anderen Geräte wurden abgemeldet." + }, + "trustUserEmergencyAccess": { + "message": "Benutzer vertrauen und bestätigen" + }, + "trustOrganization": { + "message": "Organisation vertrauen" + }, + "trust": { + "message": "Vertrauen" + }, + "doNotTrust": { + "message": "Nicht vertrauen" + }, + "emergencyAccessTrustWarning": { + "message": "Bestätige zur Sicherheit deines Kontos nur, wenn du den Notfallzugriff diesem Benutzer gewährt hast und sein Fingerabdruck mit dem übereinstimmt, was in seinem Konto angezeigt wird" + }, + "orgTrustWarning": { + "message": "Fahre zur Sicherheit deines Kontos nur fort, wenn du ein Mitglied dieser Organisation bist, die Kontowiederherstellung aktiviert hast und der unten angezeigte Fingerabdruck mit dem Fingerabdruck der Organisation übereinstimmt." + }, + "trustUser": { + "message": "Benutzer vertrauen" + }, "sshKeyWrongPassword": { "message": "Dein eingegebenes Passwort ist falsch." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Die zugewiesenen Plätze überschreiten die verfügbaren Plätze." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerabdruck-Phrase für $NUM_USERS$ Kontakte, für die du den Notfallzugriff aktiviert hast.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerabdruck-Phrase für die Organisation $ORG_NAME$, für die du die Kontowiederherstellung aktiviert hast.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Die Rotation deiner Verschlüsselungsschlüssel erfordert, den Schlüsseln aller Organisationen, die dein Konto wiederherstellen können, sowie aller Kontakte, für die du den Notfallzugriff aktiviert hast, zu vertrauen. Um fortzufahren, stelle sicher, dass du Folgendes bestätigen kannst:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Nicht vertrauenswürdige Verschlüsselungsschlüssel" + }, "changeAtRiskPassword": { "message": "Gefährdetes Passwort ändern" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Kostenlose Organisationen können bis zu 2 Sammlungen haben. Upgrade auf ein kostenpflichtiges Abo, um mehr Sammlungen hinzuzufügen." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/el/messages.json b/apps/web/src/locales/el/messages.json index a5a59f4257d..b44892b1276 100644 --- a/apps/web/src/locales/el/messages.json +++ b/apps/web/src/locales/el/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Το εξωτερικό αναγνωριστικό id μπορεί να χρησιμοποιηθεί ως αναφορά ή να συνδέσει αυτόν τον πόρο με ένα εξωτερικό σύστημα, όπως έναν κατάλογο χρηστών." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Ένθεση συλλογής σε" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "Το WebAuthn επαληθεύτηκε επιτυχώς!
Μπορείτε να κλείσετε αυτή την καρτέλα." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Η υπόδειξη κωδικού πρόσβασης, δεν μπορεί να είναι η ίδια με τον κωδικό πρόσβασης σας." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Αποτύπωμα" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Αφαίρεση Χρηστών" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/en_GB/messages.json b/apps/web/src/locales/en_GB/messages.json index 9f755b303bf..daef0bc6945 100644 --- a/apps/web/src/locales/en_GB/messages.json +++ b/apps/web/src/locales/en_GB/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organisation name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organisation" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organisation, have account recovery enabled, and the fingerprint displayed below matches the organisation's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organisation $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organisations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organisations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/en_IN/messages.json b/apps/web/src/locales/en_IN/messages.json index 1349e55f7b1..0804aa60e08 100644 --- a/apps/web/src/locales/en_IN/messages.json +++ b/apps/web/src/locales/en_IN/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "The external ID can be used as a reference or to link this resource to an external system such as a user directory." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove Users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organisation name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organisation" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organisation, have account recovery enabled, and the fingerprint displayed below matches the organisation's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organisation $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organisations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organisations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/eo/messages.json b/apps/web/src/locales/eo/messages.json index 0cafbb8a8ef..33afe669868 100644 --- a/apps/web/src/locales/eo/messages.json +++ b/apps/web/src/locales/eo/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "La ekstera identigilo povas esti uzata kiel referenco aŭ por ligi ĉi tiun rimedon al ekstera sistemo kiel uzantdosierujo." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/es/messages.json b/apps/web/src/locales/es/messages.json index 338cc195c0d..d3f9c608748 100644 --- a/apps/web/src/locales/es/messages.json +++ b/apps/web/src/locales/es/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "El Id externo puede ser usado como una referencia o para enlazar este recurso a un sistema externo, por ejemplo, un directorio de usuario." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Colección anidada bajo" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "¡WebAuthn verificado con éxito! Puede cerrar esta pestaña." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "La pista de su contraseña no puede ser la misma que la contraseña." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Huella digital" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Eliminar usuarios" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/et/messages.json b/apps/web/src/locales/et/messages.json index 9c2c407d3e2..b5ed1f22f61 100644 --- a/apps/web/src/locales/et/messages.json +++ b/apps/web/src/locales/et/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Välist Id-d kasutatakse viitena või näiteks selleks, et siduda need ressursid välise süsteemiga, nagu näites kasutaja kataloog." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Lisa kogumike jaotisesse" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn on edukalt kinnitatud! Võid selle vahelehe sulgeda." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Parooli vihje ei saa olla sama mis parool ise." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Sõrmejälg" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Kasutajate eemaldamine" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/eu/messages.json b/apps/web/src/locales/eu/messages.json index e6576e40664..06a13bb6765 100644 --- a/apps/web/src/locales/eu/messages.json +++ b/apps/web/src/locales/eu/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Kanpoko Id-a erreferentzia gisa erabil daiteke edo baliabide hori kanpoko sistema batekin lotzeko, erabiltzaileen direktorio gisa adibidez." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn behar bezala egiaztatu da! Fitxa hau itxi dezakezu." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Zure pasahitza ezin da izan zure pasahitzaren pistaren berdina." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Hatz-marka" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Kendu erabiltzaileak" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/fa/messages.json b/apps/web/src/locales/fa/messages.json index 143ac5f9c32..5e37f707f0c 100644 --- a/apps/web/src/locales/fa/messages.json +++ b/apps/web/src/locales/fa/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "شناسه خارجی می‌تواند به عنوان یک مرجع یا برای پیوند دادن این منبع به یک سیستم خارجی مانند فهرست کاربری استفاده شود." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "مجموعه لانه زیر" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn با موفقیت تأیید شد! می‌توانید این برگه را ببندید." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "اشاره به کلمه عبور شما نمی‌تواند همان کلمه عبور شما باشد." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "اثر انگشت" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "حذف کاربرها" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/fi/messages.json b/apps/web/src/locales/fi/messages.json index 9612c8cb4ad..b5b5108aa14 100644 --- a/apps/web/src/locales/fi/messages.json +++ b/apps/web/src/locales/fi/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Ulkoinen ID on Bitwarden Directory Connectin ja API:n käyttämä salaamaton viite." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Sijoita kokoelma seuraavan alle:" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn-todennus onnistui! Voit sulkea välilehden." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Salasanavihjeesi ei voi olla sama kuin salasanasi." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Sormenjälki" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Poista käyttäjiä" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "Syöttämäsi salasana on virheellinen." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Vaihda vaarantunut salasana" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/fil/messages.json b/apps/web/src/locales/fil/messages.json index a6b82cc1902..04f97960ccf 100644 --- a/apps/web/src/locales/fil/messages.json +++ b/apps/web/src/locales/fil/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Ang Panlabas na ID ay isang hindi naka encrypt na sanggunian na ginagamit ng Bitwarden Directory Connector at API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest koleksyon sa ilalim ng" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "Matagumpay na na-verify ng WebAuthn! Maaari mong isara ang tab na ito." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Hindi pwedeng maging pareho ang password hint at password mo." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Tanggalin ang mga gumagamit" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/fr/messages.json b/apps/web/src/locales/fr/messages.json index df113c1e988..0f6969aa333 100644 --- a/apps/web/src/locales/fr/messages.json +++ b/apps/web/src/locales/fr/messages.json @@ -1882,7 +1882,7 @@ "message": "Procédez ci-dessous pour que Bitwarden vous envoie des courriels de vérification lorsque vous vous connectez à partir d'un nouvel appareil." }, "turnOffNewDeviceLoginProtectionWarning": { - "message": "Avec la protection de connexion d'un nouvel appareil désactivée, toute personne ayant votre mot de passe maître peut accéder à votre compte depuis n'importe quel appareil. Pour protéger votre compte sans courriel de vérification, configurez la connexion en deux étapes." + "message": "Avec la protection de connexion d'un nouvel appareil désactivée, toute personne ayant votre mot de passe principal peut accéder à votre compte depuis n'importe quel appareil. Pour protéger votre compte sans courriel de vérification, configurez la connexion en deux étapes." }, "accountNewDeviceLoginProtectionSaved": { "message": "Modifications de la protection de connexion de l'appareil enregistrées" @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "L’identifiant externe peut être utilisé comme référence ou pour lier cette ressource à un système externe tel qu’un répertoire utilisateur." }, + "ssoExternalId": { + "message": "ID externe SSO" + }, + "ssoExternalIdDesc": { + "message": "ID externe SSO est une référence non chiffrée entre Bitwarden et votre fournisseur SSO configuré." + }, "nestCollectionUnder": { "message": "Collection imbriquée sous" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn vérifié avec succès ! Vous pouvez fermer cet onglet." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Votre nouveau mot de passe ne peut être le même que votre mot de passe actuel." + }, "hintEqualsPassword": { "message": "Votre indice de mot de passe ne peut pas être identique à votre mot de passe." }, @@ -5722,7 +5731,7 @@ } }, "eventAdminPasswordReset": { - "message": "Réinitialisation du mot de passe maître pour l'utilisateur $ID$.", + "message": "Réinitialisation du mot de passe principal pour l'utilisateur $ID$.", "placeholders": { "id": { "content": "$1", @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Empreinte" }, + "fingerprintPhrase": { + "message": "Phrase d'empreinte :" + }, "removeUsers": { "message": "Supprimer les utilisateurs" }, @@ -8388,7 +8400,7 @@ "message": "Appareils de confiance" }, "memberDecryptionOptionTdeDescPart1": { - "message": "Les membres n'auront pas besoin d'un mot de passe maître lors de la connexion avec SSO. Le mot de passe principal est remplacé par une clé de chiffrement stockée sur le périphérique, ce qui rend ce périphérique fiable. Le premier appareil avec lequel un membre créera son compte et se connectera sera fiable. Les nouveaux appareils devront être approuvés par un périphérique de confiance existant ou par un administrateur. La", + "message": "Les membres n'auront pas besoin d'un mot de passe principale lors de la connexion avec SSO. Le mot de passe principal est remplacé par une clé de chiffrement stockée sur le périphérique, ce qui rend ce périphérique fiable. Le premier appareil avec lequel un membre créera son compte et se connectera sera fiable. Les nouveaux appareils devront être approuvés par un périphérique de confiance existant ou par un administrateur. La", "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Members will not need a master password when logging in with SSO. Master password is replaced with an encryption key stored on the device, making that device trusted. The first device a member creates their account and logs into will be trusted. New devices will need to be approved by an existing trusted device or by an administrator. The single organization policy, SSO required policy, and account recovery administration policy will turn on when this option is used.'" }, "memberDecryptionOptionTdeDescLink1": { @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Le nom de l'organisation ne doit pas dépasser 50 caractères." }, + "rotationCompletedTitle": { + "message": "Rotation de la clé réussie" + }, + "rotationCompletedDesc": { + "message": "Votre mot de passe principal et vos clés de chiffrement ont été mis à jour. Vos autres appareils ont été déconnectés." + }, + "trustUserEmergencyAccess": { + "message": "Faire confiance et confirmer l'utilisateur" + }, + "trustOrganization": { + "message": "Faire confiance à l'organisation" + }, + "trust": { + "message": "Faire confiance" + }, + "doNotTrust": { + "message": "Ne pas faire confiance" + }, + "emergencyAccessTrustWarning": { + "message": "Pour la sécurité de votre compte, confirmez seulement si vous avez accordé l'accès d'urgence à cet utilisateur et que sa phrase d'empreinte correspond à ce qui est affiché dans son compte" + }, + "orgTrustWarning": { + "message": "Pour la sécurité de votre compte, continuez seulement si vous êtes un membre de cette organisation, avez la récupération de compte activée et que la phrase d'empreinte correspond à celle de l'organisation." + }, + "trustUser": { + "message": "Faire confiance à l'utilisateur" + }, "sshKeyWrongPassword": { "message": "Le mot de passe que vous avez entré est incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Les places assignées dépassent les places disponibles." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Phrase d'empreinte des $NUM_USERS$ contacts pour lesquels vous avez activé l'accès d'urgence.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Phrase d'empreinte de l'organisation $ORG_NAME$ pour laquelle vous avez activé la récupération de compte.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Faire la rotation de vos clés exige que vous fassiez confiance aux clés de toutes les organisations qui peuvent récupérer votre compte et à tous les contacts à qui vous avez autorsé l'accès d'urgence. Pour continuer, assurez-vous que vous pouvez vérifier ce qui suit :" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Clés de chiffrement non fiables" + }, "changeAtRiskPassword": { "message": "Changer le mot de passe à risque" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Les organisations gratuites peuvent avoir jusqu'à 2 collections. Passez à une offre payante pour ajouter plus de collections." + }, + "businessUnit": { + "message": "Unité d'affaires" + }, + "businessUnits": { + "message": "Unités d’affaires" + }, + "newBusinessUnit": { + "message": "Nouvelle unité d'affaires" } } diff --git a/apps/web/src/locales/gl/messages.json b/apps/web/src/locales/gl/messages.json index c7a62c4fd60..33aec61c9ad 100644 --- a/apps/web/src/locales/gl/messages.json +++ b/apps/web/src/locales/gl/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/he/messages.json b/apps/web/src/locales/he/messages.json index 13cecb8f4dc..ee7f464b9fd 100644 --- a/apps/web/src/locales/he/messages.json +++ b/apps/web/src/locales/he/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "מזהה חיצוני הוא הפניה לא מוצפנת בשימוש על ידי מחבר הספריות וה־API של Bitwarden." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "לקנן אוסף תחת" }, @@ -3971,7 +3977,7 @@ "message": "כדי לערוך את כתובת הדוא\"ל שלך." }, "view": { - "message": "צפה" + "message": "הצג" }, "invalidDateRange": { "message": "טווח תאריכים לא חוקי." @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn אומת בהצלחה! אתה רשאי לסגור כרטיסיה זו." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "רמז הסיסמה שלך לא יכול להיות אותו הדבר כמו הסיסמה שלך." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "טביעת אצבע" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "הסר משתמשים" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "שם ארגון לא יכול לחרוג מ־50 תווים." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "הסיסמה שהזנת שגויה." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "מקומות מוקצים עולים על מקומות פנויים." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "שנה סיסמה בסיכון" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "לארגונים חינמיים יכולים להיות עד 2 אוספים. שדרג לתוכנית בתשלום כדי להוסיף עוד אוספים." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/hi/messages.json b/apps/web/src/locales/hi/messages.json index 5e71c274ed9..2ffc414866e 100644 --- a/apps/web/src/locales/hi/messages.json +++ b/apps/web/src/locales/hi/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/hr/messages.json b/apps/web/src/locales/hr/messages.json index 7ab29545495..e5121050ed8 100644 --- a/apps/web/src/locales/hr/messages.json +++ b/apps/web/src/locales/hr/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Vanjski id je nešifrirana referenca koju koristi Bitwarden Directory Connector i API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Ugnijezdi zbirku pod" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn uspješno ovjeren! Možeš zatvoriti ovu karticu." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Podsjetnik za lozinku ne može biti isti kao lozinka." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Otisak prsta" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Ukloni korisnike" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Naziv organizacije ne može biti duži od 50 znakova." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "Unesena lozinka nije ispravna." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Dodijeljene licence premašuju dostupne licence." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Promijeni rizičnu lozinku" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Besplatne organizacije mogu imati do 2 zbirke. Nadogradi na plaćeni plan za dodavanje više zbirki." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/hu/messages.json b/apps/web/src/locales/hu/messages.json index dc50065f5d3..266783e836f 100644 --- a/apps/web/src/locales/hu/messages.json +++ b/apps/web/src/locales/hu/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "A külső azonosító a Bitwarden tárkapcsoló és API által nem titkosított referencia." }, + "ssoExternalId": { + "message": "SSO külső azonosító" + }, + "ssoExternalIdDesc": { + "message": "Az SSO külső azonosító egy titkosítatlan hivatkozás a Bitwarden és az jelenleg konfigurált SSO szolgáltató között." + }, "nestCollectionUnder": { "message": "Gyűjtemény beágyazása:" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "A WebAuthn sikeresen ellenőrzésre került.! A fül már bezárható." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Az új jelszó nem lehet azonos a jelenlegi jelszóval." + }, "hintEqualsPassword": { "message": "A jelszavas tipp nem lehet azonos a jelszóval." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Ujjlenyomat" }, + "fingerprintPhrase": { + "message": "Ujjlenyomat kifejezés:" + }, "removeUsers": { "message": "Felhasználók eltávolítása" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "A szervezet neve nem haladhatja meg az 50 karaktert." }, + "rotationCompletedTitle": { + "message": "A kulcsforgatás sikeres volt." + }, + "rotationCompletedDesc": { + "message": "A mesterjelszó és a titkosítási kulcsok frissítésre kerültek. A többi eszköz kijelentkeztetésre került." + }, + "trustUserEmergencyAccess": { + "message": "Bizalom és megerősítés a felhasználónál" + }, + "trustOrganization": { + "message": "Bizalom a szervezetnél" + }, + "trust": { + "message": "Bizalom" + }, + "doNotTrust": { + "message": "Nincs bizalom" + }, + "emergencyAccessTrustWarning": { + "message": "A ióka biztonság érdekében csak akkor erősítsük meg, ha vészhelyzeti hozzáférést biztosítottunk ehhez a felhasználóhoz és az ujjlenyomata megegyezik a fiókban megjelenítettekkel." + }, + "orgTrustWarning": { + "message": "A fiók biztonsága érdekében csak akkor folytassuk, ha tagja vagyunk ennek a szervezetnek, engedélyezve van a fiók helyreállítása és az alább megjelenített ujjlenyomat megegyezik a szervezet ujjlenyomatával." + }, + "trustUser": { + "message": "Bizalom a felhasználónál" + }, "sshKeyWrongPassword": { "message": "A megadott jelszó helytelen." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "A hozzárendelt helyek száma meghaladja a rendelkezésre álló helyek számát." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Ujjlenyomat kifejezés $NUM_USERS$ kapcsolathoz, amelyeknél engedélyeztük a vészhelyzeti hozzáférést.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Ujjlenyomat kifejezés $ORG_NAME$ szervezethez, amelyhez engedélyeztük a fiók helyreállítást.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "A titkosítási kulcsok forgatásához meg kell bízni minden olyan szervezet kulcsában, amely vissza tudja állítani fiókját és minden olyan kapcslatban, amelyhez engedélyeztük a vészhelyzeti hozzáférést. A folytatáshoz győződjünk meg arról, hogy ellenőrizhetjük a következőket:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Megbízhatatlan titkosítási kulcsok" + }, "changeAtRiskPassword": { "message": "Kockázatos jelszó megváltoztatása" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Az ingyenes szervezeteknek legfeljebb 2 gyűjteményük lehet. Térjünk át egy fizetett csomagra további gyűjtemények hozzáadásához." + }, + "businessUnit": { + "message": "Üzleti egység" + }, + "businessUnits": { + "message": "Üzleti egységek" + }, + "newBusinessUnit": { + "message": "Új üzleti egység" } } diff --git a/apps/web/src/locales/id/messages.json b/apps/web/src/locales/id/messages.json index d62c1dfde53..85d6795e9c1 100644 --- a/apps/web/src/locales/id/messages.json +++ b/apps/web/src/locales/id/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Id eksternal dapat digunakan sebagai referensi atau untuk menautkan sumber daya ini ke sistem eksternal seperti direktori pengguna." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn sudah diverifikasi dengan sukses. Anda dapat menutup tab ini." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Petunjuk kata sandi Anda tidak boleh sama dengan kata sandi Anda." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Sidik Jari" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Hapus pengguna" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/it/messages.json b/apps/web/src/locales/it/messages.json index 9a0ece95033..893eed1b846 100644 --- a/apps/web/src/locales/it/messages.json +++ b/apps/web/src/locales/it/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "L'ID esterno è un riferimento non crittografato usato da Bitwarden Directory Connector e API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Annida raccolta sotto" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verificato! Puoi chiudere questa scheda." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Il suggerimento per la password non può essere uguale alla tua password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Impronta" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Rimuovi utenti" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Il nome dell'organizzazione non può superare i 50 caratteri." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "La parola d'accesso inserita non è corretta." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "I posti assegnati superano i posti disponibili." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Cambia parola d'accesso a rischio" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Le organizzazioni gratuite possono avere fino a 2 raccolte. Aggiorna ad un piano a pagamento per crearne di più." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ja/messages.json b/apps/web/src/locales/ja/messages.json index 8eb0745bbc1..b9d113b98cd 100644 --- a/apps/web/src/locales/ja/messages.json +++ b/apps/web/src/locales/ja/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "外部 ID は参照用や、ユーザーディレクトリーなどの外部システムへリソースをリンクするために使用できます。" }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "コレクションを入れ子にする" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn が正常に認証されました!このタブを閉じることができます。" }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "パスワードのヒントをパスワードと同じにすることはできません。" }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "指紋" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "ユーザーを削除" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "入力されたパスワードが間違っています。" }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "危険なパスワードの変更" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "無料版の組織ではコレクションは 2 つまでです。さらにコレクションを追加するには有料プランにアップグレードしてください。" + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ka/messages.json b/apps/web/src/locales/ka/messages.json index ed327aff81c..ede2850a6e4 100644 --- a/apps/web/src/locales/ka/messages.json +++ b/apps/web/src/locales/ka/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/km/messages.json b/apps/web/src/locales/km/messages.json index 775494830de..293b3b0486f 100644 --- a/apps/web/src/locales/km/messages.json +++ b/apps/web/src/locales/km/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/kn/messages.json b/apps/web/src/locales/kn/messages.json index 88edbda5e7b..9074ab87052 100644 --- a/apps/web/src/locales/kn/messages.json +++ b/apps/web/src/locales/kn/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "ಬಾಹ್ಯ ಐಡಿಯನ್ನು ಉಲ್ಲೇಖವಾಗಿ ಬಳಸಬಹುದು ಅಥವಾ ಈ ಸಂಪನ್ಮೂಲವನ್ನು ಬಳಕೆದಾರರ ಡೈರೆಕ್ಟರಿಯಂತಹ ಬಾಹ್ಯ ವ್ಯವಸ್ಥೆಗೆ ಲಿಂಕ್ ಮಾಡಬಹುದು." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn ಯಶಸ್ವಿಯಾಗಿ ಪರಿಶೀಲಿಸಲಾಗಿದೆ! ನೀವು ಈ ಟ್ಯಾಬ್ ಅನ್ನು ಮುಚ್ಚಬಹುದು." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ನಂತೆಯೇ ಇರಬಾರದು." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "ಫಿಂಗರ್‌ಪ್ರಿಂಟ್" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಿ" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ko/messages.json b/apps/web/src/locales/ko/messages.json index 355d1cc08cf..b0868c3e601 100644 --- a/apps/web/src/locales/ko/messages.json +++ b/apps/web/src/locales/ko/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "외부 Id는 참조로 사용되거나 사용자 디렉토리같은 외부 시스템에 리소스를 링크할 수 있습니다." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn 인증을 성공적으로 완료했습니다!
이제 이 탭을 닫아도 좋습니다." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "비밀번호 힌트는 비밀번호와 같을 수 없습니다." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "지문" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "사용자 삭제" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/lv/messages.json b/apps/web/src/locales/lv/messages.json index dceb9b2be60..fba3376ac06 100644 --- a/apps/web/src/locales/lv/messages.json +++ b/apps/web/src/locales/lv/messages.json @@ -1124,7 +1124,7 @@ "message": "Izmantota šifrēšanai" }, "loginWithPasskeyEnabled": { - "message": "Pieteikšanās ar piekūves atslēgu ieslēgta" + "message": "Pieteikšanās ar piekļuves atslēgu ieslēgta" }, "passkeySaved": { "message": "$NAME$ saglabāta", @@ -1327,7 +1327,7 @@ "message": "E-pasta adrese" }, "yourVaultIsLockedV2": { - "message": "Glabātava ir slēgta." + "message": "Glabātava ir aizslēgta" }, "yourAccountIsLocked": { "message": "Konts ir slēgts" @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Ārējo ID var izmanto kā atsauci vai kā saikni starp šo līdzekli un ārēju sistēmu, piemēram, lietotāju direktoriju." }, + "ssoExternalId": { + "message": "SSO ārējais Id" + }, + "ssoExternalIdDesc": { + "message": "SSO ārējais Id ir nešifrēta atsauce starp Bitwarden un konfigurēto SSO nodrošinātāju." + }, "nestCollectionUnder": { "message": "Ievietot krājumu zem" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn tika veiksmīgi apstiprināts.
Šo cilni var aizvērt." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Jaunā parole nevar būt tāda pati kā pašreizējā." + }, "hintEqualsPassword": { "message": "Paroles norāde nedrīkst būt tāda pati kā parole." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Pirkstu nospiedums" }, + "fingerprintPhrase": { + "message": "Atpazīšanas vārdkopa:" + }, "removeUsers": { "message": "Noņemt lietotājus" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Apvienības nosaukums nevar pārsniegt 50 rakstzīmes." }, + "rotationCompletedTitle": { + "message": "Atslēgu nomaiņa sekmīga" + }, + "rotationCompletedDesc": { + "message": "Galvenā parole un šifrēšanas atslēgas tika atjauninātas. Citās ierīcēs ir notikusi atteikšanās." + }, + "trustUserEmergencyAccess": { + "message": "Uzticēties un apstiprināt lietotāju" + }, + "trustOrganization": { + "message": "Uzticēties apvienībai" + }, + "trust": { + "message": "Uzticēties" + }, + "doNotTrust": { + "message": "Neuzticēties" + }, + "emergencyAccessTrustWarning": { + "message": "Lai nodrošinātu sava konta drošību, jāapstiprina tikai tad, ja šim lietotājam ir nodrošināta ārkārtas piekļuve un tā pirkstu nospiedums atbilsta tam, kas ir attēlots tā kontā" + }, + "orgTrustWarning": { + "message": "Lai nodrošinātu sava konta drošību, jāturpina tikai tad, ja esi šīs apvienības dalībnieks, ir iespējota konta atkope un zemāk attēlotais pirkstu nospiedums atbilst apvienības pirkstu nospiedumam." + }, + "trustUser": { + "message": "Uzticēties lietotājam" + }, "sshKeyWrongPassword": { "message": "Ievadītā parole ir nepareiza." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Piešķirtās vietas pārsniedz pieejamās vietas." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Atpazīšanas vārdkopa $NUM_USERS$ kontaktpersonām, kurām ir iespējota ārkārtas piekļuve.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Atpazīšanas vārdkopa apvienībai $ORG_NAME$, kurā ir iespējota konta atkope.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Savu šifrēšanas atslēgu nomaiņai būs nepieciešams uzticēties jebkuras apvienības, kura var atkopt kontu, un kontaktpersonas, kurai ir iespējota ārkārtas piekļuve, atslēgām. Lai turpinātu, jāpārliecināš, ka var apliecināt šo:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Neuzticamas šifrēšanas atslēgas" + }, "changeAtRiskPassword": { "message": "Mainīt riskam pakļautu paroli" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Apvienībās, kuras izmanto Bitwarden bez maksas, var būt līdz 2 krājumiem. Jāpāriet uz maksas plānu, lai pievienotu vairāk krājumu." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ml/messages.json b/apps/web/src/locales/ml/messages.json index 5876b486bbf..620d1285e65 100644 --- a/apps/web/src/locales/ml/messages.json +++ b/apps/web/src/locales/ml/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "ബാഹ്യ ഐഡി ഒരു റഫറൻസായി ഉപയോഗിക്കാം അല്ലെങ്കിൽ ഈ ഉറവിടം ഒരു ഉപയോക്തൃ ഡയറക്ടറി പോലുള്ള ഒരു ബാഹ്യ സിസ്റ്റത്തിലേക്ക് ലിങ്കുചെയ്യാൻ കഴിയും." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/mr/messages.json b/apps/web/src/locales/mr/messages.json index 775494830de..293b3b0486f 100644 --- a/apps/web/src/locales/mr/messages.json +++ b/apps/web/src/locales/mr/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/my/messages.json b/apps/web/src/locales/my/messages.json index 775494830de..293b3b0486f 100644 --- a/apps/web/src/locales/my/messages.json +++ b/apps/web/src/locales/my/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/nb/messages.json b/apps/web/src/locales/nb/messages.json index c68d1bf2961..c31140eb136 100644 --- a/apps/web/src/locales/nb/messages.json +++ b/apps/web/src/locales/nb/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Den eksterne Id-en kan brukes som referanse eller for å koble denne ressursen til et eksternt system, for eksempel en brukerkatalog." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Plasser samling under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn bekreftet vellykket! Du kan lukke denne fanen." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Passordhintet ditt kan ikke være det samme som passordet ditt." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingeravtrykk" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Fjern brukere" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ne/messages.json b/apps/web/src/locales/ne/messages.json index f64cfab4ba1..6052556f397 100644 --- a/apps/web/src/locales/ne/messages.json +++ b/apps/web/src/locales/ne/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/nl/messages.json b/apps/web/src/locales/nl/messages.json index 93eca761180..22eb954f5c4 100644 --- a/apps/web/src/locales/nl/messages.json +++ b/apps/web/src/locales/nl/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Je kunt het externe ID gebruiken als referentie of om een koppeling te leggen tussen deze bron en een extern systeem zoals een directory met gebruikers." }, + "ssoExternalId": { + "message": "SSO extern ID" + }, + "ssoExternalIdDesc": { + "message": "SSO Extern ID is een niet-versleutelde referentie tussen Bitwarden en je geconfigureerde SSO-provider." + }, "nestCollectionUnder": { "message": "Plaats collectie onder" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn met succes geverifieerd! Je kunt dit tabblad sluiten." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Je nieuwe wachtwoord moet anders zijn dan je huidige wachtwoord." + }, "hintEqualsPassword": { "message": "Je wachtwoordhint moet anders zijn dan je wachtwoord." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Vingerafdruk" }, + "fingerprintPhrase": { + "message": "Vingerafdrukzin:" + }, "removeUsers": { "message": "Gebruikers verwijderen" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organisatienaam mag niet langer zijn dan 50 tekens." }, + "rotationCompletedTitle": { + "message": "Sleutelrotatie geslaagd" + }, + "rotationCompletedDesc": { + "message": "Je hoofdwachtwoord en encryptiesleutels zijn bijgewerkt. Je andere apparaten zijn uitgelogd." + }, + "trustUserEmergencyAccess": { + "message": "Gebruiker vertrouwen en bevestigen" + }, + "trustOrganization": { + "message": "Organisatie vertrouwen" + }, + "trust": { + "message": "Vertrouwen" + }, + "doNotTrust": { + "message": "Niet vertrouwen" + }, + "emergencyAccessTrustWarning": { + "message": "Bevestig, voor de veiligheid van je account, alleen als je noodtoegang hebt verleend aan deze gebruiker en de vingerafdruk voldoet aan wat er in hun account wordt weergegeven" + }, + "orgTrustWarning": { + "message": "Ga, voor de veiligheid van je account, alleen verder als je lid bent van deze organisatie, accountherstel hebt ingeschakeld en de hieronder weergegeven vingerafdruk overeenkomt met de vingerafdruk van de organisatie." + }, + "trustUser": { + "message": "Gebruiker vertrouwen" + }, "sshKeyWrongPassword": { "message": "Het door jou ingevoerde wachtwoord is onjuist." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Meer toegewezen dan beschikbare plaatsen." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Vingerafdrukzin voor $NUM_USERS$ contacten waarvoor je noodtoegang hebt ingeschakeld.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Vingerafdrukzin voor de organisatie $ORG_NAME$ waarvoor je accountherstel hebt ingeschakeld.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Het roteren van je encryptiesleutels vereist dat je sleutels vertrouwt van alle organisaties die je account kunnen herstellen en alle contacten waarvoor je noodtoegang hebt ingeschakeld. Zorg ervoor dat je het volgende kunt verifiëren:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Niet-vertrouwde encryptiesleutels" + }, "changeAtRiskPassword": { "message": "Risicovol wachtwoord wijzigen" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Gratis organisaties kunnen maximaal twee collecties hebben. Upgrade naar een betaald abonnement voor het toevoegen van meer collecties." + }, + "businessUnit": { + "message": "Bedrijfseenheid" + }, + "businessUnits": { + "message": "Bedrijfseenheden" + }, + "newBusinessUnit": { + "message": "Nieuwe bedrijfseenheid" } } diff --git a/apps/web/src/locales/nn/messages.json b/apps/web/src/locales/nn/messages.json index c50af10221a..41d012ac3e9 100644 --- a/apps/web/src/locales/nn/messages.json +++ b/apps/web/src/locales/nn/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/or/messages.json b/apps/web/src/locales/or/messages.json index 775494830de..293b3b0486f 100644 --- a/apps/web/src/locales/or/messages.json +++ b/apps/web/src/locales/or/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/pl/messages.json b/apps/web/src/locales/pl/messages.json index b4b4c90d44a..7fa157e523c 100644 --- a/apps/web/src/locales/pl/messages.json +++ b/apps/web/src/locales/pl/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Zewnętrzny identyfikator może zostać użyty jako odniesienie lub połączenie tego zasobu z zewnętrznym systemem, takim jak katalog użytkowników." }, + "ssoExternalId": { + "message": "Zewnętrzny identyfikator SSO" + }, + "ssoExternalIdDesc": { + "message": "Zewnętrzny identyfikator SSO jest niezaszyfrowanym odniesieniem między Bitwarden a Twoim skonfigurowanym dostawcą SSO." + }, "nestCollectionUnder": { "message": "Zagnieźdź kolekcję pod" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "Uwierzytelnianie WebAuthn zostało zweryfikowane! Możesz zamknąć tę kartę." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Twoje nowe hasło nie może być takie samo jak Twoje aktualne hasło." + }, "hintEqualsPassword": { "message": "Podpowiedź do hasła nie może być taka sama jak hasło." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Unikalny identyfikator konta" }, + "fingerprintPhrase": { + "message": "Fraza odcisku palca:" + }, "removeUsers": { "message": "Usuń użytkowników" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Nazwa organizacji nie może przekraczać 50 znaków." }, + "rotationCompletedTitle": { + "message": "Rotacja klucza powiodło się" + }, + "rotationCompletedDesc": { + "message": "Twoje hasło główne i klucze szyfrowania zostały zaktualizowane. Twoje inne urządzenia zostały wylogowane." + }, + "trustUserEmergencyAccess": { + "message": "Zaufaj i potwierdź użytkownika" + }, + "trustOrganization": { + "message": "Zaufaj organizacji" + }, + "trust": { + "message": "Zaufaj" + }, + "doNotTrust": { + "message": "Nie ufaj" + }, + "emergencyAccessTrustWarning": { + "message": "Dla bezpieczeństwa Twojego konta potwierdź tylko, jeśli przyznano temu użytkownikowi dostęp awaryjny i jego odcisk palca pasuje do tego, co widnieje na jego koncie" + }, + "orgTrustWarning": { + "message": "Dla zapewnienia bezpieczeństwa konta kontynuuj tylko wtedy, gdy jesteś członkiem tej organizacji, włączono odzyskiwanie konta, a odcisk palca wyświetlany poniżej pasuje do odcisku palca organizacji." + }, + "trustUser": { + "message": "Zaufaj użytkownikowi" + }, "sshKeyWrongPassword": { "message": "Wprowadzone hasło jest nieprawidłowe." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Przydzielone miejsca przekraczają dostępne miejsca." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fraza odcisku palca dla $NUM_USERS$ kontaktów, dla których włączono dostęp awaryjny.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fraza odcisku palca dla organizacji $ORG_NAME$ dla której włączyłeś odzyskiwanie konta.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotacja kluczy szyfrowania będzie wymagała zaufanych kluczy każdej organizacji, która może odzyskać Twoje konto oraz wszystkich kontaktów, które mają udostępniony dostęp awaryjny. Aby kontynuować, upewnij się, że możesz zweryfikować następujące elementy:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Niezaufane klucze szyfrowania" + }, "changeAtRiskPassword": { "message": "Zmień hasło zagrożone" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Darmowe organizacje mogą posiadać maksymalnie 2 kolekcje. Aby dodać więcej kolekcji, przejdź na plan płatny." + }, + "businessUnit": { + "message": "Jednostka Biznesowa" + }, + "businessUnits": { + "message": "Jednostki Biznesowe" + }, + "newBusinessUnit": { + "message": "Nowa jednostka biznesowa" } } diff --git a/apps/web/src/locales/pt_BR/messages.json b/apps/web/src/locales/pt_BR/messages.json index 1b89aa405f0..4cb7f19a1fc 100644 --- a/apps/web/src/locales/pt_BR/messages.json +++ b/apps/web/src/locales/pt_BR/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "O ID externo pode ser usado como referência ou vincular esse recurso a um sistema externo, como um diretório de usuários." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Aninhar coleção em" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verificado com sucesso!
Você pode fechar esta guia." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Sua nova senha não pode ser a mesma que a sua atual." + }, "hintEqualsPassword": { "message": "Sua dica de senha senha não pode ser a mesma que a sua senha." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Impressão digital" }, + "fingerprintPhrase": { + "message": "Frase biométrica:" + }, "removeUsers": { "message": "Remover Usuários" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "O nome da organização não pode exceder 50 caracteres." }, + "rotationCompletedTitle": { + "message": "Rotação de chave bem-sucedida" + }, + "rotationCompletedDesc": { + "message": "Sua senha mestra e chave de criptografia foram atualizadas. Seus outros dispositivos foram desconectados." + }, + "trustUserEmergencyAccess": { + "message": "Confiar e confirmar usuário" + }, + "trustOrganization": { + "message": "Organização de confiança" + }, + "trust": { + "message": "Confiança" + }, + "doNotTrust": { + "message": "Não confiar" + }, + "emergencyAccessTrustWarning": { + "message": "Para a segurança de sua conta, só confirme se você concedeu acesso de emergência a este usuário e sua impressão digital corresponde ao que é exibido na conta dele" + }, + "orgTrustWarning": { + "message": "Para a segurança da sua conta, prossiga somente se você for um membro desta organização, tem a recuperação de conta ativada, e a impressão digital exibida abaixo corresponde à impressão digital da organização." + }, + "trustUser": { + "message": "Confiar no usuário" + }, "sshKeyWrongPassword": { "message": "A senha está incorreta." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Os assentos atribuídos excedem os disponíveis." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Frase de impressão digital para contatos $NUM_USERS$ para os quais você ativou o acesso de emergência.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Frase de impressão digital para a organização $ORG_NAME$ para a qual você ativou a recuperação de conta.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Girar suas chaves de criptografia exigirá que você confie nas chaves de qualquer organização que possa recuperar sua conta, e quaisquer contatos que você ativou o acesso de emergência. Para continuar, certifique-se de que pode verificar o seguinte:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Chaves criptográficas não confiáveis" + }, "changeAtRiskPassword": { "message": "Alterar senhas vulneráveis" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Organizações gratuitas podem ter até duas coleções. Faça o upgrade para um plano pago para adicionar mais coleções." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/pt_PT/messages.json b/apps/web/src/locales/pt_PT/messages.json index d45484af588..3840d5fd0fd 100644 --- a/apps/web/src/locales/pt_PT/messages.json +++ b/apps/web/src/locales/pt_PT/messages.json @@ -3318,10 +3318,16 @@ "message": "Atenção! Este utilizador necessita do Key Connector para gerir a sua encriptação. Ao remover este utilizador da sua organização desativará permanentemente a sua conta. Esta ação não pode ser anulada. Deseja prosseguir?" }, "externalId": { - "message": "ID externa" + "message": "ID externo" }, "externalIdDesc": { - "message": "A ID externa é uma referência não encriptada utilizada pelo Bitwarden Directory Connector e pela API." + "message": "O ID externo é uma referência desencriptada utilizada pelo Bitwarden Directory Connector e pela API." + }, + "ssoExternalId": { + "message": "ID externo SSO" + }, + "ssoExternalIdDesc": { + "message": "O ID externo SSO é uma referência desencriptada entre o Bitwarden e o seu fornecedor de SSO configurado." }, "nestCollectionUnder": { "message": "Aninhar coleção em" @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verificado com sucesso! Pode fechar este separador." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "A sua nova palavra-passe não pode ser igual à sua palavra-passe atual." + }, "hintEqualsPassword": { "message": "A dica da sua palavra-passe não pode ser igual à sua palavra-passe." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Impressão digital" }, + "fingerprintPhrase": { + "message": "Frase de impressão digital:" + }, "removeUsers": { "message": "Remover utilizadores" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "O nome da organização não pode exceder 50 carateres." }, + "rotationCompletedTitle": { + "message": "Rotação de chaves bem-sucedida" + }, + "rotationCompletedDesc": { + "message": "A sua palavra-passe mestra e as chaves de encriptação foram atualizadas. Foi terminada a sessão nos seus outros dispositivos." + }, + "trustUserEmergencyAccess": { + "message": "Confiar e confirmar o utilizador" + }, + "trustOrganization": { + "message": "Confiar na organização" + }, + "trust": { + "message": "Confiar" + }, + "doNotTrust": { + "message": "Não confiar" + }, + "emergencyAccessTrustWarning": { + "message": "Para segurança da sua conta, confirme apenas se tiver concedido acesso de emergência a este utilizador e se a sua impressão digital corresponder à que é apresentada na sua conta" + }, + "orgTrustWarning": { + "message": "Para segurança da sua conta, prossiga apenas se for membro desta organização, tiver a recuperação de conta ativada e a impressão digital apresentada abaixo corresponder à impressão digital da organização." + }, + "trustUser": { + "message": "Confiar no utilizador" + }, "sshKeyWrongPassword": { "message": "A palavra-passe que introduziu está incorreta." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Os lugares atribuídos excedem os lugares disponíveis." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Frase de impressão digital dos $NUM_USERS$ contactos para os quais ativou o acesso de emergência.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Frase de impressão digital para a organização $ORG_NAME$ para a qual ativou a recuperação de conta.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "A rotação das suas chaves de encriptação exigirá que confie nas chaves de quaisquer organizações que possam recuperar a sua conta e em quaisquer contactos para os quais tenha ativado o acesso de emergência. Para continuar, certifique-se de que pode verificar o seguinte:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Chaves de encriptação não fiáveis" + }, "changeAtRiskPassword": { "message": "Alterar palavra-passe em risco" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "As organizações gratuitas podem ter até 2 coleções. Atualize para um plano pago para adicionar mais coleções." + }, + "businessUnit": { + "message": "Unidade de negócio" + }, + "businessUnits": { + "message": "Unidades de negócio" + }, + "newBusinessUnit": { + "message": "Nova unidade de negócio" } } diff --git a/apps/web/src/locales/ro/messages.json b/apps/web/src/locales/ro/messages.json index 9531fdaa59a..e513deb7f5e 100644 --- a/apps/web/src/locales/ro/messages.json +++ b/apps/web/src/locales/ro/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Id-ul extern poate fi utilizat ca referință sau pentru a lega această resursă de un sistem extern, cum ar fi un folder utilizator." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn a fost verificat cu succes! Puteți închide această filă." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Indiciul dvs. de parolă nu poate fi aceeași cu parola." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Amprentă" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Eliminare utilizatori" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/ru/messages.json b/apps/web/src/locales/ru/messages.json index cc2ffc2e524..f1bb004ce1d 100644 --- a/apps/web/src/locales/ru/messages.json +++ b/apps/web/src/locales/ru/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Внешний ID - это незашифрованная ссылка, используемая Bitwarden Directory Connector и API." }, + "ssoExternalId": { + "message": "Внешний ID SSO" + }, + "ssoExternalIdDesc": { + "message": "Внешний ID SSO - это незашифрованная ссылка между Bitwarden и вашим настроенным провайдером SSO." + }, "nestCollectionUnder": { "message": "Разместить коллекцию под:" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn успешно прошел верификацию!
Вы можете закрыть эту вкладку." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Ваш новый пароль не может быть таким же, как текущий." + }, "hintEqualsPassword": { "message": "Подсказка для пароля не может совпадать с паролем." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Отпечаток" }, + "fingerprintPhrase": { + "message": "Фраза отпечатка:" + }, "removeUsers": { "message": "Удалить пользователей" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Название организации не может превышать 50 символов." }, + "rotationCompletedTitle": { + "message": "Изменение ключа успешно" + }, + "rotationCompletedDesc": { + "message": "Ваш мастер-пароль и ключ шифрования были обновлены. Другие ваши устройства были выведены из системы." + }, + "trustUserEmergencyAccess": { + "message": "Доверенный и подтвержденный пользователь" + }, + "trustOrganization": { + "message": "Доверенная организация" + }, + "trust": { + "message": "Доверять" + }, + "doNotTrust": { + "message": "Не доверять" + }, + "emergencyAccessTrustWarning": { + "message": "Для обеспечения безопасности вашей учетной записи подтвердите, только если вы предоставили этому пользователю экстренный доступ и его отпечаток пальца соответствует тому, что отображается в его учетной записи" + }, + "orgTrustWarning": { + "message": "Для обеспечения безопасности вашей учетной записи действуйте только в том случае, если вы являетесь членом этой организации, у вас включено восстановление учетной записи, и отпечаток пальца, отображаемый ниже, соответствует отпечатку пальца организации." + }, + "trustUser": { + "message": "Доверенный пользователь" + }, "sshKeyWrongPassword": { "message": "Введенный пароль неверен." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Количество назначенных мест превышает количество доступных." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Фраза отпечатка пальца для контактов $NUM_USERS$, для которых вы включили экстренный доступ.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Фраза отпечатка пальца для организации $ORG_NAME$, для которой вы включили восстановление учетной записи.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Изменение ключей шифрования потребует от вас доверия к ключам любых организаций, которые могут восстановить вашу учетную запись, а также любым контактам, для которых вы включили экстренный доступ. Для продолжения убедитесь, что вы можете проверить следующее:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Не доверенные ключи шифрования" + }, "changeAtRiskPassword": { "message": "Изменить пароль, подверженный риску" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "В бесплатных организациях может быть до 2 коллекций. Перейдите на платный план, чтобы добавить больше коллекций." + }, + "businessUnit": { + "message": "Бизнес-единица" + }, + "businessUnits": { + "message": "Бизнес-единицы" + }, + "newBusinessUnit": { + "message": "Новая бизнес-единица" } } diff --git a/apps/web/src/locales/si/messages.json b/apps/web/src/locales/si/messages.json index 8583aee42de..2acc04e756d 100644 --- a/apps/web/src/locales/si/messages.json +++ b/apps/web/src/locales/si/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/sk/messages.json b/apps/web/src/locales/sk/messages.json index 6a1e2ba715b..0c3c4eaba26 100644 --- a/apps/web/src/locales/sk/messages.json +++ b/apps/web/src/locales/sk/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Externé Id sa môže použiť na previazanie tohto zdroja s externým systémom - napríklad s užívateľským adresárom." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Zaradiť zbierku pod" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn bol úspešne overený! Túto kartu môžete zavrieť." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Nápoveda pre heslo nemôže byť rovnaká ako heslo." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Odtlačok prsta" }, + "fingerprintPhrase": { + "message": "Fráza odtlačku prsta:" + }, "removeUsers": { "message": "Odstrániť používateľov" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Meno organizácie nemôže mať viac ako 50 znakov." }, + "rotationCompletedTitle": { + "message": "Obnova kľúča úspešná" + }, + "rotationCompletedDesc": { + "message": "Vaše hlavné heslo a šifrovacie kľúče boli aktualizované. Vaše ostatné zariadenia boli odhlásené." + }, + "trustUserEmergencyAccess": { + "message": "Dôverovať a povoliť používateľa" + }, + "trustOrganization": { + "message": "Dôverovať organizácii" + }, + "trust": { + "message": "Dôverovať" + }, + "doNotTrust": { + "message": "Nedôverovať" + }, + "emergencyAccessTrustWarning": { + "message": "Pre bezpečnosť vášho konta stačí overiť, ze ste tomuto používateľovi udelili núdzový pristúp a že odtlačok sa zhoduje s odtlačkom zobrazenom v používateľovom konte" + }, + "orgTrustWarning": { + "message": "Pre bezpečnosť vášho konta pokračujte iba ak ste členom organizácie, mate povolenú obnovu konta a odtlačok sa zhoduje s odtlačkom organizácie." + }, + "trustUser": { + "message": "Dôverovať používateľovi" + }, "sshKeyWrongPassword": { "message": "Zadané heslo je nesprávne." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Počet pridelených sedení presahuje počet dostupných sedení." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fráza odtlačku kontaktu $NUM_USERS$ pre ktorý(é) ste povolili núdzový prístup.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fráza odtlačku organizácie $ORG_NAME$ pre ktorú(é) ste povolili obnovu konta.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Obnovenie šifrovacieho kľúča vyžaduje aby ste dôverovali organizáciám ktoré môžu obnoviť vaše konto a kontaktom pre ktoré ste povolili núdzový pristúp. Ak chcete pokračovať, uistite sa že ste overili nasledujúce:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Nedôveryhodné šifrovacie kľúče" + }, "changeAtRiskPassword": { "message": "Zmeniť ohrozené heslo" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Bezplatné organizácie môžu mat maximálne dve zbierky. Ak chcete pridať viac zbierok povýšte na platené predplatné." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/sl/messages.json b/apps/web/src/locales/sl/messages.json index 0357dca3932..fd990234b86 100644 --- a/apps/web/src/locales/sl/messages.json +++ b/apps/web/src/locales/sl/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/sr/messages.json b/apps/web/src/locales/sr/messages.json index 7ddbbb746de..1a414d913a7 100644 --- a/apps/web/src/locales/sr/messages.json +++ b/apps/web/src/locales/sr/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Спољни ид се може користити као референца или за повезивање овог ресурса са спољним системом као што је корисничка фасцикла." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Постави колекцију испод" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "Успешна провера WebAuthn-а!
Можете да затворите овај језичак." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Ваша помоћ за лозинку не може да буде иста као лозинка." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Отисак прста" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Уклони кориснике" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Име организације не може прећи 50 знакова." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "Лозинка коју сте унели није тачна." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Променити ризичну лозинку" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Бесплатне организације могу имати до 2 колекције. Надоградите на плаћени план за додавање више колекција." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/sr_CS/messages.json b/apps/web/src/locales/sr_CS/messages.json index a27221c469e..93f2c89a16d 100644 --- a/apps/web/src/locales/sr_CS/messages.json +++ b/apps/web/src/locales/sr_CS/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/sv/messages.json b/apps/web/src/locales/sv/messages.json index aced26c606f..5005b6180c7 100644 --- a/apps/web/src/locales/sv/messages.json +++ b/apps/web/src/locales/sv/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Det externa id:t kan användas som referens eller för att länka denna resurs till ett externt system såsom en användarkatalog." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Kapsla samling under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Din lösenordsledtråd får inte vara samma som ditt lösenord." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingeravtryck" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Ta bort användare" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/te/messages.json b/apps/web/src/locales/te/messages.json index 775494830de..293b3b0486f 100644 --- a/apps/web/src/locales/te/messages.json +++ b/apps/web/src/locales/te/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/th/messages.json b/apps/web/src/locales/th/messages.json index 73d7289939b..7ea003470cb 100644 --- a/apps/web/src/locales/th/messages.json +++ b/apps/web/src/locales/th/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/tr/messages.json b/apps/web/src/locales/tr/messages.json index a9b1aaa5edf..da4b35b403e 100644 --- a/apps/web/src/locales/tr/messages.json +++ b/apps/web/src/locales/tr/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Harici kimlik, referans olarak veya bu kaynağı kullanıcı dizini gibi harici bir sisteme bağlamak için kullanılabilir." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Koleksiyonu bunun altına yerleştir" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn başarıyla doğrulandı. Bu sekmeyi kapatabilirsiniz." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Parola ipucunuz parolanızla aynı olamaz." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Parmak izi" }, + "fingerprintPhrase": { + "message": "Parmak izi ifadesi:" + }, "removeUsers": { "message": "Kullanıcıları kaldır" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "Girdiğiniz parola yanlış." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Ücretsiz kuruluşların en fazla 2 koleksiyonu olabilir. Daha fazla koleksiyon eklemek için ücretli bir plana geçin." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/uk/messages.json b/apps/web/src/locales/uk/messages.json index acd79b5dc26..834bb36adfa 100644 --- a/apps/web/src/locales/uk/messages.json +++ b/apps/web/src/locales/uk/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "Зовнішній ID – це незашифроване посилання, призначене для використання Bitwarden Directory Connector і API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Розмістити збірку під" }, @@ -5685,8 +5691,11 @@ "webAuthnSuccess": { "message": "WebAuthn успішно підтверджено! Ви можете закрити цю вкладку." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { - "message": "Підказка для пароля не може бути такою самою, як ваш пароль." + "message": "Підказка повинна відрізнятися від пароля." }, "enrollAccountRecovery": { "message": "Розгорнути на відновлення облікового запису" @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Цифровий відбиток" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Вилучити користувачів" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Назва організації не може перевищувати 50 символів." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "Ви ввели неправильний пароль." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Призначені місця перевищують доступні місця." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Змінити ризикований пароль" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Безплатні організації можуть мати до 2 збірок. Передплатіть тарифний план, щоб додати більше збірок." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/vi/messages.json b/apps/web/src/locales/vi/messages.json index 1acf336af1d..0f2e31d834a 100644 --- a/apps/web/src/locales/vi/messages.json +++ b/apps/web/src/locales/vi/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "External ID is an unencrypted reference used by the Bitwarden Directory Connector and API." }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "Nest collection under" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn verified successfully! You may close this tab." }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "Fingerprint" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "Remove users" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/zh_CN/messages.json b/apps/web/src/locales/zh_CN/messages.json index f8bb62b0b00..5140946175f 100644 --- a/apps/web/src/locales/zh_CN/messages.json +++ b/apps/web/src/locales/zh_CN/messages.json @@ -1638,10 +1638,10 @@ "message": "确认文件密码" }, "accountRestrictedOptionDescription": { - "message": "使用衍生自您账户的用户名和主密码的加密密钥,以加密此导出并限制只能导入到当前的 Bitwarden 账户。" + "message": "使用衍生自您账户用户名和主密码的加密密钥以加密此导出,并限制只能导入到当前 Bitwarden 账户。" }, "passwordProtectedOptionDescription": { - "message": "设置一个密码用来加密导出的数据,并使用此密码解密以导入到任意 Bitwarden 账户。" + "message": "设置一个文件密码以加密此导出,并使用此密码解密以导入到任意 Bitwarden 账户。" }, "exportTypeHeading": { "message": "导出类型" @@ -3321,7 +3321,13 @@ "message": "外部 ID" }, "externalIdDesc": { - "message": "外部 ID 是一个 Bitwarden Directory Connector 和 API 使用的未经加密的参考。" + "message": "外部 ID 是 Bitwarden Directory Connector 和 API 使用的未经加密的参考。" + }, + "ssoExternalId": { + "message": "SSO 外部 ID" + }, + "ssoExternalIdDesc": { + "message": "SSO 外部 ID 是 Bitwarden 与您配置的 SSO 提供程序之间的未经加密的参考。" }, "nestCollectionUnder": { "message": "嵌套于集合下" @@ -4573,7 +4579,7 @@ "message": "随时。" }, "byContinuingYouAgreeToThe": { - "message": "若继续,代表您同意" + "message": "若继续,表示您同意" }, "and": { "message": "和" @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn 验证成功!您可以关闭此标签页。" }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "您的新密码不能与当前密码相同。" + }, "hintEqualsPassword": { "message": "密码提示不能与密码相同。" }, @@ -5788,7 +5797,7 @@ "message": "自动注册" }, "resetPasswordPolicyAutoEnrollCheckbox": { - "message": "为新用户启用自动注册" + "message": "为新成员启用自动注册" }, "resetPasswordAutoEnrollInviteWarning": { "message": "此组织有一个企业策略,将自动为您注册密码重置。注册后将允许组织管理员更改您的主密码。" @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "指纹" }, + "fingerprintPhrase": { + "message": "指纹短语:" + }, "removeUsers": { "message": "移除用户" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "组织名称不能超过 50 个字符。" }, + "rotationCompletedTitle": { + "message": "密钥轮换成功" + }, + "rotationCompletedDesc": { + "message": "您的主密码和加密密钥已更新。您的其他设备已被注销。" + }, + "trustUserEmergencyAccess": { + "message": "信任并确认用户" + }, + "trustOrganization": { + "message": "信任组织" + }, + "trust": { + "message": "信任" + }, + "doNotTrust": { + "message": "不信任" + }, + "emergencyAccessTrustWarning": { + "message": "为了您的账户安全,确认前请先确认:您已授予该用户紧急访问权限,以及其指纹与其账户中显示的指纹相匹配" + }, + "orgTrustWarning": { + "message": "为了您的账户安全,继续前请先确认:您是启用了账户恢复功能的该组织的成员,以及下方显示的指纹与此组织的指纹相匹配。" + }, + "trustUser": { + "message": "信任用户" + }, "sshKeyWrongPassword": { "message": "您输入的密码不正确。" }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "分配的席位超过可用席位。" }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "启用了紧急访问权限的 $NUM_USERS$ 位联系人的指纹短语。", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "启用了账户恢复功能的组织 $ORG_NAME$ 的指纹短语。", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "轮换加密密钥将需要您信任能够恢复您账户的所有组织的密钥,以及您已为其启用紧急访问的所有联系人的密钥。要继续操作,请确保您能够验证以下信息:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "未信任的加密密钥" + }, "changeAtRiskPassword": { "message": "更改有风险的密码" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "免费组织最多拥有 2 个集合。要添加更多集合,请升级到付费计划。" + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } diff --git a/apps/web/src/locales/zh_TW/messages.json b/apps/web/src/locales/zh_TW/messages.json index d72b53d3aa3..23b932cd52a 100644 --- a/apps/web/src/locales/zh_TW/messages.json +++ b/apps/web/src/locales/zh_TW/messages.json @@ -3323,6 +3323,12 @@ "externalIdDesc": { "message": "外部 ID 可用於參考,或將此資源與使用者目錄等外部系統連結起來。" }, + "ssoExternalId": { + "message": "SSO External ID" + }, + "ssoExternalIdDesc": { + "message": "SSO External ID is an unencrypted reference between Bitwarden and your configured SSO provider." + }, "nestCollectionUnder": { "message": "將集合嵌套在" }, @@ -5685,6 +5691,9 @@ "webAuthnSuccess": { "message": "WebAuthn 驗證成功!您可以關閉此分頁。" }, + "yourNewPasswordCannotBeTheSameAsYourCurrentPassword": { + "message": "Your new password cannot be the same as your current password." + }, "hintEqualsPassword": { "message": "密碼提示不能與您的密碼相同。" }, @@ -5880,6 +5889,9 @@ "fingerprint": { "message": "指紋" }, + "fingerprintPhrase": { + "message": "Fingerprint phrase:" + }, "removeUsers": { "message": "移除使用者" }, @@ -10330,6 +10342,33 @@ "organizationNameMaxLength": { "message": "Organization name cannot exceed 50 characters." }, + "rotationCompletedTitle": { + "message": "Key rotation successful" + }, + "rotationCompletedDesc": { + "message": "Your master password and encryption keys have been updated. Your other devices have been logged out." + }, + "trustUserEmergencyAccess": { + "message": "Trust and confirm user" + }, + "trustOrganization": { + "message": "Trust organization" + }, + "trust": { + "message": "Trust" + }, + "doNotTrust": { + "message": "Do not trust" + }, + "emergencyAccessTrustWarning": { + "message": "For the security of your account, only confirm if you have granted emergency access to this user and their fingerprint matches what is displayed in their account" + }, + "orgTrustWarning": { + "message": "For the security of your account, only proceed if you are a member of this organization, have account recovery enabled, and the fingerprint displayed below matches the organization's fingerprint." + }, + "trustUser": { + "message": "Trust user" + }, "sshKeyWrongPassword": { "message": "The password you entered is incorrect." }, @@ -10499,6 +10538,30 @@ "assignedExceedsAvailable": { "message": "Assigned seats exceed available seats." }, + "userkeyRotationDisclaimerEmergencyAccessText": { + "message": "Fingerprint phrase for $NUM_USERS$ contacts for which you have enabled emergency access.", + "placeholders": { + "num_users": { + "content": "$1", + "example": "5" + } + } + }, + "userkeyRotationDisclaimerAccountRecoveryOrgsText": { + "message": "Fingerprint phrase for the organization $ORG_NAME$ for which you have enabled account recovery.", + "placeholders": { + "org_name": { + "content": "$1", + "example": "My org" + } + } + }, + "userkeyRotationDisclaimerDescription": { + "message": "Rotating your encryption keys will require you to trust keys of any organizations that can recover your account, and any contacts that you have enabled emergency access for. To continue, make sure you can verify the following:" + }, + "userkeyRotationDisclaimerTitle": { + "message": "Untrusted encryption keys" + }, "changeAtRiskPassword": { "message": "Change at-risk password" }, @@ -10528,5 +10591,14 @@ }, "cannotCreateCollection": { "message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections." + }, + "businessUnit": { + "message": "Business Unit" + }, + "businessUnits": { + "message": "Business Units" + }, + "newBusinessUnit": { + "message": "New business unit" } } From b5434adb420c0a2ed923e989c8a2e50b6855471f Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 13:32:36 +0200 Subject: [PATCH 04/14] Autosync the updated translations (#14282) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/desktop/src/locales/ru/messages.json | 2 +- apps/desktop/src/locales/zh_CN/messages.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/locales/ru/messages.json b/apps/desktop/src/locales/ru/messages.json index 193a6352254..870efba3c9e 100644 --- a/apps/desktop/src/locales/ru/messages.json +++ b/apps/desktop/src/locales/ru/messages.json @@ -157,7 +157,7 @@ "message": "Код безопасности" }, "identityName": { - "message": "Имя" + "message": "Название личности" }, "company": { "message": "Компания" diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json index 3dd411f6593..38892deb282 100644 --- a/apps/desktop/src/locales/zh_CN/messages.json +++ b/apps/desktop/src/locales/zh_CN/messages.json @@ -1672,7 +1672,7 @@ "message": "无障碍 Cookie 已保存!" }, "noAccessibilityCookieSaved": { - "message": "无障碍 Cookie 未保存!" + "message": "未保存任何无障碍 Cookie!" }, "warning": { "message": "警告", @@ -2916,7 +2916,7 @@ "message": "然后继续创建您的账户。" }, "noEmail": { - "message": "没收到电子邮件吗?" + "message": "没有收到电子邮件吗?" }, "goBack": { "message": "返回" @@ -3434,7 +3434,7 @@ "message": "文本 Send" }, "ssoError": { - "message": "找不到用于 SSO 登录的可用端口。" + "message": "未找到用于 SSO 登录的空闲端口。" }, "biometricsStatusHelptextUnlockNeeded": { "message": "生物识别解锁不可用,因为需要先使用 PIN 或密码解锁。" From c7804c103215033fdba4c4732d673a76f9294f00 Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 13:34:13 +0200 Subject: [PATCH 05/14] Autosync the updated translations (#14283) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/web/src/locales/az/messages.json | 6 +++--- apps/web/src/locales/bg/messages.json | 6 +++--- apps/web/src/locales/lv/messages.json | 8 ++++---- apps/web/src/locales/nl/messages.json | 2 +- apps/web/src/locales/pt_BR/messages.json | 10 +++++----- apps/web/src/locales/ru/messages.json | 22 +++++++++++----------- apps/web/src/locales/uk/messages.json | 4 ++-- apps/web/src/locales/zh_CN/messages.json | 18 +++++++++--------- 8 files changed, 38 insertions(+), 38 deletions(-) diff --git a/apps/web/src/locales/az/messages.json b/apps/web/src/locales/az/messages.json index 0117fa37ae4..78b0b1ec825 100644 --- a/apps/web/src/locales/az/messages.json +++ b/apps/web/src/locales/az/messages.json @@ -10593,12 +10593,12 @@ "message": "Ödənişsiz təşkilatların ən çox 2 kolleksiyası ola bilər. Daha çox kolleksiya əlavə etmək üçün ödənişli bir plana yüksəldin." }, "businessUnit": { - "message": "Business Unit" + "message": "Biznes vahidi" }, "businessUnits": { - "message": "Business Units" + "message": "Biznes vahidləri" }, "newBusinessUnit": { - "message": "New business unit" + "message": "Yeni biznes vahidi" } } diff --git a/apps/web/src/locales/bg/messages.json b/apps/web/src/locales/bg/messages.json index de23b298710..13bbdc14d4a 100644 --- a/apps/web/src/locales/bg/messages.json +++ b/apps/web/src/locales/bg/messages.json @@ -10593,12 +10593,12 @@ "message": "Безплатните организации могат да имат не повече от 2 колекции. Надградете до платен план, ако искате да имате повече колекции." }, "businessUnit": { - "message": "Business Unit" + "message": "Бизнес единица" }, "businessUnits": { - "message": "Business Units" + "message": "Бизнес единици" }, "newBusinessUnit": { - "message": "New business unit" + "message": "Нова бизнес единица" } } diff --git a/apps/web/src/locales/lv/messages.json b/apps/web/src/locales/lv/messages.json index fba3376ac06..3faf2a549de 100644 --- a/apps/web/src/locales/lv/messages.json +++ b/apps/web/src/locales/lv/messages.json @@ -7028,7 +7028,7 @@ } }, "forwarderNoDomain": { - "message": "Nederīgs $SERVICENAME$ domēna vārds.", + "message": "Nederīgs $SERVICENAME$ domēns.", "description": "Displayed when the domain is empty or domain authorization failed at the forwarding service.", "placeholders": { "servicename": { @@ -10593,12 +10593,12 @@ "message": "Apvienībās, kuras izmanto Bitwarden bez maksas, var būt līdz 2 krājumiem. Jāpāriet uz maksas plānu, lai pievienotu vairāk krājumu." }, "businessUnit": { - "message": "Business Unit" + "message": "Uzņēmējdarbības vienība" }, "businessUnits": { - "message": "Business Units" + "message": "Uzņēmējdarbības vienības" }, "newBusinessUnit": { - "message": "New business unit" + "message": "Jauna uzņēmējdarbības vienība" } } diff --git a/apps/web/src/locales/nl/messages.json b/apps/web/src/locales/nl/messages.json index 22eb954f5c4..b6811d9289f 100644 --- a/apps/web/src/locales/nl/messages.json +++ b/apps/web/src/locales/nl/messages.json @@ -6,7 +6,7 @@ "message": "Belangrijke applicaties" }, "noCriticalAppsAtRisk": { - "message": "Geen belangrijke applicaties lopen risico" + "message": "Geen kritische applicaties in gevaar" }, "accessIntelligence": { "message": "Toegangsintelligentie" diff --git a/apps/web/src/locales/pt_BR/messages.json b/apps/web/src/locales/pt_BR/messages.json index 4cb7f19a1fc..70cbc35fe6c 100644 --- a/apps/web/src/locales/pt_BR/messages.json +++ b/apps/web/src/locales/pt_BR/messages.json @@ -244,7 +244,7 @@ "message": "Chave do autenticador" }, "autofillOptions": { - "message": "Opções de autopreenchimento" + "message": "Opções de preenchimento automático" }, "websiteUri": { "message": "Site (URI)" @@ -297,7 +297,7 @@ } }, "autoFillOnPageLoad": { - "message": "Preenchimento automático ao carregar a página?" + "message": "Preencher automaticamente ao carregar a página?" }, "number": { "message": "Número" @@ -6174,13 +6174,13 @@ "message": "Ativar preenchimento automático" }, "activateAutofillPolicyDesc": { - "message": "Ative o autopreenchimento na configuração de carregamento de página na extensão do navegador para todos os membros existentes e novos." + "message": "Ative a configuração de preenchimento automático ao carregamento de página na extensão do navegador para todos os membros existentes e novos." }, "experimentalFeature": { "message": "Sites comprometidos ou não confiáveis podem tomar vantagem do autopreenchimento ao carregar a página." }, "learnMoreAboutAutofill": { - "message": "Saiba mais sobre preenchimento automático" + "message": "Saiba mais sobre o preenchimento automático" }, "selectType": { "message": "Selecionar Tipo de SSO" @@ -10049,7 +10049,7 @@ "message": "Use caixas de seleção se gostaria de preencher automaticamente a caixa de seleção de um formulário, como um e-mail de lembrança" }, "linkedHelpText": { - "message": "Use um campo vinculado quando estiver enfrentando problemas com o auto-preenchimento para um site específico." + "message": "Use um campo vinculado quando estiver enfrentando problemas com o preenchimento automático em um site específico." }, "linkedLabelHelpText": { "message": "Digite o Id html do campo, nome, nome aria-label, ou marcador de posição" diff --git a/apps/web/src/locales/ru/messages.json b/apps/web/src/locales/ru/messages.json index f1bb004ce1d..e84af0d0b54 100644 --- a/apps/web/src/locales/ru/messages.json +++ b/apps/web/src/locales/ru/messages.json @@ -33,7 +33,7 @@ "message": "Уведомленные участники" }, "revokeMembers": { - "message": "Отзыв пользователей" + "message": "Отозвать пользователей" }, "restoreMembers": { "message": "Восстановление пользователей" @@ -315,7 +315,7 @@ "message": "Код безопасности / CVV" }, "identityName": { - "message": "Имя" + "message": "Название личности" }, "company": { "message": "Компания" @@ -10343,13 +10343,13 @@ "message": "Название организации не может превышать 50 символов." }, "rotationCompletedTitle": { - "message": "Изменение ключа успешно" + "message": "Успешная ротация ключа" }, "rotationCompletedDesc": { - "message": "Ваш мастер-пароль и ключ шифрования были обновлены. Другие ваши устройства были выведены из системы." + "message": "Ваш мастер-пароль и ключи шифрования обновлены. Остальные устройства были разлогинены." }, "trustUserEmergencyAccess": { - "message": "Доверенный и подтвержденный пользователь" + "message": "Удостоверить и подтвердить пользователя" }, "trustOrganization": { "message": "Доверенная организация" @@ -10361,10 +10361,10 @@ "message": "Не доверять" }, "emergencyAccessTrustWarning": { - "message": "Для обеспечения безопасности вашей учетной записи подтвердите, только если вы предоставили этому пользователю экстренный доступ и его отпечаток пальца соответствует тому, что отображается в его учетной записи" + "message": "В целях обеспечения безопасности вашего аккаунта подтверждайте только в том случае, если вы предоставили этому пользователю экстренный доступ и его отпечаток совпадает с отображаемым в его аккаунте" }, "orgTrustWarning": { - "message": "Для обеспечения безопасности вашей учетной записи действуйте только в том случае, если вы являетесь членом этой организации, у вас включено восстановление учетной записи, и отпечаток пальца, отображаемый ниже, соответствует отпечатку пальца организации." + "message": "В целях обеспечения безопасности вашего аккаунта продолжайте только в том случае, если вы являетесь членом этой организации, у вас включено восстановление аккаунта, а отображаемый ниже отпечаток совпадает с отпечатком организации." }, "trustUser": { "message": "Доверенный пользователь" @@ -10539,7 +10539,7 @@ "message": "Количество назначенных мест превышает количество доступных." }, "userkeyRotationDisclaimerEmergencyAccessText": { - "message": "Фраза отпечатка пальца для контактов $NUM_USERS$, для которых вы включили экстренный доступ.", + "message": "Фраза отпечатка для контактов $NUM_USERS$, которым вы разрешили экстренный доступ.", "placeholders": { "num_users": { "content": "$1", @@ -10548,7 +10548,7 @@ } }, "userkeyRotationDisclaimerAccountRecoveryOrgsText": { - "message": "Фраза отпечатка пальца для организации $ORG_NAME$, для которой вы включили восстановление учетной записи.", + "message": "Фраза отпечатка для организации $ORG_NAME$, которой вы разрешили восстановление аккаунта.", "placeholders": { "org_name": { "content": "$1", @@ -10557,10 +10557,10 @@ } }, "userkeyRotationDisclaimerDescription": { - "message": "Изменение ключей шифрования потребует от вас доверия к ключам любых организаций, которые могут восстановить вашу учетную запись, а также любым контактам, для которых вы включили экстренный доступ. Для продолжения убедитесь, что вы можете проверить следующее:" + "message": "При ротации ключей шифрования вам придется доверить ключи всем организациям, которые могут восстановить ваш аккаунт, и всем контактам, для которых вы включили экстренный доступ. Для продолжения убедитесь, что вы можете проверить следующее:" }, "userkeyRotationDisclaimerTitle": { - "message": "Не доверенные ключи шифрования" + "message": "Недоверенные ключи шифрования" }, "changeAtRiskPassword": { "message": "Изменить пароль, подверженный риску" diff --git a/apps/web/src/locales/uk/messages.json b/apps/web/src/locales/uk/messages.json index 834bb36adfa..a6bb37ed1d0 100644 --- a/apps/web/src/locales/uk/messages.json +++ b/apps/web/src/locales/uk/messages.json @@ -6864,11 +6864,11 @@ "message": "Надійний пароль згенеровано! Обов'язково оновіть свій пароль на вебсайті." }, "useGeneratorHelpTextPartOne": { - "message": "Скористатися генератором", + "message": "Скористайтеся генератором,", "description": "This will be used as part of a larger sentence, broken up to include the generator icon. The full sentence will read 'Use the generator [GENERATOR_ICON] to create a strong unique password'" }, "useGeneratorHelpTextPartTwo": { - "message": "для створення надійного, унікального пароля", + "message": "щоб створити надійний, унікальний пароль", "description": "This will be used as part of a larger sentence, broken up to include the generator icon. The full sentence will read 'Use the generator [GENERATOR_ICON] to create a strong unique password'" }, "service": { diff --git a/apps/web/src/locales/zh_CN/messages.json b/apps/web/src/locales/zh_CN/messages.json index 5140946175f..b3196721a55 100644 --- a/apps/web/src/locales/zh_CN/messages.json +++ b/apps/web/src/locales/zh_CN/messages.json @@ -2912,7 +2912,7 @@ "message": "付款方式" }, "noPaymentMethod": { - "message": "无付款方式。" + "message": "没有付款方式。" }, "addPaymentMethod": { "message": "添加付款方式" @@ -2924,10 +2924,10 @@ "message": "账单" }, "noUnpaidInvoices": { - "message": "无未支付的账单。" + "message": "没有未支付的账单。" }, "noPaidInvoices": { - "message": "无已支付的账单。" + "message": "没有已支付的账单。" }, "paid": { "message": "已支付", @@ -2942,7 +2942,7 @@ "description": "Payment/credit transactions." }, "noTransactions": { - "message": "无交易记录。" + "message": "没有交易记录。" }, "chargeNoun": { "message": "费用", @@ -3968,7 +3968,7 @@ "message": "然后继续创建您的账户。" }, "noEmail": { - "message": "没收到电子邮件吗?" + "message": "没有收到电子邮件吗?" }, "goBack": { "message": "返回" @@ -8956,7 +8956,7 @@ "message": "选择要分配的集合" }, "noCollectionsAssigned": { - "message": "没有分配任何集合" + "message": "未分配任何集合" }, "successfullyAssignedCollections": { "message": "成功分配了集合" @@ -10593,12 +10593,12 @@ "message": "免费组织最多拥有 2 个集合。要添加更多集合,请升级到付费计划。" }, "businessUnit": { - "message": "Business Unit" + "message": "业务单元" }, "businessUnits": { - "message": "Business Units" + "message": "业务单元" }, "newBusinessUnit": { - "message": "New business unit" + "message": "新增业务单元" } } From cb37434a160599e6eb00f620549c841396a998cb Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 13:40:20 +0200 Subject: [PATCH 06/14] Autosync the updated translations (#14284) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/browser/src/_locales/ar/messages.json | 27 ++++++++++++++++- apps/browser/src/_locales/az/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/be/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/bg/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/bn/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/bs/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ca/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/cs/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/cy/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/da/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/de/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/el/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/en_GB/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/en_IN/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/es/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/et/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/eu/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/fa/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/fi/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/fil/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/fr/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/gl/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/he/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/hi/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/hr/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/hu/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/id/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/it/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ja/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ka/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/km/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/kn/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ko/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/lt/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/lv/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ml/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/mr/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/my/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/nb/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ne/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/nl/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/nn/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/or/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/pl/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/pt_BR/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/pt_PT/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ro/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/ru/messages.json | 27 ++++++++++++++++- apps/browser/src/_locales/si/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/sk/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/sl/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/sr/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/sv/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/te/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/th/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/tr/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/uk/messages.json | 29 +++++++++++++++++-- apps/browser/src/_locales/vi/messages.json | 25 ++++++++++++++++ apps/browser/src/_locales/zh_CN/messages.json | 29 +++++++++++++++++-- apps/browser/src/_locales/zh_TW/messages.json | 25 ++++++++++++++++ 60 files changed, 1506 insertions(+), 6 deletions(-) diff --git a/apps/browser/src/_locales/ar/messages.json b/apps/browser/src/_locales/ar/messages.json index 3ca64543a4f..1bd6a77b746 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." @@ -3986,7 +4011,7 @@ "message": "رمز غير صحيح" }, "incorrectPin": { - "message": "رمز PIN غير صحيح" + "message": "رمز المرور غير صحيح" }, "multifactorAuthenticationFailed": { "message": "Multifactor authentication failed" diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json index 07a86b42565..41e6d9b5ab9 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -1098,6 +1098,31 @@ "message": "Giriş məlumatları güncəlləndi", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Saxlama xətası", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json index 7240371ca2d..f828400c575 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json index 88128e68be1..457b0693a17 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -1098,6 +1098,31 @@ "message": "Данните за вписване са обновени", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Чудесна работа! Направихте правилните стъпки за Вашата защита и тази на $ORGANIZATION$.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Благодарим Ви, че подобрихте защитата на $ORGANIZATION$. Имате още $TASK_COUNT$ пароли за обновяване.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Промяна на следващата парола", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Грешка при запазването", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json index 7a7a9cfa981..275bb18e029 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json index 0e73dc0b92e..687610c777e 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json index 3555642ef90..d9a24c5e473 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json index 361d5314e5d..2ed34c8c71a 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -1098,6 +1098,31 @@ "message": "Přihlašovací údaje byly aktualizovány", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Skvělá práce! Podnikli jste kroky, abyste $ORGANIZATION$ udělali bezpečnější.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Děkujeme, že jste udělali $ORGANIZATION$ bezpečnější. Máte $TASK_COUNT$ hesel k aktualizaci.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Změnit další heslo", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Chyba při ukládání", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/cy/messages.json b/apps/browser/src/_locales/cy/messages.json index c0034df9d2b..eb07358540d 100644 --- a/apps/browser/src/_locales/cy/messages.json +++ b/apps/browser/src/_locales/cy/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json index c6f051ce811..914c74411e4 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json index 274bc934b39..0edf5edfa3d 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -1098,6 +1098,31 @@ "message": "Zugangsdaten aktualisiert", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Fehler beim Speichern", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json index afd76596c85..1c15f70d40c 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json index 3b968f11587..520af1ca8ff 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json index f32abc028ed..f75664f10db 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json index e031a4487d6..1400cb78845 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json index 670dab1fcda..f9f7cb950fe 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/eu/messages.json b/apps/browser/src/_locales/eu/messages.json index b5ffbf45ba2..ec1f5189946 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json index d8a8f827db4..0e5e8943b7d 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index 56e25aead7d..4048925ebaa 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -1098,6 +1098,31 @@ "message": "Kirjautumistieto päivitettiin", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Virhe tallennettaessa", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json index 69d5895ba27..9c3865bc0da 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index fe2127148c8..1f05f699ea9 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -1098,6 +1098,31 @@ "message": "Identifiant mis à jour", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Erreur lors de l'enregistrement", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/gl/messages.json b/apps/browser/src/_locales/gl/messages.json index 83af8b6db75..b2b843d7830 100644 --- a/apps/browser/src/_locales/gl/messages.json +++ b/apps/browser/src/_locales/gl/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json index 605dd5454f0..fd38df53906 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -1098,6 +1098,31 @@ "message": "כניסה עודכנה", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "שגיאה בשמירה", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json index 9cc0f5251e6..813b69b9079 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json index bef7c9b8f13..896593332a4 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -1098,6 +1098,31 @@ "message": "Prijava ažurirana", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Greška kod spremanja", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json index d0114b30b7b..f58e542c77f 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -1098,6 +1098,31 @@ "message": "A bejelentkezés frissítésre került.", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Remek munka! Megtettük a lépéseket, hogy magunk és $ORGANIZATION$ biztonságosabbá váljon.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Köszönet $ORGANIZATION$ biztonságosabbá válásához. További $TASK_COUNT$ frissítendő jelszó van még.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Következő jelszó megváltoztatása", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Hiba történt a bejelentkezés mentésekor.", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index 16b11c9e732..101fcf43795 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -1098,6 +1098,31 @@ "message": "Log masuk diperbarui", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Kesalahan saat menyimpan", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json index 1448776e430..5f9a6ca7dca 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -1098,6 +1098,31 @@ "message": "Accesso aggiornato", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Errore nel salvataggio", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json index 4aae076174e..34b15699437 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -1098,6 +1098,31 @@ "message": "ログイン情報が更新されました", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "保存エラー", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json index 132a9b4d4ed..f261f69904d 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json index a9f5f5c2d75..7bec167e1c6 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json index 9e137fd6156..7d9583dc652 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json index dfc7364710a..7d65686df5d 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json index 93bbbef7292..2245fdb0029 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json index a42ee2ace78..517dacfb72b 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -1098,6 +1098,31 @@ "message": "Pieteikšanās vienums atjaunināts", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Lielisks darbs! Tu attiecīgi rīkojies, lai padarītu savi un $ORGANIZATION$ drošāku.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Paldies par $ORGANIZATION$ padarīšanu drošāku! Tev ir vēl $TASK_COUNT$ paroļu, ko atjaunināt.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Mainīt nākamo paroli", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Kļūda saglabāšanas laikā", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json index 5810d5392e6..49a2695ce6f 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/mr/messages.json b/apps/browser/src/_locales/mr/messages.json index 303a2cf96dd..6b2f7b8bc32 100644 --- a/apps/browser/src/_locales/mr/messages.json +++ b/apps/browser/src/_locales/mr/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/my/messages.json b/apps/browser/src/_locales/my/messages.json index a9f5f5c2d75..7bec167e1c6 100644 --- a/apps/browser/src/_locales/my/messages.json +++ b/apps/browser/src/_locales/my/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json index 18d00d9c274..7fa41eed68b 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ne/messages.json b/apps/browser/src/_locales/ne/messages.json index a9f5f5c2d75..7bec167e1c6 100644 --- a/apps/browser/src/_locales/ne/messages.json +++ b/apps/browser/src/_locales/ne/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index 80eba21ddb3..dd101e62e75 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -1098,6 +1098,31 @@ "message": "Login bijgewerkt", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Goed gedaan! Je hebt stappen genomen om jou en $ORGANIZATION$ veiliger te maken.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Bedankt voor het veiliger maken van $ORGANIZATION$. Je moet nog $TASK_COUNT$ wachtwoorden bijwerken.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Volgend wachtwoord veranderen", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Fout bij opslaan", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json index a9f5f5c2d75..7bec167e1c6 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/or/messages.json b/apps/browser/src/_locales/or/messages.json index a9f5f5c2d75..7bec167e1c6 100644 --- a/apps/browser/src/_locales/or/messages.json +++ b/apps/browser/src/_locales/or/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json index 5e74025800e..3d25e6f123c 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -1098,6 +1098,31 @@ "message": "Dane logowania zostały zaktualizowane", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Świetna robota! Podjęto kroki mające na celu zwiększenie bezpieczeństwa Twojego oraz $ORGANIZATION$.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Dziękujemy za dbanie o bezpieczeństwo $ORGANIZATION$. Pozostało $TASK_COUNT$ haseł do zaktualizowania.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Zmień następne hasło", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Błąd podczas zapisywania", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json index f22958d0498..9d1744f5473 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -1098,6 +1098,31 @@ "message": "Sessão atualizada", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Erro ao salvar", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json index 172e748a3f1..daab7fb05d9 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -1098,6 +1098,31 @@ "message": "Credencial atualizada", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Excelente trabalho! Tomou as medidas necessárias para o tornar a si e à sua $ORGANIZATION$ mais seguros.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Obrigado por tornar a $ORGANIZATION$ mais segura. Tem mais $TASK_COUNT$ palavras-passe para atualizar.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Alterar a palavra-passe seguinte", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Erro ao guardar", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json index 0272add140a..bcdf10f37f1 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json index 639a3b740db..b0f03d34f69 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -1098,6 +1098,31 @@ "message": "Логин обновлен", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Отличная работа! Вы предприняли шаги, чтобы сделать себя и $ORGANIZATION$ более защищенными.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Спасибо, что сделали $ORGANIZATION$ более защищенной. У вас есть еще $TASK_COUNT$ паролей для обновления.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Изменить следующий пароль", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Ошибка при сохранении", "description": "Error message shown when the system fails to save login details." @@ -1772,7 +1797,7 @@ "message": "Полное имя" }, "identityName": { - "message": "Имя" + "message": "Название личности" }, "company": { "message": "Компания" diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json index 70c1ff7126a..4efbb2dceeb 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json index 0b0a41a49b2..b427e902334 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -1098,6 +1098,31 @@ "message": "Prihlasovacie údaje aktualizované", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Skvelá práca! Podnikli ste kroky, aby ste vy a $ORGANIZATION$ boli bezpečnejší.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Ďakujeme, že ste pre $ORGANIZATION$ zabezpečili väčšiu bezpečnosť. Máte ďalšie ($TASK_COUNT$) heslá na aktualizáciu.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Zmeniť ďalšie heslo", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Chyba pri ukladaní", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json index 0fc3b26acb8..61a70650d16 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json index c402372895e..a36006894ba 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -1098,6 +1098,31 @@ "message": "Пријава ажурирана", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Грешка при снимању", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index 74b9bbccc80..54a34e15013 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/te/messages.json b/apps/browser/src/_locales/te/messages.json index a9f5f5c2d75..7bec167e1c6 100644 --- a/apps/browser/src/_locales/te/messages.json +++ b/apps/browser/src/_locales/te/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json index 0ef98835f18..b502e29cfdd 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json index f009a52a951..8a00287dfcc 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -1098,6 +1098,31 @@ "message": "Hesap güncellendi", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Kaydetme hatası", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json index 11e5b304611..bdd96ba9ea4 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -1098,6 +1098,31 @@ "message": "Запис оновлено", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Чудова робота! Ви щойно підвищили рівень безпеки для себе та $ORGANIZATION$.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Дякуємо за підвищення рівня безпеки $ORGANIZATION$. Залишилося оновити ще $TASK_COUNT$ паролів.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Змінити наступний пароль", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Помилка збереження", "description": "Error message shown when the system fails to save login details." @@ -2126,11 +2151,11 @@ "message": "Надійний пароль згенеровано! Обов'язково оновіть свій пароль на вебсайті." }, "useGeneratorHelpTextPartOne": { - "message": "Скористатися генератором", + "message": "Скористайтеся генератором,", "description": "This will be used as part of a larger sentence, broken up to include the generator icon. The full sentence will read 'Use the generator [GENERATOR_ICON] to create a strong unique password'" }, "useGeneratorHelpTextPartTwo": { - "message": "для створення надійного, унікального пароля", + "message": "щоб створити надійний, унікальний пароль", "description": "This will be used as part of a larger sentence, broken up to include the generator icon. The full sentence will read 'Use the generator [GENERATOR_ICON] to create a strong unique password'" }, "vaultCustomization": { diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 4693c93af9c..c6c6ed7ee6d 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index c8eaacc8c86..662284568cd 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -1098,6 +1098,31 @@ "message": "登录已更新", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "干得好!您采取了使您和 $ORGANIZATION$ 更加安全的措施。", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "感谢您使 $ORGANIZATION$ 更加安全。您还有 $TASK_COUNT$ 个密码需要更新。", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "更改下一个密码", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "保存时出错", "description": "Error message shown when the system fails to save login details." @@ -2825,7 +2850,7 @@ "message": "选择文件夹..." }, "noFoldersFound": { - "message": "找不到文件夹", + "message": "未找到任何文件夹", "description": "Used as a message within the notification bar when no folders are found" }, "orgPermissionsUpdatedMustSetPassword": { @@ -3929,7 +3954,7 @@ "message": "此应用程序已存在一个通行密钥。" }, "noPasskeysFoundForThisApplication": { - "message": "没有找到此应用程序的通行密钥。" + "message": "未找到此应用程序的通行密钥。" }, "noMatchingPasskeyLogin": { "message": "您没有匹配此站点的登录。" diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json index 1ba3a2166dd..7d56ecd8e63 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -1098,6 +1098,31 @@ "message": "Login updated", "description": "Message displayed when login details are successfully updated." }, + "loginUpdateTaskSuccess": { + "message": "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", + "placeholders": { + "organization": { + "content": "$1" + } + }, + "description": "Shown to user after login is updated." + }, + "loginUpdateTaskSuccessAdditional": { + "message": "Thank you for making $ORGANIZATION$ more secure. You have $TASK_COUNT$ more passwords to update.", + "placeholders": { + "organization": { + "content": "$1" + }, + "task_count": { + "content": "$2" + } + }, + "description": "Shown to user after login is updated." + }, + "nextSecurityTaskAction": { + "message": "Change next password", + "description": "Message prompting user to undertake completion of another security task." + }, "saveFailure": { "message": "Error saving", "description": "Error message shown when the system fails to save login details." From 9f174e7723ebdd39f4351cf434ac45d7cbc213f6 Mon Sep 17 00:00:00 2001 From: Opeyemi Date: Tue, 15 Apr 2025 14:57:37 +0100 Subject: [PATCH 07/14] update mas-dev SHA-1 (#14290) --- apps/browser/scripts/package-safari.ps1 | 2 +- apps/desktop/scripts/after-pack.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/browser/scripts/package-safari.ps1 b/apps/browser/scripts/package-safari.ps1 index ce208478098..1df40c68b37 100755 --- a/apps/browser/scripts/package-safari.ps1 +++ b/apps/browser/scripts/package-safari.ps1 @@ -52,7 +52,7 @@ foreach ($subBuildPath in $subBuildPaths) { "--verbose", "--force", "--sign", - "4B9662CAB74E8E4F4ECBDD9EDEF2543659D95E3C", + "588E3F1724AE018EBA762E42279DAE85B313E3ED", "--entitlements", $entitlementsPath ) diff --git a/apps/desktop/scripts/after-pack.js b/apps/desktop/scripts/after-pack.js index 45b79c0fe86..99c3d91be52 100644 --- a/apps/desktop/scripts/after-pack.js +++ b/apps/desktop/scripts/after-pack.js @@ -42,7 +42,7 @@ async function run(context) { if (process.env.GITHUB_ACTIONS === "true") { if (is_mas) { id = is_mas_dev - ? "4B9662CAB74E8E4F4ECBDD9EDEF2543659D95E3C" + ? "588E3F1724AE018EBA762E42279DAE85B313E3ED" : "3rd Party Mac Developer Application: Bitwarden Inc"; } else { id = "Developer ID Application: 8bit Solutions LLC"; From b09305577f450922fe0a37f3ee35e756eb603eb8 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 15 Apr 2025 16:39:02 +0200 Subject: [PATCH 08/14] [PM-19603] Change asymmetric interface to only allow key encapsulation (#14046) * Change asymmetric interface to only allow key encapsulation * Fix naming * Clean up naming * Update libs/common/src/key-management/crypto/abstractions/encrypt.service.ts Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Update libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Update libs/common/src/key-management/crypto/abstractions/encrypt.service.ts Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Fix test --------- Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> --- .../bulk/base-bulk-confirm.component.ts | 2 +- .../members/members.component.ts | 2 +- ...zation-user-reset-password.service.spec.ts | 9 +- ...rganization-user-reset-password.service.ts | 12 ++- .../rotateable-key-set.service.spec.ts | 2 +- .../services/rotateable-key-set.service.ts | 10 ++- .../services/emergency-access.service.spec.ts | 10 ++- .../services/emergency-access.service.ts | 14 ++-- .../accept-organization.service.spec.ts | 6 +- .../accept-organization.service.ts | 2 +- .../organization-auth-request.service.spec.ts | 13 ++- .../organization-auth-request.service.ts | 6 +- .../providers/manage/members.component.ts | 2 +- .../auth/components/set-password.component.ts | 5 +- .../default-set-password-jit.service.spec.ts | 4 +- .../default-set-password-jit.service.ts | 2 +- .../webauthn-login.strategy.spec.ts | 12 +-- .../webauthn-login.strategy.ts | 5 +- .../auth-request/auth-request.service.spec.ts | 32 ++++--- .../auth-request/auth-request.service.ts | 20 ++--- .../domain/encrypted-organization-key.ts | 6 +- ...-enrollment.service.implementation.spec.ts | 4 +- ...reset-enrollment.service.implementation.ts | 2 +- .../crypto/abstractions/encrypt.service.ts | 31 +++++++ .../encrypt.service.implementation.ts | 84 +++++++++++-------- .../crypto/services/encrypt.service.spec.ts | 37 ++++---- .../device-trust.service.implementation.ts | 10 +-- .../services/device-trust.service.spec.ts | 18 ++-- libs/key-management/src/key.service.spec.ts | 4 +- libs/key-management/src/key.service.ts | 6 +- 30 files changed, 229 insertions(+), 143 deletions(-) diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts index 05e302f011d..6b3f958fe51 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/base-bulk-confirm.component.ts @@ -71,7 +71,7 @@ export abstract class BaseBulkConfirmComponent implements OnInit { if (publicKey == null) { continue; } - const encryptedKey = await this.encryptService.rsaEncrypt(key.key, publicKey); + const encryptedKey = await this.encryptService.encapsulateKeyUnsigned(key, publicKey); userIdsWithKeys.push({ id: user.id, key: encryptedKey.encryptedString, diff --git a/apps/web/src/app/admin-console/organizations/members/members.component.ts b/apps/web/src/app/admin-console/organizations/members/members.component.ts index a64247339a5..3ce78354046 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/members.component.ts @@ -322,7 +322,7 @@ export class MembersComponent extends BaseMembersComponent async confirmUser(user: OrganizationUserView, publicKey: Uint8Array): Promise { const orgKey = await this.keyService.getOrgKey(this.organization.id); - const key = await this.encryptService.rsaEncrypt(orgKey.key, publicKey); + const key = await this.encryptService.encapsulateKeyUnsigned(orgKey, publicKey); const request = new OrganizationUserConfirmRequest(); request.key = key.encryptedString; await this.organizationUserApiService.postOrganizationUserConfirm( diff --git a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts index ce167950727..575c1017f21 100644 --- a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts +++ b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.spec.ts @@ -89,7 +89,7 @@ describe("OrganizationUserResetPasswordService", () => { }), ); - encryptService.rsaEncrypt.mockResolvedValue( + encryptService.encapsulateKeyUnsigned.mockResolvedValue( new EncString(EncryptionType.Rsa2048_OaepSha1_B64, "mockEncryptedUserKey"), ); }); @@ -111,7 +111,10 @@ describe("OrganizationUserResetPasswordService", () => { it("should rsa encrypt the user key", async () => { await sut.buildRecoveryKey(mockOrgId, mockUserKey, mockPublicKeys); - expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(expect.anything(), expect.anything()); + expect(encryptService.encapsulateKeyUnsigned).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + ); }); it("should throw an error if the public key is not trusted", async () => { @@ -199,7 +202,7 @@ describe("OrganizationUserResetPasswordService", () => { publicKey: Utils.fromUtf8ToArray("test-public-key"), }), ); - encryptService.rsaEncrypt.mockResolvedValue( + encryptService.encapsulateKeyUnsigned.mockResolvedValue( new EncString(EncryptionType.Rsa2048_OaepSha1_B64, "mockEncryptedUserKey"), ); }); diff --git a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts index 4b5c03a5a5b..78d2d8fd165 100644 --- a/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts +++ b/apps/web/src/app/admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service.ts @@ -14,7 +14,6 @@ import { EncryptService } from "@bitwarden/common/key-management/crypto/abstract import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; import { @@ -59,6 +58,10 @@ export class OrganizationUserResetPasswordService userKey: UserKey, trustedPublicKeys: Uint8Array[], ): Promise { + if (userKey == null) { + throw new Error("User key is required for recovery."); + } + // Retrieve Public Key const orgKeys = await this.organizationApiService.getKeys(orgId); if (orgKeys == null) { @@ -76,7 +79,8 @@ export class OrganizationUserResetPasswordService } // RSA Encrypt user key with organization's public key - const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); + const encryptedKey = await this.encryptService.encapsulateKeyUnsigned(userKey, publicKey); + return encryptedKey.encryptedString; } @@ -114,11 +118,11 @@ export class OrganizationUserResetPasswordService ); // Decrypt User's Reset Password Key to get UserKey - const decValue = await this.encryptService.rsaDecrypt( + const userKey = await this.encryptService.decapsulateKeyUnsigned( new EncString(response.resetPasswordKey), decPrivateKey, ); - const existingUserKey = new SymmetricCryptoKey(decValue) as UserKey; + const existingUserKey = userKey as UserKey; // determine Kdf Algorithm const kdfConfig: KdfConfig = diff --git a/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts b/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts index 1241ea88fe9..1a83fed37b7 100644 --- a/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts +++ b/apps/web/src/app/auth/core/services/rotateable-key-set.service.spec.ts @@ -35,7 +35,7 @@ describe("RotateableKeySetService", () => { const encryptedPrivateKey = Symbol(); keyService.makeKeyPair.mockResolvedValue(["publicKey", encryptedPrivateKey as any]); keyService.getUserKey.mockResolvedValue({ key: userKey.key } as any); - encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey as any); + encryptService.encapsulateKeyUnsigned.mockResolvedValue(encryptedUserKey as any); encryptService.encrypt.mockResolvedValue(encryptedPublicKey as any); const result = await service.createKeySet(externalKey as any); diff --git a/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts b/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts index 64a8bdfbfb4..8510aa1c29a 100644 --- a/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts +++ b/apps/web/src/app/auth/core/services/rotateable-key-set.service.ts @@ -25,7 +25,10 @@ export class RotateableKeySetService { const userKey = await this.keyService.getUserKey(); const rawPublicKey = Utils.fromB64ToArray(publicKey); - const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, rawPublicKey); + const encryptedUserKey = await this.encryptService.encapsulateKeyUnsigned( + userKey, + rawPublicKey, + ); const encryptedPublicKey = await this.encryptService.encrypt(rawPublicKey, userKey); return new RotateableKeySet(encryptedUserKey, encryptedPublicKey, encryptedPrivateKey); } @@ -60,7 +63,10 @@ export class RotateableKeySetService { throw new Error("failed to rotate key set: could not decrypt public key"); } const newEncryptedPublicKey = await this.encryptService.encrypt(publicKey, newUserKey); - const newEncryptedUserKey = await this.encryptService.rsaEncrypt(newUserKey.key, publicKey); + const newEncryptedUserKey = await this.encryptService.encapsulateKeyUnsigned( + newUserKey, + publicKey, + ); const newRotateableKeySet = new RotateableKeySet( newEncryptedUserKey, diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts index 6ad2c4de70e..6b4b3f2ff1e 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts @@ -130,7 +130,9 @@ describe("EmergencyAccessService", () => { keyService.getUserKey.mockResolvedValueOnce(mockUserKey); - encryptService.rsaEncrypt.mockResolvedValueOnce(mockUserPublicKeyEncryptedUserKey); + encryptService.encapsulateKeyUnsigned.mockResolvedValueOnce( + mockUserPublicKeyEncryptedUserKey, + ); emergencyAccessApiService.postEmergencyAccessConfirm.mockResolvedValueOnce(); @@ -160,7 +162,9 @@ describe("EmergencyAccessService", () => { const mockDecryptedGrantorUserKey = new Uint8Array(64); keyService.getPrivateKey.mockResolvedValue(new Uint8Array(64)); - encryptService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedGrantorUserKey); + encryptService.decapsulateKeyUnsigned.mockResolvedValueOnce( + new SymmetricCryptoKey(mockDecryptedGrantorUserKey), + ); const mockMasterKey = new SymmetricCryptoKey(new Uint8Array(64) as CsprngArray) as MasterKey; @@ -253,7 +257,7 @@ describe("EmergencyAccessService", () => { publicKey: Utils.fromUtf8ToB64("trustedPublicKey"), } as UserKeyResponse); - encryptService.rsaEncrypt.mockImplementation((plainValue, publicKey) => { + encryptService.encapsulateKeyUnsigned.mockImplementation((plainValue, publicKey) => { return Promise.resolve( new EncString(EncryptionType.Rsa2048_OaepSha1_B64, "Encrypted: " + plainValue), ); diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts index e86e0822ef3..5094c0c09ab 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts @@ -12,7 +12,6 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; @@ -234,11 +233,10 @@ export class EmergencyAccessService throw new Error("Active user does not have a private key, cannot get view only ciphers."); } - const grantorKeyBuffer = await this.encryptService.rsaDecrypt( + const grantorUserKey = (await this.encryptService.decapsulateKeyUnsigned( new EncString(response.keyEncrypted), activeUserPrivateKey, - ); - const grantorUserKey = new SymmetricCryptoKey(grantorKeyBuffer) as UserKey; + )) as UserKey; let ciphers: CipherView[] = []; if (await this.configService.getFeatureFlag(FeatureFlag.PM4154_BulkEncryptionService)) { @@ -271,15 +269,15 @@ export class EmergencyAccessService throw new Error("Active user does not have a private key, cannot complete a takeover."); } - const grantorKeyBuffer = await this.encryptService.rsaDecrypt( + const grantorKey = await this.encryptService.decapsulateKeyUnsigned( new EncString(takeoverResponse.keyEncrypted), activeUserPrivateKey, ); - if (grantorKeyBuffer == null) { + if (grantorKey == null) { throw new Error("Failed to decrypt grantor key"); } - const grantorUserKey = new SymmetricCryptoKey(grantorKeyBuffer) as UserKey; + const grantorUserKey = grantorKey as UserKey; let config: KdfConfig; @@ -407,6 +405,6 @@ export class EmergencyAccessService } private async encryptKey(userKey: UserKey, publicKey: Uint8Array): Promise { - return (await this.encryptService.rsaEncrypt(userKey.key, publicKey)).encryptedString; + return (await this.encryptService.encapsulateKeyUnsigned(userKey, publicKey)).encryptedString; } } diff --git a/apps/web/src/app/auth/organization-invite/accept-organization.service.spec.ts b/apps/web/src/app/auth/organization-invite/accept-organization.service.spec.ts index e7137e1d5bb..cc2d0e371ff 100644 --- a/apps/web/src/app/auth/organization-invite/accept-organization.service.spec.ts +++ b/apps/web/src/app/auth/organization-invite/accept-organization.service.spec.ts @@ -196,7 +196,7 @@ describe("AcceptOrganizationInviteService", () => { ); accountService.activeAccount$ = new BehaviorSubject({ id: "activeUserId" }) as any; keyService.userKey$.mockReturnValue(new BehaviorSubject({ key: "userKey" } as any)); - encryptService.rsaEncrypt.mockResolvedValue({ + encryptService.encapsulateKeyUnsigned.mockResolvedValue({ encryptedString: "encryptedString", } as EncString); @@ -218,8 +218,8 @@ describe("AcceptOrganizationInviteService", () => { expect(result).toBe(true); expect(OrganizationTrustComponent.open).toHaveBeenCalled(); - expect(encryptService.rsaEncrypt).toHaveBeenCalledWith( - "userKey", + expect(encryptService.encapsulateKeyUnsigned).toHaveBeenCalledWith( + { key: "userKey" }, Utils.fromB64ToArray("publicKey"), ); expect(organizationUserApiService.postOrganizationUserAccept).toHaveBeenCalled(); diff --git a/apps/web/src/app/auth/organization-invite/accept-organization.service.ts b/apps/web/src/app/auth/organization-invite/accept-organization.service.ts index 837031380f3..8b5db9f4872 100644 --- a/apps/web/src/app/auth/organization-invite/accept-organization.service.ts +++ b/apps/web/src/app/auth/organization-invite/accept-organization.service.ts @@ -202,7 +202,7 @@ export class AcceptOrganizationInviteService { const activeUserId = (await firstValueFrom(this.accountService.activeAccount$)).id; const userKey = await firstValueFrom(this.keyService.userKey$(activeUserId)); // RSA Encrypt user's encKey.key with organization public key - const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); + const encryptedKey = await this.encryptService.encapsulateKeyUnsigned(userKey, publicKey); // Add reset password key to accept request request.resetPasswordKey = encryptedKey.encryptedString; diff --git a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts index 448399a8bb0..933a5af1760 100644 --- a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts +++ b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.spec.ts @@ -7,6 +7,7 @@ import { import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; +import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { KeyService } from "@bitwarden/key-management"; import { OrganizationAuthRequestApiService } from "./organization-auth-request-api.service"; @@ -124,8 +125,10 @@ describe("OrganizationAuthRequestService", () => { ); const encryptedUserKey = new EncString("encryptedUserKey"); - encryptService.rsaDecrypt.mockResolvedValue(new Uint8Array(32)); - encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey); + encryptService.decapsulateKeyUnsigned.mockResolvedValue( + new SymmetricCryptoKey(new Uint8Array(32)), + ); + encryptService.encapsulateKeyUnsigned.mockResolvedValue(encryptedUserKey); const mockPendingAuthRequest = new PendingAuthRequestView(); mockPendingAuthRequest.id = "requestId1"; @@ -166,8 +169,10 @@ describe("OrganizationAuthRequestService", () => { ); const encryptedUserKey = new EncString("encryptedUserKey"); - encryptService.rsaDecrypt.mockResolvedValue(new Uint8Array(32)); - encryptService.rsaEncrypt.mockResolvedValue(encryptedUserKey); + encryptService.decapsulateKeyUnsigned.mockResolvedValue( + new SymmetricCryptoKey(new Uint8Array(32)), + ); + encryptService.encapsulateKeyUnsigned.mockResolvedValue(encryptedUserKey); const mockPendingAuthRequest = new PendingAuthRequestView(); mockPendingAuthRequest.id = "requestId1"; diff --git a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts index 025b021f83d..97e271e770e 100644 --- a/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts +++ b/bitwarden_license/bit-common/src/admin-console/auth-requests/organization-auth-request.service.ts @@ -7,7 +7,6 @@ import { import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { KeyService } from "@bitwarden/key-management"; import { OrganizationAuthRequestApiService } from "./organization-auth-request-api.service"; @@ -119,13 +118,12 @@ export class OrganizationAuthRequestService { ); // Decrypt user key with decrypted org private key - const decValue = await this.encryptService.rsaDecrypt( + const userKey = await this.encryptService.decapsulateKeyUnsigned( new EncString(encryptedUserKey), decOrgPrivateKey, ); - const userKey = new SymmetricCryptoKey(decValue); // Re-encrypt user Key with the Device Public Key - return await this.encryptService.rsaEncrypt(userKey.key, devicePubKey); + return await this.encryptService.encapsulateKeyUnsigned(userKey, devicePubKey); } } diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts index 7eff2c0f0b6..4a184d2dd16 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/members.component.ts @@ -187,7 +187,7 @@ export class MembersComponent extends BaseMembersComponent { async confirmUser(user: ProviderUser, publicKey: Uint8Array): Promise { const providerKey = await this.keyService.getProviderKey(this.providerId); - const key = await this.encryptService.rsaEncrypt(providerKey.key, publicKey); + const key = await this.encryptService.encapsulateKeyUnsigned(providerKey, publicKey); const request = new ProviderUserConfirmRequest(); request.key = key.encryptedString; await this.apiService.postProviderUserConfirm(this.providerId, user.id, request); diff --git a/libs/angular/src/auth/components/set-password.component.ts b/libs/angular/src/auth/components/set-password.component.ts index aec0673bb52..ee0756355cf 100644 --- a/libs/angular/src/auth/components/set-password.component.ts +++ b/libs/angular/src/auth/components/set-password.component.ts @@ -211,7 +211,10 @@ export class SetPasswordComponent extends BaseChangePasswordComponent implements // RSA Encrypt user key with organization public key const userKey = await this.keyService.getUserKey(); - const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); + const encryptedUserKey = await this.encryptService.encapsulateKeyUnsigned( + userKey, + publicKey, + ); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.masterPasswordHash = masterPasswordHash; diff --git a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts index cbcebd14526..12d4d8a2e39 100644 --- a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts +++ b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.spec.ts @@ -174,7 +174,7 @@ describe("DefaultSetPasswordJitService", () => { } keyService.userKey$.mockReturnValue(of(userKey)); - encryptService.rsaEncrypt.mockResolvedValue(userKeyEncString); + encryptService.encapsulateKeyUnsigned.mockResolvedValue(userKeyEncString); organizationUserApiService.putOrganizationUserResetPasswordEnrollment.mockResolvedValue( undefined, @@ -216,7 +216,7 @@ describe("DefaultSetPasswordJitService", () => { // Assert expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest); expect(organizationApiService.getKeys).toHaveBeenCalledWith(orgId); - expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(userKey.key, orgPublicKey); + expect(encryptService.encapsulateKeyUnsigned).toHaveBeenCalledWith(userKey, orgPublicKey); expect( organizationUserApiService.putOrganizationUserResetPasswordEnrollment, ).toHaveBeenCalled(); diff --git a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts index 174760aae21..2f96972d88d 100644 --- a/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts +++ b/libs/auth/src/angular/set-password-jit/default-set-password-jit.service.ts @@ -161,7 +161,7 @@ export class DefaultSetPasswordJitService implements SetPasswordJitService { throw new Error("userKey not found. Could not handle reset password auto enroll."); } - const encryptedUserKey = await this.encryptService.rsaEncrypt(userKey.key, publicKey); + const encryptedUserKey = await this.encryptService.encapsulateKeyUnsigned(userKey, publicKey); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.masterPasswordHash = masterKeyHash; diff --git a/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts index aac4a36c24a..2cdeb710ab9 100644 --- a/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/webauthn-login.strategy.spec.ts @@ -231,7 +231,9 @@ describe("WebAuthnLoginStrategy", () => { const mockUserKey = new SymmetricCryptoKey(mockUserKeyArray) as UserKey; encryptService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey); - encryptService.rsaDecrypt.mockResolvedValue(mockUserKeyArray); + encryptService.decapsulateKeyUnsigned.mockResolvedValue( + new SymmetricCryptoKey(mockUserKeyArray), + ); // Act await webAuthnLoginStrategy.logIn(webAuthnCredentials); @@ -249,8 +251,8 @@ describe("WebAuthnLoginStrategy", () => { idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedPrivateKey, webAuthnCredentials.prfKey, ); - expect(encryptService.rsaDecrypt).toHaveBeenCalledTimes(1); - expect(encryptService.rsaDecrypt).toHaveBeenCalledWith( + expect(encryptService.decapsulateKeyUnsigned).toHaveBeenCalledTimes(1); + expect(encryptService.decapsulateKeyUnsigned).toHaveBeenCalledWith( idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedUserKey, mockPrfPrivateKey, ); @@ -278,7 +280,7 @@ describe("WebAuthnLoginStrategy", () => { // Assert expect(encryptService.decryptToBytes).not.toHaveBeenCalled(); - expect(encryptService.rsaDecrypt).not.toHaveBeenCalled(); + expect(encryptService.decapsulateKeyUnsigned).not.toHaveBeenCalled(); expect(keyService.setUserKey).not.toHaveBeenCalled(); }); @@ -330,7 +332,7 @@ describe("WebAuthnLoginStrategy", () => { apiService.postIdentityToken.mockResolvedValue(idTokenResponse); - encryptService.rsaDecrypt.mockResolvedValue(null); + encryptService.decapsulateKeyUnsigned.mockResolvedValue(null); // Act await webAuthnLoginStrategy.logIn(webAuthnCredentials); diff --git a/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts b/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts index 97696a26699..895617b3237 100644 --- a/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/webauthn-login.strategy.ts @@ -7,7 +7,6 @@ import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { WebAuthnLoginTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/webauthn-login-token.request"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; @@ -89,13 +88,13 @@ export class WebAuthnLoginStrategy extends LoginStrategy { ); // decrypt user key with private key - const userKey = await this.encryptService.rsaDecrypt( + const userKey = await this.encryptService.decapsulateKeyUnsigned( new EncString(webAuthnPrfOption.encryptedUserKey.encryptedString), privateKey, ); if (userKey) { - await this.keyService.setUserKey(new SymmetricCryptoKey(userKey) as UserKey, userId); + await this.keyService.setUserKey(userKey as UserKey, userId); } } } diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts index 1e9c46db0ee..b5846fcfdbf 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts @@ -88,6 +88,9 @@ describe("AuthRequestService", () => { encryptService.rsaEncrypt.mockResolvedValue({ encryptedString: "ENCRYPTED_STRING", } as EncString); + encryptService.encapsulateKeyUnsigned.mockResolvedValue({ + encryptedString: "ENCRYPTED_STRING", + } as EncString); appIdService.getAppId.mockResolvedValue("APP_ID"); }); it("should throw if auth request is missing id or key", async () => { @@ -111,7 +114,10 @@ describe("AuthRequestService", () => { new AuthRequestResponse({ id: "123", publicKey: "KEY" }), ); - expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything()); + expect(encryptService.encapsulateKeyUnsigned).toHaveBeenCalledWith( + { encKey: new Uint8Array(64) }, + expect.anything(), + ); }); it("should use the user key if the master key and hash do not exist", async () => { @@ -122,7 +128,10 @@ describe("AuthRequestService", () => { new AuthRequestResponse({ id: "123", publicKey: "KEY" }), ); - expect(encryptService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything()); + expect(encryptService.encapsulateKeyUnsigned).toHaveBeenCalledWith( + { key: new Uint8Array(64) }, + expect.anything(), + ); }); }); describe("setUserKeyAfterDecryptingSharedUserKey", () => { @@ -214,7 +223,9 @@ describe("AuthRequestService", () => { const mockDecryptedUserKeyBytes = new Uint8Array(64); const mockDecryptedUserKey = new SymmetricCryptoKey(mockDecryptedUserKeyBytes) as UserKey; - encryptService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedUserKeyBytes); + encryptService.decapsulateKeyUnsigned.mockResolvedValueOnce( + new SymmetricCryptoKey(mockDecryptedUserKeyBytes), + ); // Act const result = await sut.decryptPubKeyEncryptedUserKey( @@ -223,7 +234,7 @@ describe("AuthRequestService", () => { ); // Assert - expect(encryptService.rsaDecrypt).toBeCalledWith( + expect(encryptService.decapsulateKeyUnsigned).toBeCalledWith( new EncString(mockPubKeyEncryptedUserKey), mockPrivateKey, ); @@ -244,9 +255,10 @@ describe("AuthRequestService", () => { const mockDecryptedMasterKeyHashBytes = new Uint8Array(64); const mockDecryptedMasterKeyHash = Utils.fromBufferToUtf8(mockDecryptedMasterKeyHashBytes); - encryptService.rsaDecrypt - .mockResolvedValueOnce(mockDecryptedMasterKeyBytes) - .mockResolvedValueOnce(mockDecryptedMasterKeyHashBytes); + encryptService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedMasterKeyHashBytes); + encryptService.decapsulateKeyUnsigned.mockResolvedValueOnce( + new SymmetricCryptoKey(mockDecryptedMasterKeyBytes), + ); // Act const result = await sut.decryptPubKeyEncryptedMasterKeyAndHash( @@ -256,13 +268,11 @@ describe("AuthRequestService", () => { ); // Assert - expect(encryptService.rsaDecrypt).toHaveBeenNthCalledWith( - 1, + expect(encryptService.decapsulateKeyUnsigned).toHaveBeenCalledWith( new EncString(mockPubKeyEncryptedMasterKey), mockPrivateKey, ); - expect(encryptService.rsaDecrypt).toHaveBeenNthCalledWith( - 2, + expect(encryptService.rsaDecrypt).toHaveBeenCalledWith( new EncString(mockPubKeyEncryptedMasterKeyHash), mockPrivateKey, ); diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.ts b/libs/auth/src/common/services/auth-request/auth-request.service.ts index 1da5d2f1882..f4316c2e519 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.ts @@ -14,7 +14,6 @@ import { AuthRequestPushNotification } from "@bitwarden/common/models/response/n import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { AUTH_REQUEST_DISK_LOCAL, StateProvider, @@ -116,13 +115,12 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { Utils.fromUtf8ToArray(masterKeyHash), pubKey, ); - keyToEncrypt = masterKey.encKey; + keyToEncrypt = masterKey; } else { - const userKey = await this.keyService.getUserKey(); - keyToEncrypt = userKey.key; + keyToEncrypt = await this.keyService.getUserKey(); } - const encryptedKey = await this.encryptService.rsaEncrypt(keyToEncrypt, pubKey); + const encryptedKey = await this.encryptService.encapsulateKeyUnsigned(keyToEncrypt, pubKey); const response = new PasswordlessAuthRequest( encryptedKey.encryptedString, @@ -171,12 +169,10 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { pubKeyEncryptedUserKey: string, privateKey: Uint8Array, ): Promise { - const decryptedUserKeyBytes = await this.encryptService.rsaDecrypt( + return (await this.encryptService.decapsulateKeyUnsigned( new EncString(pubKeyEncryptedUserKey), privateKey, - ); - - return new SymmetricCryptoKey(decryptedUserKeyBytes) as UserKey; + )) as UserKey; } async decryptPubKeyEncryptedMasterKeyAndHash( @@ -184,17 +180,15 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { pubKeyEncryptedMasterKeyHash: string, privateKey: Uint8Array, ): Promise<{ masterKey: MasterKey; masterKeyHash: string }> { - const decryptedMasterKeyArrayBuffer = await this.encryptService.rsaDecrypt( + const masterKey = (await this.encryptService.decapsulateKeyUnsigned( new EncString(pubKeyEncryptedMasterKey), privateKey, - ); + )) as MasterKey; const decryptedMasterKeyHashArrayBuffer = await this.encryptService.rsaDecrypt( new EncString(pubKeyEncryptedMasterKeyHash), privateKey, ); - - const masterKey = new SymmetricCryptoKey(decryptedMasterKeyArrayBuffer) as MasterKey; const masterKeyHash = Utils.fromBufferToUtf8(decryptedMasterKeyHashArrayBuffer); return { diff --git a/libs/common/src/admin-console/models/domain/encrypted-organization-key.ts b/libs/common/src/admin-console/models/domain/encrypted-organization-key.ts index 67a5b0dd123..984d80ba519 100644 --- a/libs/common/src/admin-console/models/domain/encrypted-organization-key.ts +++ b/libs/common/src/admin-console/models/domain/encrypted-organization-key.ts @@ -31,8 +31,10 @@ export class EncryptedOrganizationKey implements BaseEncryptedOrganizationKey { constructor(private key: string) {} async decrypt(encryptService: EncryptService, privateKey: UserPrivateKey) { - const decValue = await encryptService.rsaDecrypt(this.encryptedOrganizationKey, privateKey); - return new SymmetricCryptoKey(decValue) as OrgKey; + return (await encryptService.decapsulateKeyUnsigned( + this.encryptedOrganizationKey, + privateKey, + )) as OrgKey; } get encryptedOrganizationKey() { diff --git a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts index 8516400fe09..76c2d443d1d 100644 --- a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts +++ b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.spec.ts @@ -100,7 +100,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => { activeAccountSubject.next(Object.assign(user1AccountInfo, { id: "userId" as UserId })); keyService.getUserKey.mockResolvedValue({ key: "key" } as any); - encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any); + encryptService.encapsulateKeyUnsigned.mockResolvedValue(encryptedKey as any); await service.enroll("orgId"); @@ -122,7 +122,7 @@ describe("PasswordResetEnrollmentServiceImplementation", () => { }; const encryptedKey = { encryptedString: "encryptedString" }; organizationApiService.getKeys.mockResolvedValue(orgKeyResponse as any); - encryptService.rsaEncrypt.mockResolvedValue(encryptedKey as any); + encryptService.encapsulateKeyUnsigned.mockResolvedValue(encryptedKey as any); await service.enroll("orgId", "userId", { key: "key" } as any); diff --git a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts index 824521d8a2e..ef9c5ad3265 100644 --- a/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts +++ b/libs/common/src/auth/services/password-reset-enrollment.service.implementation.ts @@ -51,7 +51,7 @@ export class PasswordResetEnrollmentServiceImplementation userId ?? (await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)))); userKey = userKey ?? (await this.keyService.getUserKey(userId)); // RSA Encrypt user's userKey.key with organization public key - const encryptedKey = await this.encryptService.rsaEncrypt(userKey.key, orgPublicKey); + const encryptedKey = await this.encryptService.encapsulateKeyUnsigned(userKey, orgPublicKey); const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); resetRequest.resetPasswordKey = encryptedKey.encryptedString; diff --git a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts index 91e10f19069..a1e54f7064f 100644 --- a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts +++ b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts @@ -35,7 +35,38 @@ export abstract class EncryptService { key: SymmetricCryptoKey, decryptTrace?: string, ): Promise; + + /** + * Encapsulates a symmetric key with an asymmetric public key + * Note: This does not establish sender authenticity + * @param sharedKey - The symmetric key that is to be shared + * @param encapsulationKey - The encapsulation key (public key) of the receiver that the key is shared with + */ + abstract encapsulateKeyUnsigned( + sharedKey: SymmetricCryptoKey, + encapsulationKey: Uint8Array, + ): Promise; + /** + * Decapsulates a shared symmetric key with an asymmetric private key + * Note: This does not establish sender authenticity + * @param encryptedSharedKey - The encrypted shared symmetric key + * @param decapsulationKey - The key to decapsulate with (private key) + */ + abstract decapsulateKeyUnsigned( + encryptedSharedKey: EncString, + decapsulationKey: Uint8Array, + ): Promise; + /** + * @deprecated Use encapsulateKeyUnsigned instead + * @param data - The data to encrypt + * @param publicKey - The public key to encrypt with + */ abstract rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise; + /** + * @deprecated Use decapsulateKeyUnsigned instead + * @param data - The ciphertext to decrypt + * @param privateKey - The privateKey to decrypt with + */ abstract rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise; /** * @deprecated Replaced by BulkEncryptService, remove once the feature is tested and the featureflag PM-4154-multi-worker-encryption-service is removed diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts index 10d29198ada..4b299c9c6e6 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts @@ -235,42 +235,22 @@ export class EncryptServiceImplementation implements EncryptService { } } - async rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise { - if (data == null) { - throw new Error("No data provided for encryption."); + async encapsulateKeyUnsigned( + sharedKey: SymmetricCryptoKey, + encapsulationKey: Uint8Array, + ): Promise { + if (sharedKey == null) { + throw new Error("No sharedKey provided for encapsulation"); } - - if (publicKey == null) { - throw new Error("No public key provided for encryption."); - } - const encrypted = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, "sha1"); - return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(encrypted)); + return await this.rsaEncrypt(sharedKey.toEncoded(), encapsulationKey); } - async rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise { - if (data == null) { - throw new Error("[Encrypt service] rsaDecrypt: No data provided for decryption."); - } - - let algorithm: "sha1" | "sha256"; - switch (data.encryptionType) { - case EncryptionType.Rsa2048_OaepSha1_B64: - case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: - algorithm = "sha1"; - break; - case EncryptionType.Rsa2048_OaepSha256_B64: - case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: - algorithm = "sha256"; - break; - default: - throw new Error("Invalid encryption type."); - } - - if (privateKey == null) { - throw new Error("[Encrypt service] rsaDecrypt: No private key provided for decryption."); - } - - return this.cryptoFunctionService.rsaDecrypt(data.dataBytes, privateKey, algorithm); + async decapsulateKeyUnsigned( + encryptedSharedKey: EncString, + decapsulationKey: Uint8Array, + ): Promise { + const keyBytes = await this.rsaDecrypt(encryptedSharedKey, decapsulationKey); + return new SymmetricCryptoKey(keyBytes); } /** @@ -341,4 +321,42 @@ export class EncryptServiceImplementation implements EncryptService { this.logDecryptError(msg, keyEncType, dataEncType, decryptContext); } } + + async rsaEncrypt(data: Uint8Array, publicKey: Uint8Array): Promise { + if (data == null) { + throw new Error("No data provided for encryption."); + } + + if (publicKey == null) { + throw new Error("No public key provided for encryption."); + } + const encrypted = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, "sha1"); + return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(encrypted)); + } + + async rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise { + if (data == null) { + throw new Error("[Encrypt service] rsaDecrypt: No data provided for decryption."); + } + + let algorithm: "sha1" | "sha256"; + switch (data.encryptionType) { + case EncryptionType.Rsa2048_OaepSha1_B64: + case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: + algorithm = "sha1"; + break; + case EncryptionType.Rsa2048_OaepSha256_B64: + case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: + algorithm = "sha256"; + break; + default: + throw new Error("Invalid encryption type."); + } + + if (privateKey == null) { + throw new Error("[Encrypt service] rsaDecrypt: No private key provided for decryption."); + } + + return this.cryptoFunctionService.rsaDecrypt(data.dataBytes, privateKey, algorithm); + } } diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts b/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts index c65c78d88d7..4cbe3a3da90 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts @@ -412,7 +412,8 @@ describe("EncryptService", () => { }); describe("rsa", () => { - const data = makeStaticByteArray(10, 100); + const data = makeStaticByteArray(64, 100); + const testKey = new SymmetricCryptoKey(data); const encryptedData = makeStaticByteArray(10, 150); const publicKey = makeStaticByteArray(10, 200); const privateKey = makeStaticByteArray(10, 250); @@ -422,22 +423,26 @@ describe("EncryptService", () => { return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(data)); } - describe("rsaEncrypt", () => { + describe("encapsulateKeyUnsigned", () => { it("throws if no data is provided", () => { - return expect(encryptService.rsaEncrypt(null, publicKey)).rejects.toThrow("No data"); + return expect(encryptService.encapsulateKeyUnsigned(null, publicKey)).rejects.toThrow( + "No sharedKey provided for encapsulation", + ); }); it("throws if no public key is provided", () => { - return expect(encryptService.rsaEncrypt(data, null)).rejects.toThrow("No public key"); + return expect(encryptService.encapsulateKeyUnsigned(testKey, null)).rejects.toThrow( + "No public key", + ); }); it("encrypts data with provided key", async () => { cryptoFunctionService.rsaEncrypt.mockResolvedValue(encryptedData); - const actual = await encryptService.rsaEncrypt(data, publicKey); + const actual = await encryptService.encapsulateKeyUnsigned(testKey, publicKey); expect(cryptoFunctionService.rsaEncrypt).toBeCalledWith( - expect.toEqualBuffer(data), + expect.toEqualBuffer(testKey.key), expect.toEqualBuffer(publicKey), "sha1", ); @@ -447,13 +452,17 @@ describe("EncryptService", () => { }); }); - describe("rsaDecrypt", () => { + describe("decapsulateKeyUnsigned", () => { it("throws if no data is provided", () => { - return expect(encryptService.rsaDecrypt(null, privateKey)).rejects.toThrow("No data"); + return expect(encryptService.decapsulateKeyUnsigned(null, privateKey)).rejects.toThrow( + "No data", + ); }); it("throws if no private key is provided", () => { - return expect(encryptService.rsaDecrypt(encString, null)).rejects.toThrow("No private key"); + return expect(encryptService.decapsulateKeyUnsigned(encString, null)).rejects.toThrow( + "No private key", + ); }); it.each([EncryptionType.AesCbc256_B64, EncryptionType.AesCbc256_HmacSha256_B64])( @@ -461,16 +470,16 @@ describe("EncryptService", () => { async (encType) => { encString.encryptionType = encType; - await expect(encryptService.rsaDecrypt(encString, privateKey)).rejects.toThrow( - "Invalid encryption type", - ); + await expect( + encryptService.decapsulateKeyUnsigned(encString, privateKey), + ).rejects.toThrow("Invalid encryption type"); }, ); it("decrypts data with provided key", async () => { cryptoFunctionService.rsaDecrypt.mockResolvedValue(data); - const actual = await encryptService.rsaDecrypt(makeEncString(data), privateKey); + const actual = await encryptService.decapsulateKeyUnsigned(makeEncString(data), privateKey); expect(cryptoFunctionService.rsaDecrypt).toBeCalledWith( expect.toEqualBuffer(data), @@ -478,7 +487,7 @@ describe("EncryptService", () => { "sha1", ); - expect(actual).toEqualBuffer(data); + expect(actual.key).toEqualBuffer(data); }); }); }); diff --git a/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts b/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts index bddcf6185f0..a2211753f4e 100644 --- a/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts +++ b/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts @@ -161,7 +161,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { deviceKeyEncryptedDevicePrivateKey, ] = await Promise.all([ // Encrypt user key with the DevicePublicKey - this.encryptService.rsaEncrypt(userKey.key, devicePublicKey), + this.encryptService.encapsulateKeyUnsigned(userKey, devicePublicKey), // Encrypt devicePublicKey with user key this.encryptService.encrypt(devicePublicKey, userKey), @@ -285,8 +285,8 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { ); // Encrypt the brand new user key with the now-decrypted public key for the device - const encryptedNewUserKey = await this.encryptService.rsaEncrypt( - newUserKey.key, + const encryptedNewUserKey = await this.encryptService.encapsulateKeyUnsigned( + newUserKey, decryptedDevicePublicKey, ); @@ -401,12 +401,12 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { ); // Attempt to decrypt encryptedUserDataKey with devicePrivateKey - const userKey = await this.encryptService.rsaDecrypt( + const userKey = await this.encryptService.decapsulateKeyUnsigned( new EncString(encryptedUserKey.encryptedString), devicePrivateKey, ); - return new SymmetricCryptoKey(userKey) as UserKey; + return userKey as UserKey; // FIXME: Remove when updating file. Eslint update // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { diff --git a/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts b/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts index 61c90c5b5ee..8431fe4cc35 100644 --- a/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts +++ b/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts @@ -416,7 +416,7 @@ describe("deviceTrustService", () => { .mockResolvedValue(mockUserKey); cryptoSvcRsaEncryptSpy = jest - .spyOn(encryptService, "rsaEncrypt") + .spyOn(encryptService, "encapsulateKeyUnsigned") .mockResolvedValue(mockDevicePublicKeyEncryptedUserKey); encryptServiceEncryptSpy = jest @@ -449,8 +449,8 @@ describe("deviceTrustService", () => { expect(cryptoSvcRsaEncryptSpy).toHaveBeenCalledTimes(1); // RsaEncrypt must be called w/ a user key array buffer of 64 bytes - const userKeyKey: Uint8Array = cryptoSvcRsaEncryptSpy.mock.calls[0][0]; - expect(userKeyKey.byteLength).toBe(64); + const userKey = cryptoSvcRsaEncryptSpy.mock.calls[0][0]; + expect(userKey.key.byteLength).toBe(64); expect(encryptServiceEncryptSpy).toHaveBeenCalledTimes(2); @@ -610,7 +610,7 @@ describe("deviceTrustService", () => { mockUserId, mockEncryptedDevicePrivateKey, mockEncryptedUserKey, - mockDeviceKey, + null, ); expect(result).toBeNull(); @@ -621,8 +621,8 @@ describe("deviceTrustService", () => { .spyOn(encryptService, "decryptToBytes") .mockResolvedValue(new Uint8Array(userKeyBytesLength)); const rsaDecryptSpy = jest - .spyOn(encryptService, "rsaDecrypt") - .mockResolvedValue(new Uint8Array(userKeyBytesLength)); + .spyOn(encryptService, "decapsulateKeyUnsigned") + .mockResolvedValue(new SymmetricCryptoKey(new Uint8Array(userKeyBytesLength))); const result = await deviceTrustService.decryptUserKeyWithDeviceKey( mockUserId, @@ -863,9 +863,9 @@ describe("deviceTrustService", () => { }); // Mock the encryption of the new user key with the decrypted public key - encryptService.rsaEncrypt.mockImplementationOnce((data, publicKey) => { - expect(data.byteLength).toBe(64); // New key should also be 64 bytes - expect(new Uint8Array(data)[0]).toBe(FakeNewUserKeyMarker); // New key should have the first byte be '1'; + encryptService.encapsulateKeyUnsigned.mockImplementationOnce((data, publicKey) => { + expect(data.key.byteLength).toBe(64); // New key should also be 64 bytes + expect(new Uint8Array(data.key)[0]).toBe(FakeNewUserKeyMarker); // New key should have the first byte be '1'; expect(new Uint8Array(publicKey)[0]).toBe(FakeDecryptedPublicKeyMarker); return Promise.resolve(new EncString("4.ZW5jcnlwdGVkdXNlcg==")); diff --git a/libs/key-management/src/key.service.spec.ts b/libs/key-management/src/key.service.spec.ts index 049ff7411c3..90d049b7293 100644 --- a/libs/key-management/src/key.service.spec.ts +++ b/libs/key-management/src/key.service.spec.ts @@ -557,8 +557,8 @@ describe("keyService", () => { return Promise.resolve(fakePrivateKeyDecryption(encryptedPrivateKey, userKey)); }); - encryptService.rsaDecrypt.mockImplementation((data, privateKey) => { - return Promise.resolve(fakeOrgKeyDecryption(data, privateKey)); + encryptService.decapsulateKeyUnsigned.mockImplementation((data, privateKey) => { + return Promise.resolve(new SymmetricCryptoKey(fakeOrgKeyDecryption(data, privateKey))); }); } diff --git a/libs/key-management/src/key.service.ts b/libs/key-management/src/key.service.ts index e4f07911661..baf1b86e160 100644 --- a/libs/key-management/src/key.service.ts +++ b/libs/key-management/src/key.service.ts @@ -493,7 +493,7 @@ export class DefaultKeyService implements KeyServiceAbstraction { throw new Error("No public key found."); } - const encShareKey = await this.encryptService.rsaEncrypt(shareKey.key, publicKey); + const encShareKey = await this.encryptService.encapsulateKeyUnsigned(shareKey, publicKey); return [encShareKey, shareKey as T]; } @@ -968,11 +968,11 @@ export class DefaultKeyService implements KeyServiceAbstraction { return this.stateProvider.getUser(userId, USER_ENCRYPTED_PROVIDER_KEYS).state$.pipe( // Convert each value in the record to it's own decryption observable convertValues(async (_, value) => { - const decrypted = await this.encryptService.rsaDecrypt( + const decapsulatedKey = await this.encryptService.decapsulateKeyUnsigned( new EncString(value), userPrivateKey, ); - return new SymmetricCryptoKey(decrypted) as ProviderKey; + return decapsulatedKey as ProviderKey; }), // switchMap since there are no side effects switchMap((encryptedProviderKeys) => { From 94d94875475288de257b7a311ff0a1f577e8d1e6 Mon Sep 17 00:00:00 2001 From: Andy Pixley <3723676+pixman20@users.noreply.github.com> Date: Tue, 15 Apr 2025 12:31:08 -0400 Subject: [PATCH 09/14] [BRE-777] Fixing output to match what's in gh-actions (#14292) --- .github/workflows/deploy-web.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-web.yml b/.github/workflows/deploy-web.yml index 9b890491282..1cde8dd636a 100644 --- a/.github/workflows/deploy-web.yml +++ b/.github/workflows/deploy-web.yml @@ -242,7 +242,7 @@ jobs: run: | # If run-id was used, get the commit from the download-latest-artifacts-run-id step if [ "${{ inputs.build-web-run-id }}" ]; then - echo "commit=${{ steps.download-latest-artifacts-run-id.outputs.artifact_build_commit }}" >> $GITHUB_OUTPUT + echo "commit=${{ steps.download-latest-artifacts-run-id.outputs.artifact-build-commit }}" >> $GITHUB_OUTPUT elif [ "${{ steps.download-latest-artifacts.outcome }}" == "failure" ]; then # If the download-latest-artifacts step failed, query the GH API to get the commit SHA of the artifact that was just built with trigger-build-web. @@ -251,7 +251,7 @@ jobs: else # Set the commit to the output of step download-latest-artifacts. - echo "commit=${{ steps.download-latest-artifacts.outputs.artifact_build_commit }}" >> $GITHUB_OUTPUT + echo "commit=${{ steps.download-latest-artifacts.outputs.artifact-build-commit }}" >> $GITHUB_OUTPUT fi notify-start: From f74d7e5fd5d4a4602cea2c6afc55bc594d46ce1e Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:17:53 -0400 Subject: [PATCH 10/14] [PM-20239] Initializing `nx` (#14276) * Add .nx file to .gitignore Co-authored-by: Addison Beck * Add nx package Co-authored-by: Addison Beck * Add nx.json file Co-authored-by: Addison Beck * Add nx to Platform ownership --------- Co-authored-by: Addison Beck --- .github/renovate.json5 | 1 + .gitignore | 3 + nx.json | 10 + package-lock.json | 528 ++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 5 files changed, 538 insertions(+), 5 deletions(-) create mode 100644 nx.json diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 973ba700349..c4202ed2a68 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -250,6 +250,7 @@ "napi-derive", "node-forge", "node-ipc", + "nx", "oo7", "oslog", "pin-project", diff --git a/.gitignore b/.gitignore index d0d8edd596c..e865fa6a8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ storybook-static # Local app configuration apps/**/config/local.json + +# Nx +.nx diff --git a/nx.json b/nx.json new file mode 100644 index 00000000000..7da50182873 --- /dev/null +++ b/nx.json @@ -0,0 +1,10 @@ +{ + "cacheDirectory": ".nx/cache", + "defaultBase": "main", + "namedInputs": { + "default": ["{projectRoot}/**/*"], + "production": ["!{projectRoot}/**/*.spec.ts"] + }, + "parallel": 4, + "targetDefaults": {} +} diff --git a/package-lock.json b/package-lock.json index 3cba61db6f8..cb9baf4fafe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,6 +156,7 @@ "json5": "2.2.3", "lint-staged": "15.4.1", "mini-css-extract-plugin": "2.9.2", + "nx": "20.8.0", "postcss": "8.5.1", "postcss-loader": "8.1.1", "prettier": "3.4.2", @@ -5954,6 +5955,34 @@ "node": "*" } }, + "node_modules/@emnapi/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.1.tgz", + "integrity": "sha512-4JFstCTaToCFrPqrGzgkF8N2NHjtsaY4uRh6brZQ5L9e4wbMieX8oDT8N7qfVFTQecHFEtkj4ve49VIZ3mKVqw==", + "dev": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.1.tgz", + "integrity": "sha512-LMshMVP0ZhACNjQNYXiU1iZJ6QCcv0lUdPDPugqGvCGXt5xtRVBPdtA0qU12pEXZzpWAhWlZYptfdAFq10DOVQ==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", @@ -8223,6 +8252,17 @@ "url": "https://github.com/sponsors/Brooooooklyn" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, "node_modules/@ng-select/ng-select": { "version": "13.9.1", "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-13.9.1.tgz", @@ -8758,6 +8798,166 @@ "node": "^16.13.0 || >=18.0.0" } }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.8.0.tgz", + "integrity": "sha512-A6Te2KlINtcOo/depXJzPyjbk9E0cmgbom/sm/49XdQ8G94aDfyIIY1RIdwmDCK5NVd74KFG3JIByTk5+VnAhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-darwin-x64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.8.0.tgz", + "integrity": "sha512-UpqayUjgalArXaDvOoshqSelTrEp42cGDsZGy0sqpxwBpm3oPQ8wE1d7oBAmRo208rAxOuFP0LZRFUqRrwGvLA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.8.0.tgz", + "integrity": "sha512-dUR2fsLyKZYMHByvjy2zvmdMbsdXAiP+6uTlIAuu8eHMZ2FPQCAtt7lPYLwOFUxUXChbek2AJ+uCI0gRAgK/eg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.8.0.tgz", + "integrity": "sha512-GuZ7t0SzSX5ksLYva7koKZovQ5h/Kr1pFbOsQcBf3VLREBqFPSz6t7CVYpsIsMhiu/I3EKq6FZI3wDOJbee5uw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.8.0.tgz", + "integrity": "sha512-CiI955Q+XZmBBZ7cQqQg0MhGEFwZIgSpJnjPfWBt3iOYP8aE6nZpNOkmD7O8XcN/nEwwyeCOF8euXqEStwsk8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.8.0.tgz", + "integrity": "sha512-Iy9DpvVisxsfNh4gOinmMQ4cLWdBlgvt1wmry1UwvcXg479p1oJQ1Kp1wksUZoWYqrAG8VPZUmkE0f7gjyHTGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.8.0.tgz", + "integrity": "sha512-kZrrXXzVSbqwmdTmQ9xL4Jhi0/FSLrePSxYCL9oOM3Rsj0lmo/aC9kz4NBv1ZzuqT7fumpBOnhqiL1QyhOWOeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.8.0.tgz", + "integrity": "sha512-0l9jEMN8NhULKYCFiDF7QVpMMNG40duya+OF8dH0OzFj52N0zTsvsgLY72TIhslCB/cC74oAzsmWEIiFslscnA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.8.0.tgz", + "integrity": "sha512-5miZJmRSwx1jybBsiB3NGocXL9TxGdT2D+dOqR2fsLklpGz0ItEWm8+i8lhDjgOdAr2nFcuQUfQMY57f9FOHrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.8.0.tgz", + "integrity": "sha512-0P5r+bDuSNvoWys+6C1/KqGpYlqwSHpigCcyRzR62iZpT3OooZv+nWO06RlURkxMR8LNvYXTSSLvoLkjxqM8uQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -10856,6 +11056,15 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", @@ -13196,6 +13405,59 @@ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "license": "BSD-2-Clause" }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", + "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", + "dev": true, + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/7zip-bin": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", @@ -14298,11 +14560,10 @@ } }, "node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "dev": true, - "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -18077,6 +18338,18 @@ "node": ">=10.13.0" } }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -20259,6 +20532,43 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1" + } + }, + "node_modules/front-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/front-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/front-matter/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -28045,6 +28355,12 @@ "license": "MIT", "peer": true }, + "node_modules/node-machine-id": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", + "dev": true + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -28513,6 +28829,209 @@ "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "license": "MIT" }, + "node_modules/nx": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.8.0.tgz", + "integrity": "sha512-+BN5B5DFBB5WswD8flDDTnr4/bf1VTySXOv60aUAllHqR+KS6deT0p70TTMZF4/A2n/L2UCWDaDro37MGaYozA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@napi-rs/wasm-runtime": "0.2.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.2", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.8.3", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "resolve.exports": "2.0.3", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yaml": "^2.6.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "20.8.0", + "@nx/nx-darwin-x64": "20.8.0", + "@nx/nx-freebsd-x64": "20.8.0", + "@nx/nx-linux-arm-gnueabihf": "20.8.0", + "@nx/nx-linux-arm64-gnu": "20.8.0", + "@nx/nx-linux-arm64-musl": "20.8.0", + "@nx/nx-linux-x64-gnu": "20.8.0", + "@nx/nx-linux-x64-musl": "20.8.0", + "@nx/nx-win32-arm64-msvc": "20.8.0", + "@nx/nx-win32-x64-msvc": "20.8.0" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/nx/node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nx/node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/nx/node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/nx/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/nx/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/nx/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/nx/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nx/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nx/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nx/node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/nx/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -31294,7 +31813,6 @@ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" } diff --git a/package.json b/package.json index f24588c4c82..28d243e1c32 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,7 @@ "json5": "2.2.3", "lint-staged": "15.4.1", "mini-css-extract-plugin": "2.9.2", + "nx": "20.8.0", "postcss": "8.5.1", "postcss-loader": "8.1.1", "prettier": "3.4.2", From e3d1ef456e8dfaba8fbdac1a420f513a8acebd17 Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Tue, 15 Apr 2025 14:37:12 -0400 Subject: [PATCH 11/14] [PM-14909] Add data/state for security task completion notification (#14279) * include tasks with notification cipher data * send security task information with update success message for notification * mark completed cipher updates with tasks as complete * refactor notification confirmation components and add stories * add keyhole icon * add conditional footer button to notification confirmation component * add external link icon * add external link icon to action button * add notification confirmation footer story * use keyhole icon if there are no additional security tasks to complete * add new message catalog entries to chrome.i18n * reimplement sending security task information with update success message for notification * open tasks in extension from confirmation notification button * update vault message key and dismiss all security tasks for a given cipher upon password update * resolve changes against updated main branch basis * put task fetching behind feature flag and update tests * cleanup * more cleanup --- .../abstractions/notification.background.ts | 1 + .../notification.background.spec.ts | 98 +++++++++++++- .../background/notification.background.ts | 123 ++++++++++++++++-- .../abstractions/notification-bar.ts | 7 +- apps/browser/src/autofill/notification/bar.ts | 6 +- ...rlay-notifications-content.service.spec.ts | 24 ++-- .../overlay-notifications-content.service.ts | 6 +- .../browser/src/background/main.background.ts | 23 ++-- 8 files changed, 247 insertions(+), 41 deletions(-) diff --git a/apps/browser/src/autofill/background/abstractions/notification.background.ts b/apps/browser/src/autofill/background/abstractions/notification.background.ts index 851f07576dd..6b3c91a109c 100644 --- a/apps/browser/src/autofill/background/abstractions/notification.background.ts +++ b/apps/browser/src/autofill/background/abstractions/notification.background.ts @@ -95,6 +95,7 @@ type NotificationBackgroundExtensionMessageHandlers = { unlockCompleted: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; bgGetFolderData: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; bgCloseNotificationBar: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; + bgOpenAtRisksPasswords: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; bgAdjustNotificationBar: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; bgAddLogin: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; bgChangedPassword: ({ message, sender }: BackgroundOnMessageHandlerParams) => Promise; diff --git a/apps/browser/src/autofill/background/notification.background.spec.ts b/apps/browser/src/autofill/background/notification.background.spec.ts index ebdd244e140..ffc416ab62a 100644 --- a/apps/browser/src/autofill/background/notification.background.spec.ts +++ b/apps/browser/src/autofill/background/notification.background.spec.ts @@ -1,5 +1,5 @@ import { mock, MockProxy } from "jest-mock-extended"; -import { BehaviorSubject, firstValueFrom } from "rxjs"; +import { BehaviorSubject, firstValueFrom, of } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { DefaultPolicyService } from "@bitwarden/common/admin-console/services/policy/default-policy.service"; @@ -12,6 +12,7 @@ import { UserNotificationSettingsService } from "@bitwarden/common/autofill/serv import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { SelfHostedEnvironment } from "@bitwarden/common/platform/services/default-environment.service"; import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; import { UserId } from "@bitwarden/common/types/guid"; @@ -19,6 +20,7 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { CipherService } from "@bitwarden/common/vault/services/cipher.service"; import { FolderService } from "@bitwarden/common/vault/services/folder/folder.service"; +import { TaskService, SecurityTask } from "@bitwarden/common/vault/tasks"; import { BrowserApi } from "../../platform/browser/browser-api"; import { NotificationQueueMessageType } from "../enums/notification-queue-message-type.enum"; @@ -46,6 +48,8 @@ jest.mock("rxjs", () => { }); describe("NotificationBackground", () => { + const messagingService = mock(); + const taskService = mock(); let notificationBackground: NotificationBackground; const autofillService = mock(); const cipherService = mock(); @@ -88,6 +92,8 @@ describe("NotificationBackground", () => { policyService, themeStateService, userNotificationSettingsService, + taskService, + messagingService, ); }); @@ -201,8 +207,8 @@ describe("NotificationBackground", () => { await flushPromises(); expect(notificationBackground["handleSaveCipherMessage"]).toHaveBeenCalledWith( - message.data.commandToRetry.message, - message.data.commandToRetry.sender, + message.data?.commandToRetry?.message, + message.data?.commandToRetry?.sender, ); }); }); @@ -498,7 +504,7 @@ describe("NotificationBackground", () => { expect(pushChangePasswordToQueueSpy).toHaveBeenCalledWith( null, "example.com", - message.data.newPassword, + message.data?.newPassword, sender.tab, true, ); @@ -570,7 +576,7 @@ describe("NotificationBackground", () => { expect(pushChangePasswordToQueueSpy).toHaveBeenCalledWith( "cipher-id", "example.com", - message.data.newPassword, + message.data?.newPassword, sender.tab, ); }); @@ -618,7 +624,7 @@ describe("NotificationBackground", () => { expect(pushChangePasswordToQueueSpy).toHaveBeenCalledWith( "cipher-id", "example.com", - message.data.newPassword, + message.data?.newPassword, sender.tab, ); }); @@ -844,6 +850,86 @@ describe("NotificationBackground", () => { ); }); + it("completes password update notification with a security task notice if any are present for the cipher, and dismisses tasks for the updated cipher", async () => { + const mockCipherId = "testId"; + const mockOrgId = "testOrgId"; + const mockSecurityTask = { + id: "testTaskId", + organizationId: mockOrgId, + cipherId: mockCipherId, + type: 0, + status: 0, + creationDate: new Date(), + revisionDate: new Date(), + } as SecurityTask; + const mockSecurityTask2 = { + ...mockSecurityTask, + id: "testTaskId2", + cipherId: "testId2", + } as SecurityTask; + taskService.tasksEnabled$.mockImplementation(() => of(true)); + taskService.pendingTasks$.mockImplementation(() => + of([mockSecurityTask, mockSecurityTask2]), + ); + jest + .spyOn(notificationBackground as any, "getNotificationFlag") + .mockResolvedValueOnce(true); + jest.spyOn(notificationBackground as any, "getOrgData").mockResolvedValueOnce([ + { + id: mockOrgId, + name: "Org Name, LLC", + productTierType: 3, + }, + ]); + + const tab = createChromeTabMock({ id: 1, url: "https://example.com" }); + const sender = mock({ tab }); + const message: NotificationBackgroundExtensionMessage = { + command: "bgSaveCipher", + edit: false, + folder: "folder-id", + }; + const queueMessage = mock({ + type: NotificationQueueMessageType.ChangePassword, + tab, + domain: "example.com", + newPassword: "newPassword", + }); + notificationBackground["notificationQueue"] = [queueMessage]; + const cipherView = mock({ + id: mockCipherId, + organizationId: mockOrgId, + login: { username: "testUser" }, + }); + getDecryptedCipherByIdSpy.mockResolvedValueOnce(cipherView); + + sendMockExtensionMessage(message, sender); + await flushPromises(); + + expect(editItemSpy).not.toHaveBeenCalled(); + expect(createWithServerSpy).not.toHaveBeenCalled(); + expect(updatePasswordSpy).toHaveBeenCalledWith( + cipherView, + queueMessage.newPassword, + message.edit, + sender.tab, + mockCipherId, + ); + expect(updateWithServerSpy).toHaveBeenCalled(); + expect(tabSendMessageDataSpy).toHaveBeenCalledWith( + sender.tab, + "saveCipherAttemptCompleted", + { + cipherId: "testId", + task: { + orgName: "Org Name, LLC", + remainingTasksCount: 1, + }, + username: "testUser", + }, + ); + }); + it("updates the cipher password if the queue message was locked and an existing cipher has the same username as the message", async () => { const tab = createChromeTabMock({ id: 1, url: "https://example.com" }); const sender = mock({ tab }); diff --git a/apps/browser/src/autofill/background/notification.background.ts b/apps/browser/src/autofill/background/notification.background.ts index c2e90460dfc..1f0cc469e2c 100644 --- a/apps/browser/src/autofill/background/notification.background.ts +++ b/apps/browser/src/autofill/background/notification.background.ts @@ -1,6 +1,6 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { firstValueFrom, switchMap } from "rxjs"; +import { firstValueFrom, switchMap, map } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; @@ -22,16 +22,21 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { CipherType } from "@bitwarden/common/vault/enums"; +import { VaultMessages } from "@bitwarden/common/vault/enums/vault-messages.enum"; import { buildCipherIcon } from "@bitwarden/common/vault/icon/build-cipher-icon"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view"; import { LoginView } from "@bitwarden/common/vault/models/view/login.view"; +import { TaskService } from "@bitwarden/common/vault/tasks"; +import { SecurityTaskType } from "@bitwarden/common/vault/tasks/enums"; +import { SecurityTask } from "@bitwarden/common/vault/tasks/models/security-task"; import { openUnlockPopout } from "../../auth/popup/utils/auth-popout-window"; import { BrowserApi } from "../../platform/browser/browser-api"; @@ -70,6 +75,8 @@ export default class NotificationBackground { bgChangedPassword: ({ message, sender }) => this.changedPassword(message, sender), bgCloseNotificationBar: ({ message, sender }) => this.handleCloseNotificationBarMessage(message, sender), + bgOpenAtRisksPasswords: ({ message, sender }) => + this.handleOpenAtRisksPasswordsMessage(message, sender), bgGetActiveUserServerConfig: () => this.getActiveUserServerConfig(), bgGetDecryptedCiphers: () => this.getNotificationCipherData(), bgGetEnableChangedPasswordPrompt: () => this.getEnableChangedPasswordPrompt(), @@ -106,6 +113,8 @@ export default class NotificationBackground { private policyService: PolicyService, private themeStateService: ThemeStateService, private userNotificationSettingsService: UserNotificationSettingsServiceAbstraction, + private taskService: TaskService, + protected messagingService: MessagingService, ) {} init() { @@ -154,17 +163,20 @@ export default class NotificationBackground { firstValueFrom(this.domainSettingsService.showFavicons$), firstValueFrom(this.environmentService.environment$), ]); + const iconsServerUrl = env.getIconsUrl(); const activeUserId = await firstValueFrom( this.accountService.activeAccount$.pipe(getOptionalUserId), ); + const decryptedCiphers = await this.cipherService.getAllDecryptedForUrl( - currentTab.url, + currentTab?.url, activeUserId, ); return decryptedCiphers.map((view) => { const { id, name, reprompt, favorite, login } = view; + return { id, name, @@ -599,13 +611,13 @@ export default class NotificationBackground { try { await this.cipherService.createWithServer(cipher); await BrowserApi.tabSendMessageData(tab, "saveCipherAttemptCompleted", { - username: String(queueMessage?.username), - cipherId: String(cipher?.id), + username: queueMessage?.username && String(queueMessage.username), + cipherId: cipher?.id && String(cipher.id), }); await BrowserApi.tabSendMessage(tab, { command: "addedCipher" }); } catch (error) { await BrowserApi.tabSendMessageData(tab, "saveCipherAttemptCompleted", { - error: String(error.message), + error: error?.message && String(error.message), }); } } @@ -638,15 +650,49 @@ export default class NotificationBackground { return; } const cipher = await this.cipherService.encrypt(cipherView, userId); + + const shouldGetTasks = await this.getNotificationFlag(); + try { + const tasks = shouldGetTasks ? await this.getSecurityTasks(userId) : []; + const updatedCipherTask = tasks.find((task) => task.cipherId === cipherView?.id); + const cipherHasTask = !!updatedCipherTask?.id; + + let taskOrgName: string; + if (cipherHasTask && updatedCipherTask?.organizationId) { + const userOrgs = await this.getOrgData(); + taskOrgName = userOrgs.find(({ id }) => id === updatedCipherTask.organizationId)?.name; + } + + const taskData = cipherHasTask + ? { + remainingTasksCount: tasks.length - 1, + orgName: taskOrgName, + } + : undefined; + await this.cipherService.updateWithServer(cipher); + await BrowserApi.tabSendMessageData(tab, "saveCipherAttemptCompleted", { - username: String(cipherView?.login?.username), - cipherId: String(cipherView?.id), + username: cipherView?.login?.username && String(cipherView.login.username), + cipherId: cipherView?.id && String(cipherView.id), + task: taskData, }); + + // If the cipher had a security task, mark it as complete + if (cipherHasTask) { + // guard against multiple (redundant) security tasks per cipher + await Promise.all( + tasks.map((task) => { + if (task.cipherId === cipherView?.id) { + return this.taskService.markAsComplete(task.id, userId); + } + }), + ); + } } catch (error) { await BrowserApi.tabSendMessageData(tab, "saveCipherAttemptCompleted", { - error: String(error?.message), + error: error?.message && String(error.message), }); } } @@ -699,6 +745,32 @@ export default class NotificationBackground { return null; } + private async getSecurityTasks(userId: UserId) { + let tasks: SecurityTask[] = []; + + if (userId) { + tasks = await firstValueFrom( + this.taskService.tasksEnabled$(userId).pipe( + switchMap((tasksEnabled) => { + if (!tasksEnabled) { + return []; + } + + return this.taskService + .pendingTasks$(userId) + .pipe( + map((tasks) => + tasks.filter(({ type }) => type === SecurityTaskType.UpdateAtRiskCredential), + ), + ); + }), + ), + ); + } + + return tasks; + } + /** * Saves the current tab's domain to the never save list. * @@ -819,6 +891,41 @@ export default class NotificationBackground { }); } + /** + * Sends a message to the background to open the + * at-risk passwords extension view. Triggers + * notification closure as a side-effect. + * + * @param message - The extension message + * @param sender - The contextual sender of the message + */ + private async handleOpenAtRisksPasswordsMessage( + message: NotificationBackgroundExtensionMessage, + sender: chrome.runtime.MessageSender, + ) { + const browserAction = BrowserApi.getBrowserAction(); + + try { + // Set route of the popup before attempting to open it. + // If the vault is locked, this won't have an effect as the auth guards will + // redirect the user to the login page. + await browserAction.setPopup({ popup: "popup/index.html#/at-risk-passwords" }); + + await Promise.all([ + this.messagingService.send(VaultMessages.OpenAtRiskPasswords), + BrowserApi.tabSendMessageData(sender.tab, "closeNotificationBar", { + fadeOutNotification: !!message.fadeOutNotification, + }), + ]); + } finally { + // Reset the popup route to the default route so any subsequent + // popup openings will not open to the at-risk-passwords page. + await browserAction.setPopup({ + popup: "popup/index.html#/", + }); + } + } + /** * Sends a message back to the sender tab which triggers * an CSS adjustment of the notification bar. diff --git a/apps/browser/src/autofill/notification/abstractions/notification-bar.ts b/apps/browser/src/autofill/notification/abstractions/notification-bar.ts index 7e2fdab04d3..cbfeffcf2f4 100644 --- a/apps/browser/src/autofill/notification/abstractions/notification-bar.ts +++ b/apps/browser/src/autofill/notification/abstractions/notification-bar.ts @@ -29,11 +29,14 @@ type NotificationBarIframeInitData = { }; type NotificationBarWindowMessage = { - cipherId?: string; command: string; + data?: { + cipherId?: string; + task?: NotificationTaskInfo; + username?: string; + }; error?: string; initData?: NotificationBarIframeInitData; - username?: string; }; type NotificationBarWindowMessageHandlers = { diff --git a/apps/browser/src/autofill/notification/bar.ts b/apps/browser/src/autofill/notification/bar.ts index f544e75527c..d660790ee63 100644 --- a/apps/browser/src/autofill/notification/bar.ts +++ b/apps/browser/src/autofill/notification/bar.ts @@ -356,7 +356,8 @@ function openViewVaultItemPopout(e: Event, cipherId: string) { function handleSaveCipherConfirmation(message: NotificationBarWindowMessage) { const { theme, type } = notificationBarIframeInitData; - const { error, username, cipherId } = message; + const { error, data } = message; + const { username, cipherId, task } = data || {}; const i18n = getI18n(); const resolvedTheme = getResolvedTheme(theme ?? ThemeTypes.Light); @@ -371,8 +372,9 @@ function handleSaveCipherConfirmation(message: NotificationBarWindowMessage) { i18n, error, username: username ?? i18n.typeLogin, + task, handleOpenVault: (e) => cipherId && openViewVaultItemPopout(e, cipherId), - handleOpenTasks: () => {}, + handleOpenTasks: () => sendPlatformMessage({ command: "bgOpenAtRisksPasswords" }), }), document.body, ); diff --git a/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.spec.ts b/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.spec.ts index 8a8ccdf363b..28db10b35fa 100644 --- a/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.spec.ts +++ b/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.spec.ts @@ -23,8 +23,8 @@ describe("OverlayNotificationsContentService", () => { autofillInit = new AutofillInit( domQueryService, domElementVisibilityService, - null, - null, + undefined, + undefined, overlayNotificationsContentService, ); autofillInit.init(); @@ -89,7 +89,7 @@ describe("OverlayNotificationsContentService", () => { await flushPromises(); expect( - overlayNotificationsContentService["notificationBarIframeElement"].style.transform, + overlayNotificationsContentService["notificationBarIframeElement"]?.style.transform, ).toBe("translateX(100%)"); }); @@ -103,12 +103,12 @@ describe("OverlayNotificationsContentService", () => { }); await flushPromises(); - overlayNotificationsContentService["notificationBarIframeElement"].dispatchEvent( + overlayNotificationsContentService["notificationBarIframeElement"]?.dispatchEvent( new Event("load"), ); expect( - overlayNotificationsContentService["notificationBarIframeElement"].style.transform, + overlayNotificationsContentService["notificationBarIframeElement"]?.style.transform, ).toBe("translateX(0)"); }); @@ -134,7 +134,7 @@ describe("OverlayNotificationsContentService", () => { globalThis.dispatchEvent( new MessageEvent("message", { data: { command: "initNotificationBar" }, - source: overlayNotificationsContentService["notificationBarIframeElement"].contentWindow, + source: overlayNotificationsContentService["notificationBarIframeElement"]?.contentWindow, }), ); await flushPromises(); @@ -168,9 +168,9 @@ describe("OverlayNotificationsContentService", () => { data: { fadeOutNotification: true }, }); - expect(overlayNotificationsContentService["notificationBarIframeElement"].style.opacity).toBe( - "0", - ); + expect( + overlayNotificationsContentService["notificationBarIframeElement"]?.style.opacity, + ).toBe("0"); jest.advanceTimersByTime(150); @@ -210,7 +210,7 @@ describe("OverlayNotificationsContentService", () => { data: { height: 1000 }, }); - expect(overlayNotificationsContentService["notificationBarElement"].style.height).toBe( + expect(overlayNotificationsContentService["notificationBarElement"]?.style.height).toBe( "1000px", ); }); @@ -236,13 +236,13 @@ describe("OverlayNotificationsContentService", () => { sendMockExtensionMessage({ command: "saveCipherAttemptCompleted", - data: { error: "" }, + data: { error: undefined }, }); expect( overlayNotificationsContentService["notificationBarIframeElement"].contentWindow .postMessage, - ).toHaveBeenCalledWith({ command: "saveCipherAttemptCompleted", error: "" }, "*"); + ).toHaveBeenCalledWith({ command: "saveCipherAttemptCompleted", error: undefined }, "*"); }); }); diff --git a/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts b/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts index 662ec624dc4..519521feaa9 100644 --- a/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts +++ b/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts @@ -135,9 +135,13 @@ export class OverlayNotificationsContentService * @private */ private handleSaveCipherAttemptCompletedMessage(message: NotificationsExtensionMessage) { + // destructure error out of data + const { error, ...otherData } = message?.data || {}; + this.sendMessageToNotificationBarIframe({ command: "saveCipherAttemptCompleted", - error: message.data?.error, + data: Object.keys(otherData).length ? otherData : undefined, + error, }); } diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index a5001e0c5b7..c437698f525 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -1186,6 +1186,17 @@ export default class MainBackground { this.authService, () => this.generatePasswordToClipboard(), ); + + this.taskService = new DefaultTaskService( + this.stateProvider, + this.apiService, + this.organizationService, + this.configService, + this.authService, + this.notificationsService, + messageListener, + ); + this.notificationBackground = new NotificationBackground( this.accountService, this.authService, @@ -1200,6 +1211,8 @@ export default class MainBackground { this.policyService, this.themeStateService, this.userNotificationSettingsService, + this.taskService, + this.messagingService, ); this.overlayNotificationsBackground = new OverlayNotificationsBackground( @@ -1304,16 +1317,6 @@ export default class MainBackground { this.configService, ); - this.taskService = new DefaultTaskService( - this.stateProvider, - this.apiService, - this.organizationService, - this.configService, - this.authService, - this.notificationsService, - messageListener, - ); - this.inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService(); this.ipcContentScriptManagerService = new IpcContentScriptManagerService(this.configService); From 4cddc40828920914776a05fc906b087ac3bfcf12 Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Tue, 15 Apr 2025 14:39:48 -0400 Subject: [PATCH 12/14] remove inlineAutofillMenuRefreshAddEditCipher message (#13805) --- .../src/autofill/background/overlay.background.spec.ts | 5 ----- apps/browser/src/autofill/background/overlay.background.ts | 1 - .../background/overlay.background.deprecated.spec.ts | 3 --- .../deprecated/background/overlay.background.deprecated.ts | 1 - 4 files changed, 10 deletions(-) diff --git a/apps/browser/src/autofill/background/overlay.background.spec.ts b/apps/browser/src/autofill/background/overlay.background.spec.ts index 3085dbc2f8d..0fe4a459048 100644 --- a/apps/browser/src/autofill/background/overlay.background.spec.ts +++ b/apps/browser/src/autofill/background/overlay.background.spec.ts @@ -117,7 +117,6 @@ describe("OverlayBackground", () => { let getFrameDetailsSpy: jest.SpyInstance; let tabsSendMessageSpy: jest.SpyInstance; let tabSendMessageDataSpy: jest.SpyInstance; - let sendMessageSpy: jest.SpyInstance; let getTabFromCurrentWindowIdSpy: jest.SpyInstance; let getTabSpy: jest.SpyInstance; let openUnlockPopoutSpy: jest.SpyInstance; @@ -228,7 +227,6 @@ describe("OverlayBackground", () => { tabSendMessageDataSpy = jest .spyOn(BrowserApi, "tabSendMessageData") .mockImplementation(() => Promise.resolve()); - sendMessageSpy = jest.spyOn(BrowserApi, "sendMessage"); getTabFromCurrentWindowIdSpy = jest.spyOn(BrowserApi, "getTabFromCurrentWindowId"); getTabSpy = jest.spyOn(BrowserApi, "getTab"); openUnlockPopoutSpy = jest.spyOn(overlayBackground as any, "openUnlockPopout"); @@ -1553,7 +1551,6 @@ describe("OverlayBackground", () => { await flushPromises(); expect(cipherService.setAddEditCipherInfo).toHaveBeenCalled(); - expect(sendMessageSpy).toHaveBeenCalledWith("inlineAutofillMenuRefreshAddEditCipher"); expect(openAddEditVaultItemPopoutSpy).toHaveBeenCalled(); }); @@ -1579,7 +1576,6 @@ describe("OverlayBackground", () => { await flushPromises(); expect(cipherService.setAddEditCipherInfo).toHaveBeenCalled(); - expect(sendMessageSpy).toHaveBeenCalledWith("inlineAutofillMenuRefreshAddEditCipher"); expect(openAddEditVaultItemPopoutSpy).toHaveBeenCalled(); }); @@ -1618,7 +1614,6 @@ describe("OverlayBackground", () => { await flushPromises(); expect(cipherService.setAddEditCipherInfo).toHaveBeenCalled(); - expect(sendMessageSpy).toHaveBeenCalledWith("inlineAutofillMenuRefreshAddEditCipher"); expect(openAddEditVaultItemPopoutSpy).toHaveBeenCalled(); }); diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index fa0ae9b9b3e..a2088f50a11 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -2434,7 +2434,6 @@ export class OverlayBackground implements OverlayBackgroundInterface { cipherId: cipherView.id, cipherType: addNewCipherType, }); - await BrowserApi.sendMessage("inlineAutofillMenuRefreshAddEditCipher"); } catch (error) { this.logService.error("Error building cipher and opening add/edit vault item popout", error); } diff --git a/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.spec.ts b/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.spec.ts index 128dd189878..68f8032350e 100644 --- a/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.spec.ts +++ b/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.spec.ts @@ -647,9 +647,6 @@ describe("OverlayBackground", () => { await flushPromises(); expect(overlayBackground["cipherService"].setAddEditCipherInfo).toHaveBeenCalled(); - expect(BrowserApi.sendMessage).toHaveBeenCalledWith( - "inlineAutofillMenuRefreshAddEditCipher", - ); expect(overlayBackground["openAddEditVaultItemPopout"]).toHaveBeenCalled(); }); }); diff --git a/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.ts b/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.ts index d0fad4cd00e..c9eb442d75d 100644 --- a/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.ts +++ b/apps/browser/src/autofill/deprecated/background/overlay.background.deprecated.ts @@ -678,7 +678,6 @@ class LegacyOverlayBackground implements OverlayBackgroundInterface { ); await this.openAddEditVaultItemPopout(sender.tab, { cipherId: cipherView.id }); - await BrowserApi.sendMessage("inlineAutofillMenuRefreshAddEditCipher"); } /** From 8258ea39b0b33eaabf8320cea98b64208b96f931 Mon Sep 17 00:00:00 2001 From: Shane Melton Date: Tue, 15 Apr 2025 12:17:41 -0700 Subject: [PATCH 13/14] [PM-18903] Desktop sync issues (#13681) * [PM-18707] Use different BroadcasterSubscriptionId in base view component to avoid collision with desktop view component * [PM-18707] Use userId instead of payloadUserId for cipher notification syncs * [PM-19032] Live Sync on Desktop (#13851) * migrate the vault-items to an observables rather than async/promises - this helps keep data in sync with the service state and avoids race conditions * migrate the view component to an observables rather than async/promises - this helps keep data in sync with the service state and avoids race conditions * decrypt saved cipher from server * bump timeout for upserting ciphers * mark `go` as async in desktop vault - previously it was a floating promise * Revert "mark `go` as async in desktop vault" This reverts commit fd28f40b187c39fb30d1d1ab2972d398b2673419. * Revert "bump timeout for upserting ciphers" This reverts commit e963acc377b0018fb1f90d4e9d181959820e00b3. * move vault utilities to `common` rather than `lib` to avoid circular dependencies * use `perUserCache$` for `cipherViews$` to avoid new subscriptions from being created * use userId from observable rather than locally set to be the most up to date * [PM-18707] Add clearBuffer$ input to perUserCache$ helper so that the internal share replay buffers can be cleared * [PM-18707] Rework forceCipherViews$ to clearBuffer$ refactor - Add dependency for cipherDecryptionKeys$ for the cipherViews so that decryption is never attempted without keys * [PM-18707] Add overload to perUserCache to satisfy type checker * [PM-18707] Fix overloads * [PM-18707] Add check for empty failed to decrypt ciphers * [PM-18707] Mark vault component for check after observable emits. The cipherViews$ observable now persists between subscriptions, meaning that updates via the sync push notifications can occur outside the AngularZone causing delays in updating the view. --------- Co-authored-by: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> Co-authored-by: Nick Krantz --- .../vault/app/vault/vault-items.component.ts | 3 - .../src/vault/app/vault/view.component.ts | 4 +- .../vault/individual-vault/vault.component.ts | 14 +- .../vault/components/add-edit.component.ts | 9 +- .../vault/components/vault-items.component.ts | 111 +++++++----- .../src/vault/components/view.component.ts | 167 +++++++++++------- .../internal/default-notifications.service.ts | 4 +- .../src/vault/services/cipher.service.ts | 64 +++---- .../tasks/services/default-task.service.ts | 5 +- .../src/vault/utils/observable-utilities.ts | 26 ++- 10 files changed, 239 insertions(+), 168 deletions(-) diff --git a/apps/desktop/src/vault/app/vault/vault-items.component.ts b/apps/desktop/src/vault/app/vault/vault-items.component.ts index b7a45bd2467..d5838459ff7 100644 --- a/apps/desktop/src/vault/app/vault/vault-items.component.ts +++ b/apps/desktop/src/vault/app/vault/vault-items.component.ts @@ -27,9 +27,6 @@ export class VaultItemsComponent extends BaseVaultItemsComponent { // eslint-disable-next-line rxjs-angular/prefer-takeuntil searchBarService.searchText$.pipe(distinctUntilChanged()).subscribe((searchText) => { this.searchText = searchText; - // 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.search(200); }); } diff --git a/apps/desktop/src/vault/app/vault/view.component.ts b/apps/desktop/src/vault/app/vault/view.component.ts index 9ddf18fff93..e5f677cbca6 100644 --- a/apps/desktop/src/vault/app/vault/view.component.ts +++ b/apps/desktop/src/vault/app/vault/view.component.ts @@ -126,9 +126,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro } async ngOnChanges() { - await super.load(); - - if (this.cipher.decryptionFailure) { + if (this.cipher?.decryptionFailure) { DecryptionFailureDialogComponent.open(this.dialogService, { cipherIds: [this.cipherId as CipherId], }); diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts index c2173e29ee0..7055f164a53 100644 --- a/apps/web/src/app/vault/individual-vault/vault.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault.component.ts @@ -13,6 +13,7 @@ import { Subject, } from "rxjs"; import { + catchError, concatMap, debounceTime, filter, @@ -23,7 +24,6 @@ import { take, takeUntil, tap, - catchError, } from "rxjs/operators"; import { @@ -64,6 +64,7 @@ import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-repromp import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { ServiceUtils } from "@bitwarden/common/vault/service-utils"; +import { filterOutNullish } from "@bitwarden/common/vault/utils/observable-utilities"; import { DialogRef, DialogService, Icons, ToastService } from "@bitwarden/components"; import { AddEditFolderDialogComponent, @@ -138,7 +139,6 @@ const SearchTextDebounceInterval = 200; VaultFilterModule, VaultItemsModule, SharedModule, - DecryptionFailureDialogComponent, ], providers: [ RoutedVaultFilterService, @@ -348,9 +348,8 @@ export class VaultComponent implements OnInit, OnDestroy { ]).pipe( filter(([ciphers, filter]) => ciphers != undefined && filter != undefined), concatMap(async ([ciphers, filter, searchText]) => { - const failedCiphers = await firstValueFrom( - this.cipherService.failedToDecryptCiphers$(activeUserId), - ); + const failedCiphers = + (await firstValueFrom(this.cipherService.failedToDecryptCiphers$(activeUserId))) ?? []; const filterFunction = createFilterFunction(filter); // Append any failed to decrypt ciphers to the top of the cipher list const allCiphers = [...failedCiphers, ...ciphers]; @@ -472,6 +471,7 @@ export class VaultComponent implements OnInit, OnDestroy { firstSetup$ .pipe( switchMap(() => this.cipherService.failedToDecryptCiphers$(activeUserId)), + filterOutNullish(), map((ciphers) => ciphers.filter((c) => !c.isDeleted)), filter((ciphers) => ciphers.length > 0), take(1), @@ -528,6 +528,10 @@ export class VaultComponent implements OnInit, OnDestroy { this.isEmpty = collections?.length === 0 && ciphers?.length === 0; this.performingInitialLoad = false; this.refreshing = false; + + // Explicitly mark for check to ensure the view is updated + // Some sources are not always emitted within the Angular zone (e.g. ciphers updated via WS notifications) + this.changeDetectorRef.markForCheck(); }, ); } diff --git a/libs/angular/src/vault/components/add-edit.component.ts b/libs/angular/src/vault/components/add-edit.component.ts index 2393863bb5f..b9defa8383d 100644 --- a/libs/angular/src/vault/components/add-edit.component.ts +++ b/libs/angular/src/vault/components/add-edit.component.ts @@ -422,10 +422,15 @@ export class AddEditComponent implements OnInit, OnDestroy { const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); const cipher = await this.encryptCipher(activeUserId); + try { this.formPromise = this.saveCipher(cipher); - await this.formPromise; - this.cipher.id = cipher.id; + const savedCipher = await this.formPromise; + + // Reset local cipher from the saved cipher returned from the server + this.cipher = await savedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(savedCipher, activeUserId), + ); this.toastService.showToast({ variant: "success", title: null, diff --git a/libs/angular/src/vault/components/vault-items.component.ts b/libs/angular/src/vault/components/vault-items.component.ts index f7280cb74b3..852302cc0c4 100644 --- a/libs/angular/src/vault/components/vault-items.component.ts +++ b/libs/angular/src/vault/components/vault-items.component.ts @@ -1,13 +1,22 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core"; -import { BehaviorSubject, Subject, firstValueFrom, from, switchMap, takeUntil } from "rxjs"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { + BehaviorSubject, + Subject, + combineLatest, + filter, + from, + of, + switchMap, + takeUntil, +} from "rxjs"; import { SearchService } from "@bitwarden/common/abstractions/search.service"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; @@ -21,17 +30,17 @@ export class VaultItemsComponent implements OnInit, OnDestroy { loaded = false; ciphers: CipherView[] = []; - filter: (cipher: CipherView) => boolean = null; deleted = false; organization: Organization; protected searchPending = false; - private userId: UserId; + /** Construct filters as an observable so it can be appended to the cipher stream. */ + private _filter$ = new BehaviorSubject<(cipher: CipherView) => boolean | null>(null); private destroy$ = new Subject(); - private searchTimeout: any = null; private isSearchable: boolean = false; private _searchText$ = new BehaviorSubject(""); + get searchText() { return this._searchText$.value; } @@ -39,18 +48,28 @@ export class VaultItemsComponent implements OnInit, OnDestroy { this._searchText$.next(value); } + get filter() { + return this._filter$.value; + } + + set filter(value: (cipher: CipherView) => boolean | null) { + this._filter$.next(value); + } + constructor( protected searchService: SearchService, protected cipherService: CipherService, protected accountService: AccountService, - ) {} + ) { + this.subscribeToCiphers(); + } async ngOnInit() { - this.userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - - this._searchText$ + combineLatest([getUserId(this.accountService.activeAccount$), this._searchText$]) .pipe( - switchMap((searchText) => from(this.searchService.isSearchable(this.userId, searchText))), + switchMap(([userId, searchText]) => + from(this.searchService.isSearchable(userId, searchText)), + ), takeUntil(this.destroy$), ) .subscribe((isSearchable) => { @@ -80,23 +99,6 @@ export class VaultItemsComponent implements OnInit, OnDestroy { async applyFilter(filter: (cipher: CipherView) => boolean = null) { this.filter = filter; - await this.search(null); - } - - async search(timeout: number = null, indexedCiphers?: CipherView[]) { - this.searchPending = false; - if (this.searchTimeout != null) { - clearTimeout(this.searchTimeout); - } - if (timeout == null) { - await this.doSearch(indexedCiphers); - return; - } - this.searchPending = true; - this.searchTimeout = setTimeout(async () => { - await this.doSearch(indexedCiphers); - this.searchPending = false; - }, timeout); } selectCipher(cipher: CipherView) { @@ -121,25 +123,44 @@ export class VaultItemsComponent implements OnInit, OnDestroy { protected deletedFilter: (cipher: CipherView) => boolean = (c) => c.isDeleted === this.deleted; - protected async doSearch(indexedCiphers?: CipherView[], userId?: UserId) { - // Get userId from activeAccount if not provided from parent stream - if (!userId) { - userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - } + /** + * Creates stream of dependencies that results in the list of ciphers to display + * within the vault list. + * + * Note: This previously used promises but race conditions with how the ciphers were + * stored in electron. Using observables is more reliable as fresh values will always + * cascade through the components. + */ + private subscribeToCiphers() { + getUserId(this.accountService.activeAccount$) + .pipe( + switchMap((userId) => + combineLatest([ + this.cipherService.cipherViews$(userId).pipe(filter((ciphers) => ciphers != null)), + this.cipherService.failedToDecryptCiphers$(userId), + this._searchText$, + this._filter$, + of(userId), + ]), + ), + switchMap(([indexedCiphers, failedCiphers, searchText, filter, userId]) => { + let allCiphers = indexedCiphers ?? []; + const _failedCiphers = failedCiphers ?? []; - indexedCiphers = - indexedCiphers ?? (await firstValueFrom(this.cipherService.cipherViews$(userId))); + allCiphers = [..._failedCiphers, ...allCiphers]; - const failedCiphers = await firstValueFrom(this.cipherService.failedToDecryptCiphers$(userId)); - if (failedCiphers != null && failedCiphers.length > 0) { - indexedCiphers = [...failedCiphers, ...indexedCiphers]; - } - - this.ciphers = await this.searchService.searchCiphers( - this.userId, - this.searchText, - [this.filter, this.deletedFilter], - indexedCiphers, - ); + return this.searchService.searchCiphers( + userId, + searchText, + [filter, this.deletedFilter], + allCiphers, + ); + }), + takeUntilDestroyed(), + ) + .subscribe((ciphers) => { + this.ciphers = ciphers; + this.loaded = true; + }); } } diff --git a/libs/angular/src/vault/components/view.component.ts b/libs/angular/src/vault/components/view.component.ts index 0dda3c593b7..6b6f24f4217 100644 --- a/libs/angular/src/vault/components/view.component.ts +++ b/libs/angular/src/vault/components/view.component.ts @@ -11,7 +11,17 @@ import { OnInit, Output, } from "@angular/core"; -import { filter, firstValueFrom, map, Observable } from "rxjs"; +import { + BehaviorSubject, + combineLatest, + filter, + firstValueFrom, + map, + Observable, + of, + switchMap, + tap, +} from "rxjs"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; @@ -46,11 +56,22 @@ import { DialogService, ToastService } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; import { PasswordRepromptService } from "@bitwarden/vault"; -const BroadcasterSubscriptionId = "ViewComponent"; +const BroadcasterSubscriptionId = "BaseViewComponent"; @Directive() export class ViewComponent implements OnDestroy, OnInit { - @Input() cipherId: string; + /** Observable of cipherId$ that will update each time the `Input` updates */ + private _cipherId$ = new BehaviorSubject(null); + + @Input() + set cipherId(value: string) { + this._cipherId$.next(value); + } + + get cipherId(): string { + return this._cipherId$.getValue(); + } + @Input() collectionId: string; @Output() onEditCipher = new EventEmitter(); @Output() onCloneCipher = new EventEmitter(); @@ -126,13 +147,30 @@ export class ViewComponent implements OnDestroy, OnInit { switch (message.command) { case "syncCompleted": if (message.successfully) { - await this.load(); this.changeDetectorRef.detectChanges(); } break; } }); }); + + // Set up the subscription to the activeAccount$ and cipherId$ observables + combineLatest([this.accountService.activeAccount$.pipe(getUserId), this._cipherId$]) + .pipe( + tap(() => this.cleanUp()), + switchMap(([userId, cipherId]) => { + const cipher$ = this.cipherService.cipherViews$(userId).pipe( + map((ciphers) => ciphers?.find((c) => c.id === cipherId)), + filter((cipher) => !!cipher), + ); + return combineLatest([of(userId), cipher$]); + }), + ) + .subscribe(([userId, cipher]) => { + this.cipher = cipher; + + void this.constructCipherDetails(userId); + }); } ngOnDestroy() { @@ -140,70 +178,6 @@ export class ViewComponent implements OnDestroy, OnInit { this.cleanUp(); } - async load() { - this.cleanUp(); - - // Grab individual cipher from `cipherViews$` for the most up-to-date information - const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); - this.cipher = await firstValueFrom( - this.cipherService.cipherViews$(activeUserId).pipe( - map((ciphers) => ciphers?.find((c) => c.id === this.cipherId)), - filter((cipher) => !!cipher), - ), - ); - - this.canAccessPremium = await firstValueFrom( - this.billingAccountProfileStateService.hasPremiumFromAnySource$(activeUserId), - ); - this.showPremiumRequiredTotp = - this.cipher.login.totp && !this.canAccessPremium && !this.cipher.organizationUseTotp; - this.canDeleteCipher$ = this.cipherAuthorizationService.canDeleteCipher$(this.cipher, [ - this.collectionId as CollectionId, - ]); - this.canRestoreCipher$ = this.cipherAuthorizationService.canRestoreCipher$(this.cipher); - - if (this.cipher.folderId) { - this.folder = await ( - await firstValueFrom(this.folderService.folderViews$(activeUserId)) - ).find((f) => f.id == this.cipher.folderId); - } - - const canGenerateTotp = - this.cipher.type === CipherType.Login && - this.cipher.login.totp && - (this.cipher.organizationUseTotp || this.canAccessPremium); - - this.totpInfo$ = canGenerateTotp - ? this.totpService.getCode$(this.cipher.login.totp).pipe( - map((response) => { - const epoch = Math.round(new Date().getTime() / 1000.0); - const mod = epoch % response.period; - - // Format code - const totpCodeFormatted = - response.code.length > 4 - ? `${response.code.slice(0, Math.floor(response.code.length / 2))} ${response.code.slice(Math.floor(response.code.length / 2))}` - : response.code; - - return { - totpCode: response.code, - totpCodeFormatted, - totpDash: +(Math.round(((78.6 / response.period) * mod + "e+2") as any) + "e-2"), - totpSec: response.period - mod, - totpLow: response.period - mod <= 7, - } as TotpInfo; - }), - ) - : undefined; - - if (this.previousCipherId !== this.cipherId) { - // 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.eventCollectionService.collect(EventType.Cipher_ClientViewed, this.cipherId); - } - this.previousCipherId = this.cipherId; - } - async edit() { this.onEditCipher.emit(this.cipher); } @@ -533,4 +507,61 @@ export class ViewComponent implements OnDestroy, OnInit { this.showCardCode = false; this.passwordReprompted = false; } + + /** + * When a cipher is viewed, construct all details for the view that are not directly + * available from the cipher object itself. + */ + private async constructCipherDetails(userId: UserId) { + this.canAccessPremium = await firstValueFrom( + this.billingAccountProfileStateService.hasPremiumFromAnySource$(userId), + ); + this.showPremiumRequiredTotp = + this.cipher.login.totp && !this.canAccessPremium && !this.cipher.organizationUseTotp; + this.canDeleteCipher$ = this.cipherAuthorizationService.canDeleteCipher$(this.cipher, [ + this.collectionId as CollectionId, + ]); + this.canRestoreCipher$ = this.cipherAuthorizationService.canRestoreCipher$(this.cipher); + + if (this.cipher.folderId) { + this.folder = await ( + await firstValueFrom(this.folderService.folderViews$(userId)) + ).find((f) => f.id == this.cipher.folderId); + } + + const canGenerateTotp = + this.cipher.type === CipherType.Login && + this.cipher.login.totp && + (this.cipher.organizationUseTotp || this.canAccessPremium); + + this.totpInfo$ = canGenerateTotp + ? this.totpService.getCode$(this.cipher.login.totp).pipe( + map((response) => { + const epoch = Math.round(new Date().getTime() / 1000.0); + const mod = epoch % response.period; + + // Format code + const totpCodeFormatted = + response.code.length > 4 + ? `${response.code.slice(0, Math.floor(response.code.length / 2))} ${response.code.slice(Math.floor(response.code.length / 2))}` + : response.code; + + return { + totpCode: response.code, + totpCodeFormatted, + totpDash: +(Math.round(((78.6 / response.period) * mod + "e+2") as any) + "e-2"), + totpSec: response.period - mod, + totpLow: response.period - mod <= 7, + } as TotpInfo; + }), + ) + : undefined; + + if (this.previousCipherId !== this.cipherId) { + // 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.eventCollectionService.collect(EventType.Cipher_ClientViewed, this.cipherId); + } + this.previousCipherId = this.cipherId; + } } diff --git a/libs/common/src/platform/notifications/internal/default-notifications.service.ts b/libs/common/src/platform/notifications/internal/default-notifications.service.ts index 423b3370455..40c93f8f22a 100644 --- a/libs/common/src/platform/notifications/internal/default-notifications.service.ts +++ b/libs/common/src/platform/notifications/internal/default-notifications.service.ts @@ -153,14 +153,14 @@ export class DefaultNotificationsService implements NotificationsServiceAbstract await this.syncService.syncUpsertCipher( notification.payload as SyncCipherNotification, notification.type === NotificationType.SyncCipherUpdate, - payloadUserId, + userId, ); break; case NotificationType.SyncCipherDelete: case NotificationType.SyncLoginDelete: await this.syncService.syncDeleteCipher( notification.payload as SyncCipherNotification, - payloadUserId, + userId, ); break; case NotificationType.SyncFolderCreate: diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 8d4146eaaba..c192876c83e 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -1,17 +1,6 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { - combineLatest, - filter, - firstValueFrom, - map, - merge, - Observable, - of, - shareReplay, - Subject, - switchMap, -} from "rxjs"; +import { combineLatest, filter, firstValueFrom, map, Observable, Subject, switchMap } from "rxjs"; import { SemVer } from "semver"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -40,6 +29,7 @@ import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypt import { StateProvider } from "../../platform/state"; import { CipherId, CollectionId, OrganizationId, UserId } from "../../types/guid"; import { OrgKey, UserKey } from "../../types/key"; +import { perUserCache$ } from "../../vault/utils/observable-utilities"; import { CipherService as CipherServiceAbstraction } from "../abstractions/cipher.service"; import { CipherFileUploadService } from "../abstractions/file-upload/cipher-file-upload.service"; import { FieldType } from "../enums"; @@ -91,11 +81,12 @@ export class CipherService implements CipherServiceAbstraction { this.sortCiphersByLastUsed, ); /** - * Observable that forces the `cipherViews$` observable to re-emit with the provided value. - * Used to let subscribers of `cipherViews$` know that the decrypted ciphers have been cleared for the active user. + * Observable that forces the `cipherViews$` observable for the given user to emit a null value. + * Used to let subscribers of `cipherViews$` know that the decrypted ciphers have been cleared for the user and to + * clear them from the shareReplay buffer created in perUserCache$(). * @private */ - private forceCipherViews$: Subject = new Subject(); + private clearCipherViewsForUser$: Subject = new Subject(); constructor( private keyService: KeyService, @@ -132,13 +123,16 @@ export class CipherService implements CipherServiceAbstraction { * A `null` value indicates that the latest encrypted ciphers have not been decrypted yet and that * decryption is in progress. The latest decrypted ciphers will be emitted once decryption is complete. */ - cipherViews$(userId: UserId): Observable { - return combineLatest([this.encryptedCiphersState(userId).state$, this.localData$(userId)]).pipe( - filter(([ciphers]) => ciphers != null), // Skip if ciphers haven't been loaded yor synced yet - switchMap(() => merge(this.forceCipherViews$, this.getAllDecrypted(userId))), - shareReplay({ bufferSize: 1, refCount: true }), + cipherViews$ = perUserCache$((userId: UserId): Observable => { + return combineLatest([ + this.encryptedCiphersState(userId).state$, + this.localData$(userId), + this.keyService.cipherDecryptionKeys$(userId, true), + ]).pipe( + filter(([ciphers, keys]) => ciphers != null && keys != null), // Skip if ciphers haven't been loaded yor synced yet + switchMap(() => this.getAllDecrypted(userId)), ); - } + }, this.clearCipherViewsForUser$); addEditCipherInfo$(userId: UserId): Observable { return this.addEditCipherInfoState(userId).state$; @@ -149,13 +143,11 @@ export class CipherService implements CipherServiceAbstraction { * * An empty array indicates that all ciphers were successfully decrypted. */ - failedToDecryptCiphers$(userId: UserId): Observable { + failedToDecryptCiphers$ = perUserCache$((userId: UserId): Observable => { return this.failedToDecryptCiphersState(userId).state$.pipe( filter((ciphers) => ciphers != null), - switchMap((ciphers) => merge(this.forceCipherViews$, of(ciphers))), - shareReplay({ bufferSize: 1, refCount: true }), ); - } + }, this.clearCipherViewsForUser$); async setDecryptedCipherCache(value: CipherView[], userId: UserId) { // Sometimes we might prematurely decrypt the vault and that will result in no ciphers @@ -190,10 +182,8 @@ export class CipherService implements CipherServiceAbstraction { userId ??= activeUserId; await this.clearDecryptedCiphersState(userId); - // Force the cipherView$ observable (which always tracks the active user) to re-emit - if (userId == activeUserId) { - this.forceCipherViews$.next(null); - } + // Force the cached cipherView$ observable(s) to emit a null value + this.clearCipherViewsForUser$.next(userId); } async encrypt( @@ -402,10 +392,14 @@ export class CipherService implements CipherServiceAbstraction { return await this.getDecryptedCiphers(userId); } - const [newDecCiphers, failedCiphers] = await this.decryptCiphers( - await this.getAll(userId), - userId, - ); + const decrypted = await this.decryptCiphers(await this.getAll(userId), userId); + + // We failed to decrypt, return empty array but do not cache + if (decrypted == null) { + return []; + } + + const [newDecCiphers, failedCiphers] = decrypted; await this.setDecryptedCipherCache(newDecCiphers, userId); await this.setFailedDecryptedCiphers(failedCiphers, userId); @@ -429,12 +423,12 @@ export class CipherService implements CipherServiceAbstraction { private async decryptCiphers( ciphers: Cipher[], userId: UserId, - ): Promise<[CipherView[], CipherView[]]> { + ): Promise<[CipherView[], CipherView[]] | null> { const keys = await firstValueFrom(this.keyService.cipherDecryptionKeys$(userId, true)); if (keys == null || (keys.userKey == null && Object.keys(keys.orgKeys).length === 0)) { // return early if there are no keys to decrypt with - return [[], []]; + return null; } // Group ciphers by orgId or under 'null' for the user's ciphers diff --git a/libs/common/src/vault/tasks/services/default-task.service.ts b/libs/common/src/vault/tasks/services/default-task.service.ts index 016eed2e7d6..7386102263c 100644 --- a/libs/common/src/vault/tasks/services/default-task.service.ts +++ b/libs/common/src/vault/tasks/services/default-task.service.ts @@ -12,8 +12,11 @@ import { MessageListener } from "@bitwarden/common/platform/messaging"; import { NotificationsService } from "@bitwarden/common/platform/notifications"; import { StateProvider } from "@bitwarden/common/platform/state"; import { SecurityTaskId, UserId } from "@bitwarden/common/types/guid"; +import { + filterOutNullish, + perUserCache$, +} from "@bitwarden/common/vault/utils/observable-utilities"; -import { filterOutNullish, perUserCache$ } from "../../utils/observable-utilities"; import { TaskService } from "../abstractions/task.service"; import { SecurityTaskStatus } from "../enums"; import { SecurityTask, SecurityTaskData, SecurityTaskResponse } from "../models"; diff --git a/libs/common/src/vault/utils/observable-utilities.ts b/libs/common/src/vault/utils/observable-utilities.ts index bb559c600d3..cdec51fc953 100644 --- a/libs/common/src/vault/utils/observable-utilities.ts +++ b/libs/common/src/vault/utils/observable-utilities.ts @@ -1,20 +1,38 @@ -import { filter, Observable, OperatorFunction, shareReplay } from "rxjs"; +import { EMPTY, filter, map, merge, Observable, OperatorFunction, shareReplay } from "rxjs"; import { UserId } from "@bitwarden/common/types/guid"; /** * Builds an observable once per userId and caches it for future requests. * The built observables are shared among subscribers with a replay buffer size of 1. + * + * Optionally, a clearBuffer$ observable can be provided to clear the replay buffer for a specific or all userIds. * @param create - A function that creates an observable for a given userId. + * @param clearBuffer$ - An observable that, when emitted, clears the buffer for the emitted userId. When null is emitted, all caches are cleared. */ export function perUserCache$( create: (userId: UserId) => Observable, -): (userId: UserId) => Observable { - const cache = new Map>(); + clearBuffer$: Observable, +): (userId: UserId) => Observable; +export function perUserCache$( + create: (userId: UserId) => Observable, +): (userId: UserId) => Observable; +export function perUserCache$( + create: (userId: UserId) => Observable, + clearBuffer$: Observable | undefined = undefined, +): (userId: UserId) => Observable { + const cache = new Map>(); return (userId: UserId) => { let observable = cache.get(userId); if (!observable) { - observable = create(userId).pipe(shareReplay({ bufferSize: 1, refCount: false })); + clearBuffer$ ??= EMPTY; + observable = merge( + create(userId), + clearBuffer$.pipe( + filter((clearId) => clearId === userId || clearId === null), + map(() => null), + ), + ).pipe(shareReplay({ bufferSize: 1, refCount: false })); cache.set(userId, observable); } return observable; From b66430b25cb68fe3f8a99b6f1d2631a3807a199e Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Tue, 15 Apr 2025 16:36:05 -0400 Subject: [PATCH 14/14] [PM-19781] Lit Components icons cleanup (#14294) * update icon shapes to match new design system icons * add AngleUpIcon to storybook * rename Family icon to Users to match design system naming conventions * add Collection icon * move illustrations to their own path/category to match design system convention * remove hardcoded PartyHorn illustration size * fix swapped story names * rename PartyHorn illustration to Celebrate to match design system convention * update Warning illustration to use new design system shape --- .../cipher/cipher-indicator-icons.ts | 4 +- .../content/components/icons/angle-down.ts | 4 +- .../content/components/icons/angle-up.ts | 9 +--- .../content/components/icons/business.ts | 19 ++------ .../content/components/icons/close.ts | 4 +- .../content/components/icons/collection.ts | 23 ++++++++++ .../components/icons/exclamation-triangle.ts | 14 +++++- .../content/components/icons/family.ts | 18 -------- .../content/components/icons/folder.ts | 5 ++- .../content/components/icons/globe.ts | 5 +-- .../content/components/icons/index.ts | 6 +-- .../content/components/icons/pencil-square.ts | 8 +++- .../content/components/icons/shield.ts | 4 +- .../autofill/content/components/icons/user.ts | 4 +- .../content/components/icons/users.ts | 18 ++++++++ .../content/components/icons/warning.ts | 23 ---------- .../celebrate.ts} | 12 ++--- .../content/components/illustrations/index.ts | 3 ++ .../{icons => illustrations}/keyhole.ts | 0 .../components/illustrations/warning.ts | 22 ++++++++++ .../lit-stories/.lit-docs/icons.mdx | 10 ++--- ... => cipher-indicator-icons.lit-stories.ts} | 2 +- .../lit-stories/icons/icons.lit-stories.ts | 10 ++--- .../illustrations.lit-stories.ts | 44 +++++++++++++++++++ .../components/notification/button-row.ts | 4 +- .../notification/confirmation/body.ts | 4 +- 26 files changed, 168 insertions(+), 111 deletions(-) create mode 100644 apps/browser/src/autofill/content/components/icons/collection.ts delete mode 100644 apps/browser/src/autofill/content/components/icons/family.ts create mode 100644 apps/browser/src/autofill/content/components/icons/users.ts delete mode 100644 apps/browser/src/autofill/content/components/icons/warning.ts rename apps/browser/src/autofill/content/components/{icons/party-horn.ts => illustrations/celebrate.ts} (98%) create mode 100644 apps/browser/src/autofill/content/components/illustrations/index.ts rename apps/browser/src/autofill/content/components/{icons => illustrations}/keyhole.ts (100%) create mode 100644 apps/browser/src/autofill/content/components/illustrations/warning.ts rename apps/browser/src/autofill/content/components/lit-stories/ciphers/{cipher-indicator-icon.lit-stories.ts => cipher-indicator-icons.lit-stories.ts} (94%) create mode 100644 apps/browser/src/autofill/content/components/lit-stories/illustrations/illustrations.lit-stories.ts diff --git a/apps/browser/src/autofill/content/components/cipher/cipher-indicator-icons.ts b/apps/browser/src/autofill/content/components/cipher/cipher-indicator-icons.ts index 39d4dd28f24..9096149f510 100644 --- a/apps/browser/src/autofill/content/components/cipher/cipher-indicator-icons.ts +++ b/apps/browser/src/autofill/content/components/cipher/cipher-indicator-icons.ts @@ -4,7 +4,7 @@ import { html } from "lit"; import { Theme } from "@bitwarden/common/platform/enums"; import { themes } from "../../../content/components/constants/styles"; -import { Business, Family } from "../../../content/components/icons"; +import { Business, Users } from "../../../content/components/icons"; // @TODO connect data source to icon checks // @TODO support other indicator types (attachments, etc) @@ -19,7 +19,7 @@ export function CipherInfoIndicatorIcons({ }) { const indicatorIcons = [ ...(showBusinessIcon ? [Business({ color: themes[theme].text.muted, theme })] : []), - ...(showFamilyIcon ? [Family({ color: themes[theme].text.muted, theme })] : []), + ...(showFamilyIcon ? [Users({ color: themes[theme].text.muted, theme })] : []), ]; return indicatorIcons.length diff --git a/apps/browser/src/autofill/content/components/icons/angle-down.ts b/apps/browser/src/autofill/content/components/icons/angle-down.ts index db5275aafa9..27cd5ab81c5 100644 --- a/apps/browser/src/autofill/content/components/icons/angle-down.ts +++ b/apps/browser/src/autofill/content/components/icons/angle-down.ts @@ -8,10 +8,10 @@ export function AngleDown({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/angle-up.ts b/apps/browser/src/autofill/content/components/icons/angle-up.ts index 7344123d5ad..f8bda632285 100644 --- a/apps/browser/src/autofill/content/components/icons/angle-up.ts +++ b/apps/browser/src/autofill/content/components/icons/angle-up.ts @@ -8,15 +8,10 @@ export function AngleUp({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/business.ts b/apps/browser/src/autofill/content/components/icons/business.ts index ef8e082c21f..79e64a0a1f9 100644 --- a/apps/browser/src/autofill/content/components/icons/business.ts +++ b/apps/browser/src/autofill/content/components/icons/business.ts @@ -8,30 +8,17 @@ export function Business({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + - - `; } diff --git a/apps/browser/src/autofill/content/components/icons/close.ts b/apps/browser/src/autofill/content/components/icons/close.ts index c9d9286ca3f..27610bc7773 100644 --- a/apps/browser/src/autofill/content/components/icons/close.ts +++ b/apps/browser/src/autofill/content/components/icons/close.ts @@ -8,10 +8,10 @@ export function Close({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/collection.ts b/apps/browser/src/autofill/content/components/icons/collection.ts new file mode 100644 index 00000000000..fb2c58647c5 --- /dev/null +++ b/apps/browser/src/autofill/content/components/icons/collection.ts @@ -0,0 +1,23 @@ +import { css } from "@emotion/css"; +import { html } from "lit"; + +import { IconProps } from "../common-types"; +import { buildIconColorRule, ruleNames, themes } from "../constants/styles"; + +export function Collection({ color, disabled, theme }: IconProps) { + const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; + + return html` + + + + + `; +} diff --git a/apps/browser/src/autofill/content/components/icons/exclamation-triangle.ts b/apps/browser/src/autofill/content/components/icons/exclamation-triangle.ts index d87d5621e30..c4f587b2d7b 100644 --- a/apps/browser/src/autofill/content/components/icons/exclamation-triangle.ts +++ b/apps/browser/src/autofill/content/components/icons/exclamation-triangle.ts @@ -8,10 +8,20 @@ export function ExclamationTriangle({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + + + `; diff --git a/apps/browser/src/autofill/content/components/icons/family.ts b/apps/browser/src/autofill/content/components/icons/family.ts deleted file mode 100644 index 9870c5d37c0..00000000000 --- a/apps/browser/src/autofill/content/components/icons/family.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { css } from "@emotion/css"; -import { html } from "lit"; - -import { IconProps } from "../common-types"; -import { buildIconColorRule, ruleNames, themes } from "../constants/styles"; - -export function Family({ color, disabled, theme }: IconProps) { - const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; - - return html` - - - - `; -} diff --git a/apps/browser/src/autofill/content/components/icons/folder.ts b/apps/browser/src/autofill/content/components/icons/folder.ts index 84577aef820..1b93d2d32ea 100644 --- a/apps/browser/src/autofill/content/components/icons/folder.ts +++ b/apps/browser/src/autofill/content/components/icons/folder.ts @@ -8,10 +8,11 @@ export function Folder({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/globe.ts b/apps/browser/src/autofill/content/components/icons/globe.ts index fc0a975284d..936fd8d2802 100644 --- a/apps/browser/src/autofill/content/components/icons/globe.ts +++ b/apps/browser/src/autofill/content/components/icons/globe.ts @@ -8,11 +8,10 @@ export function Globe({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/index.ts b/apps/browser/src/autofill/content/components/icons/index.ts index 4b6cb7abdd8..de39b70ab24 100644 --- a/apps/browser/src/autofill/content/components/icons/index.ts +++ b/apps/browser/src/autofill/content/components/icons/index.ts @@ -3,14 +3,12 @@ export { AngleUp } from "./angle-up"; export { BrandIconContainer } from "./brand-icon-container"; export { Business } from "./business"; export { Close } from "./close"; +export { Collection } from "./collection"; export { ExclamationTriangle } from "./exclamation-triangle"; export { ExternalLink } from "./external-link"; -export { Family } from "./family"; export { Folder } from "./folder"; export { Globe } from "./globe"; -export { Keyhole } from "./keyhole"; -export { PartyHorn } from "./party-horn"; export { PencilSquare } from "./pencil-square"; export { Shield } from "./shield"; export { User } from "./user"; -export { Warning } from "./warning"; +export { Users } from "./users"; diff --git a/apps/browser/src/autofill/content/components/icons/pencil-square.ts b/apps/browser/src/autofill/content/components/icons/pencil-square.ts index f41ab927809..11366f2631a 100644 --- a/apps/browser/src/autofill/content/components/icons/pencil-square.ts +++ b/apps/browser/src/autofill/content/components/icons/pencil-square.ts @@ -8,10 +8,14 @@ export function PencilSquare({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + + `; diff --git a/apps/browser/src/autofill/content/components/icons/shield.ts b/apps/browser/src/autofill/content/components/icons/shield.ts index 5a2d7d39d58..a027dd3e113 100644 --- a/apps/browser/src/autofill/content/components/icons/shield.ts +++ b/apps/browser/src/autofill/content/components/icons/shield.ts @@ -8,10 +8,10 @@ export function Shield({ color, theme }: IconProps) { const shapeColor = color || themes[theme].brandLogo; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/user.ts b/apps/browser/src/autofill/content/components/icons/user.ts index 32ccd3a2031..b59204a0ad8 100644 --- a/apps/browser/src/autofill/content/components/icons/user.ts +++ b/apps/browser/src/autofill/content/components/icons/user.ts @@ -8,10 +8,10 @@ export function User({ color, disabled, theme }: IconProps) { const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; return html` - + `; diff --git a/apps/browser/src/autofill/content/components/icons/users.ts b/apps/browser/src/autofill/content/components/icons/users.ts new file mode 100644 index 00000000000..eb7840104f0 --- /dev/null +++ b/apps/browser/src/autofill/content/components/icons/users.ts @@ -0,0 +1,18 @@ +import { css } from "@emotion/css"; +import { html } from "lit"; + +import { IconProps } from "../common-types"; +import { buildIconColorRule, ruleNames, themes } from "../constants/styles"; + +export function Users({ color, disabled, theme }: IconProps) { + const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main; + + return html` + + + + `; +} diff --git a/apps/browser/src/autofill/content/components/icons/warning.ts b/apps/browser/src/autofill/content/components/icons/warning.ts deleted file mode 100644 index 9ae9aeca352..00000000000 --- a/apps/browser/src/autofill/content/components/icons/warning.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { html } from "lit"; - -// This icon has static multi-colors for each theme -export function Warning() { - return html` - - - - - - `; -} diff --git a/apps/browser/src/autofill/content/components/icons/party-horn.ts b/apps/browser/src/autofill/content/components/illustrations/celebrate.ts similarity index 98% rename from apps/browser/src/autofill/content/components/icons/party-horn.ts rename to apps/browser/src/autofill/content/components/illustrations/celebrate.ts index 439d60a79de..30b3743004f 100644 --- a/apps/browser/src/autofill/content/components/icons/party-horn.ts +++ b/apps/browser/src/autofill/content/components/illustrations/celebrate.ts @@ -5,16 +5,10 @@ import { ThemeTypes } from "@bitwarden/common/platform/enums"; import { IconProps } from "../common-types"; // This icon has static multi-colors for each theme -export function PartyHorn({ theme }: IconProps) { +export function Celebrate({ theme }: IconProps) { if (theme === ThemeTypes.Dark) { return html` - + + + + + + + `; +} diff --git a/apps/browser/src/autofill/content/components/lit-stories/.lit-docs/icons.mdx b/apps/browser/src/autofill/content/components/lit-stories/.lit-docs/icons.mdx index f85cf3ae90f..571ed10285a 100644 --- a/apps/browser/src/autofill/content/components/lit-stories/.lit-docs/icons.mdx +++ b/apps/browser/src/autofill/content/components/lit-stories/.lit-docs/icons.mdx @@ -2,7 +2,7 @@ import { Meta, Controls } from "@storybook/addon-docs"; import * as stories from "./icons.lit-stories"; - + ## Icon Stories @@ -14,12 +14,12 @@ like size, color, and theme. Each story is an example of how a specific icon can | | | | ------------------------- | ------------------ | -| `AngleDownIcon` | `FolderIcon` | -| `BusinessIcon` | `GlobeIcon` | -| `BrandIcon` | `PartyHornIcon` | +| `AngleDownIcon` | `AngleUpIcon` | +| `BusinessIcon` | `FolderIcon` | +| `BrandIcon` | `GlobeIcon` | | `CloseIcon` | `PencilSquareIcon` | | `ExclamationTriangleIcon` | `ShieldIcon` | -| `FamilyIcon` | `UserIcon` | +| `UsersIcon` | `UserIcon` | ## Props diff --git a/apps/browser/src/autofill/content/components/lit-stories/ciphers/cipher-indicator-icon.lit-stories.ts b/apps/browser/src/autofill/content/components/lit-stories/ciphers/cipher-indicator-icons.lit-stories.ts similarity index 94% rename from apps/browser/src/autofill/content/components/lit-stories/ciphers/cipher-indicator-icon.lit-stories.ts rename to apps/browser/src/autofill/content/components/lit-stories/ciphers/cipher-indicator-icons.lit-stories.ts index 89c3ecbcb1c..08530452730 100644 --- a/apps/browser/src/autofill/content/components/lit-stories/ciphers/cipher-indicator-icon.lit-stories.ts +++ b/apps/browser/src/autofill/content/components/lit-stories/ciphers/cipher-indicator-icons.lit-stories.ts @@ -12,7 +12,7 @@ type Args = { }; export default { - title: "Components/Ciphers/Cipher Indicator Icon", + title: "Components/Ciphers/Cipher Indicator Icons", argTypes: { showBusinessIcon: { control: "boolean" }, showFamilyIcon: { control: "boolean" }, diff --git a/apps/browser/src/autofill/content/components/lit-stories/icons/icons.lit-stories.ts b/apps/browser/src/autofill/content/components/lit-stories/icons/icons.lit-stories.ts index 8bd87ef6674..fc5db1c7c2c 100644 --- a/apps/browser/src/autofill/content/components/lit-stories/icons/icons.lit-stories.ts +++ b/apps/browser/src/autofill/content/components/lit-stories/icons/icons.lit-stories.ts @@ -14,7 +14,7 @@ type Args = { }; export default { - title: "Components/Icons/Icons", + title: "Components/Icons", argTypes: { iconLink: { control: "text" }, color: { control: "color" }, @@ -53,16 +53,16 @@ const createIconStory = (iconName: keyof typeof Icons): StoryObj => { }; export const AngleDownIcon = createIconStory("AngleDown"); -export const BusinessIcon = createIconStory("Business"); +export const AngleUpIcon = createIconStory("AngleUp"); export const BrandIcon = createIconStory("BrandIconContainer"); +export const BusinessIcon = createIconStory("Business"); export const CloseIcon = createIconStory("Close"); +export const CollectionIcon = createIconStory("Collection"); export const ExclamationTriangleIcon = createIconStory("ExclamationTriangle"); export const ExternalLinkIcon = createIconStory("ExternalLink"); -export const FamilyIcon = createIconStory("Family"); export const FolderIcon = createIconStory("Folder"); export const GlobeIcon = createIconStory("Globe"); -export const KeyholeIcon = createIconStory("Keyhole"); -export const PartyHornIcon = createIconStory("PartyHorn"); export const PencilSquareIcon = createIconStory("PencilSquare"); export const ShieldIcon = createIconStory("Shield"); export const UserIcon = createIconStory("User"); +export const UsersIcon = createIconStory("Users"); diff --git a/apps/browser/src/autofill/content/components/lit-stories/illustrations/illustrations.lit-stories.ts b/apps/browser/src/autofill/content/components/lit-stories/illustrations/illustrations.lit-stories.ts new file mode 100644 index 00000000000..86d55f2f795 --- /dev/null +++ b/apps/browser/src/autofill/content/components/lit-stories/illustrations/illustrations.lit-stories.ts @@ -0,0 +1,44 @@ +import { Meta, StoryObj } from "@storybook/web-components"; +import { html } from "lit"; + +import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum"; + +import * as Illustrations from "../../illustrations"; + +type Args = { + theme: Theme; + size: number; +}; + +export default { + title: "Components/Illustrations", + argTypes: { + theme: { control: "select", options: [...Object.values(ThemeTypes)] }, + size: { control: "number", min: 10, max: 100, step: 1 }, + }, + args: { + theme: ThemeTypes.Light, + size: 50, + }, +} as Meta; + +const Template = ( + args: Args, + IllustrationComponent: (props: Args) => ReturnType, +) => html` +
+ ${IllustrationComponent({ ...args })} +
+`; + +const createIllustrationStory = (illustrationName: keyof typeof Illustrations): StoryObj => { + return { + render: (args) => Template(args, Illustrations[illustrationName]), + } as StoryObj; +}; + +export const KeyholeIllustration = createIllustrationStory("Keyhole"); +export const CelebrateIllustration = createIllustrationStory("Celebrate"); +export const WarningIllustration = createIllustrationStory("Warning"); diff --git a/apps/browser/src/autofill/content/components/notification/button-row.ts b/apps/browser/src/autofill/content/components/notification/button-row.ts index 8661f5957e1..6fa32f11aa2 100644 --- a/apps/browser/src/autofill/content/components/notification/button-row.ts +++ b/apps/browser/src/autofill/content/components/notification/button-row.ts @@ -4,14 +4,14 @@ import { ProductTierType } from "@bitwarden/common/billing/enums"; import { Theme } from "@bitwarden/common/platform/enums"; import { Option, OrgView, FolderView } from "../common-types"; -import { Business, Family, Folder, User } from "../icons"; +import { Business, Users, Folder, User } from "../icons"; import { ButtonRow } from "../rows/button-row"; function getVaultIconByProductTier(productTierType?: ProductTierType): Option["icon"] { switch (productTierType) { case ProductTierType.Free: case ProductTierType.Families: - return Family; + return Users; case ProductTierType.Teams: case ProductTierType.Enterprise: case ProductTierType.TeamsStarter: diff --git a/apps/browser/src/autofill/content/components/notification/confirmation/body.ts b/apps/browser/src/autofill/content/components/notification/confirmation/body.ts index 55d257b36f4..d2ac7f36277 100644 --- a/apps/browser/src/autofill/content/components/notification/confirmation/body.ts +++ b/apps/browser/src/autofill/content/components/notification/confirmation/body.ts @@ -4,7 +4,7 @@ import { html, nothing } from "lit"; import { Theme } from "@bitwarden/common/platform/enums"; import { themes } from "../../constants/styles"; -import { PartyHorn, Keyhole, Warning } from "../../icons"; +import { Celebrate, Keyhole, Warning } from "../../illustrations"; import { NotificationConfirmationMessage } from "./message"; @@ -33,7 +33,7 @@ export function NotificationConfirmationBody({ theme, handleOpenVault, }: NotificationConfirmationBodyProps) { - const IconComponent = tasksAreComplete ? Keyhole : !error ? PartyHorn : Warning; + const IconComponent = tasksAreComplete ? Keyhole : !error ? Celebrate : Warning; const showConfirmationMessage = confirmationMessage || buttonText || messageDetails;