diff --git a/.eslintrc.json b/.eslintrc.json index 4fba3dd6128..d6c329a94dc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -34,20 +34,14 @@ } }, "rules": { - "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled - "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], "@typescript-eslint/explicit-member-accessibility": [ "error", - { - "accessibility": "no-public" - } - ], - "@typescript-eslint/no-this-alias": [ - "error", - { - "allowedNames": ["self"] - } + { "accessibility": "no-public" } ], + "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled + "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], + "@typescript-eslint/no-this-alias": ["error", { "allowedNames": ["self"] }], + "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], "no-console": "error", "import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package. "import/order": [ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c5f55674aee..a70774b5e1d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -75,8 +75,8 @@ apps/web/src/translation-constants.ts @bitwarden/team-platform-dev apps/browser/src/autofill @bitwarden/team-autofill-dev ## Component Library ## -.storybook @bitwarden/team-platform-dev -libs/components @bitwarden/team-platform-dev +.storybook @bitwarden/team-component-library +libs/components @bitwarden/team-component-library ## Desktop native module ## apps/desktop/desktop_native @bitwarden/team-platform-dev diff --git a/.storybook/main.ts b/.storybook/main.ts index acc6e2a56db..37339b7343c 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -4,6 +4,7 @@ import remarkGfm from "remark-gfm"; const config: StorybookConfig = { stories: [ + "../libs/auth/src/**/*.stories.@(js|jsx|ts|tsx)", "../libs/components/src/**/*.mdx", "../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)", "../apps/web/src/**/*.mdx", diff --git a/apps/browser/config/base.json b/apps/browser/config/base.json index 81b11cd38b7..348f00d1f36 100644 --- a/apps/browser/config/base.json +++ b/apps/browser/config/base.json @@ -1,6 +1,7 @@ { "dev_flags": {}, "flags": { - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/browser/config/development.json b/apps/browser/config/development.json index 972812a9c59..eafd0ffd878 100644 --- a/apps/browser/config/development.json +++ b/apps/browser/config/development.json @@ -6,6 +6,7 @@ } }, "flags": { - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/browser/config/production.json b/apps/browser/config/production.json index b04d1531a2f..f57c3d9bc38 100644 --- a/apps/browser/config/production.json +++ b/apps/browser/config/production.json @@ -1,3 +1,5 @@ { - "flags": {} + "flags": { + "enableCipherKeyEncryption": false + } } diff --git a/apps/browser/package.json b/apps/browser/package.json index fb7b8ad19bf..4e17fd4288d 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/browser", - "version": "2023.9.1", + "version": "2023.9.2", "scripts": { "build": "webpack", "build:mv3": "cross-env MANIFEST_VERSION=3 webpack", diff --git a/apps/browser/src/_locales/ar/messages.json b/apps/browser/src/_locales/ar/messages.json index be4eaca46f7..ba917a9e681 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json index 774e3fd64cd..b784592a3b0 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Yığcamlaşdırmanı aç/bağla", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json index 2fc14ecb1fc..e941d525936 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json index 0bd4ba3b7f9..08451607d2b 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Превключване на свиването", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Псевдонимен домейн" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Записите с включено изискване за повторно въвеждане на главната парола не могат да бъдат попълвани автоматично при зареждане на страницата. Автоматичното попълване при зареждане на страницата е изключено.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Автоматичното попълване при зареждане на страницата използва настройката си по подразбиране.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Изключете повторното въвеждане на главната парола, за да редактирате това поле", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json index f57c4687ea3..edee2852116 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json index 1c930eeafc7..e984a88b7bc 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json index 41f022a4362..7839cceebcb 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Redueix/Amplia", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json index 27ddddb5124..71446db9f2c 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Přepnout sbalení", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Doména aliasu" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Položky se žádostí o změnu hlavního hesla nemohou být automaticky vyplněny při načítání stránky. Automatické vyplnění při načítání stránky je vypnuto.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automatické vyplnění při načítání stránky bylo nastaveno na výchozí nastavení.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Pro úpravu tohoto pole vypněte požadavek na hlavní heslo", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/cy/messages.json b/apps/browser/src/_locales/cy/messages.json index c7817b42bce..7292370f533 100644 --- a/apps/browser/src/_locales/cy/messages.json +++ b/apps/browser/src/_locales/cy/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json index cce307701b2..1bc0ed79e5a 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Fold sammen/ud", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasdomæne" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Emner, hvor der anmodes om hovedadgangskode igen, kan ikke autoudfyldes ved sideindlæsning. Autoudfyldning ved sideindlæsning er slået fra.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Autoudfyldning ved sideindlæsning sat til standardindstillingen.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Slå anmodning om hovedadgangskode igen fra for at redigere dette felt", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json index 1b3eb19ee8e..443d4294cd3 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Ein-/ausklappen", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias-Domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Einträge, die eine erneuten Abfrage des Master-Passworts verlangen, können nicht beim Laden einer Seite automatisch ausgefüllt werden. Auto-Ausfüllen beim Laden einer Seite deaktiviert.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-Ausfüllen beim Lader einer Seite wurde auf die Standardeinstellung gesetzt.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Deaktiviere die erneute Abfrage des Master-Passworts, um dieses Feld zu bearbeiten", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json index 552f0b14850..c0b349f8aff 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Εναλλαγή σύμπτυξης", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index fe5400c6a90..22330901579 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-fill" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generate password (copied)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "No matching logins" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Unlock your vault" }, @@ -2407,6 +2431,9 @@ "message": "Toggle collapse", "description": "Toggling an expand/collapse state." }, + "aliasDomain": { + "message": "Alias domain" + }, "passwordRepromptDisabledAutofillOnPageLoad": { "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json index 6307472164d..fbe9e4fc31e 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json index 8bdedacc45c..0ae234fbece 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json index 5890a499518..15f8b4fbefa 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -637,7 +637,7 @@ "message": "Unlock your Bitwarden vault to complete the auto-fill request." }, "notificationUnlock": { - "message": "Unlock" + "message": "Desbloquear" }, "enableContextMenuItem": { "message": "Mostrar las opciones de menú contextuales" @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json index c3d12a9b120..b799c3a63a3 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Peida", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domeen" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/eu/messages.json b/apps/browser/src/_locales/eu/messages.json index a57b243a923..6290304cda6 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json index a6c4f2652c0..250ca3631a5 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "باز و بسته کردن", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index 81bf6c64322..3a829d4783d 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Laajenna tai supista", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasverkkotunnus" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Kohteita, joille pääsalasanan uudelleenkysely on käytössä, ei voida täyttää automaattisesti sivujen avautuessa. Automaattinen täyttö sivujen avautuessa poistettiin käytöstä.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automaattinen täyttö sivun avautuessa käyttää oletusasetusta.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Poista pääsalasanan uudelleenkysely käytöstä muokataksesi kenttää", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json index df4726ac9cb..a8673d001ae 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index d4b04dfa24f..ba4d6a6dd86 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -339,7 +339,7 @@ "message": "Autre" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "Configurez une méthode de déverrouillage pour changer le délai d'attente de votre coffre." }, "rateExtension": { "message": "Noter l'extension" @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Domaine de l'alias" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Désactivez la resaisie du mot de passe maître pour éditer ce champ", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/gl/messages.json b/apps/browser/src/_locales/gl/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/gl/messages.json +++ b/apps/browser/src/_locales/gl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json index 48d88f82d40..68f1ebc1218 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json index 2619e217370..2b99c964209 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "डोमेन उपनाम" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json index 9113a3b2687..b88c097804f 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -772,7 +772,7 @@ "message": "Značajka nije dostupna" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Potrebna je migracija ključa za šifriranje. Prijavi se na web trezoru za ažuriranje ključa za šifriranje." }, "premiumMembership": { "message": "Premium članstvo" @@ -1992,7 +1992,7 @@ "message": "Izvoz osobnog trezora" }, "exportingIndividualVaultDescription": { - "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", + "message": "Izvest će se samo stavke osobnog trezora povezanog s $EMAIL$. Stavke organizacijskog trezora neće biti uključene. Izvest će se samo informacija o stavci trezora bez pripadajućih podataka o povijesti lozinki i privitaka.", "placeholders": { "email": { "content": "$1", @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Sažmi/Proširi", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domene" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Stavke za koje je potrebna glavna lozinka neće se auto-ispuniti kod učitavanja stranice. Auto-ispuna pri učitavanju stranice je isključena.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-ispuna kod učitavanja stranice koristi zadane postavke.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Isključi traženje glavne lozinke za promjenu ovog polja", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json index 3b1c44dcfbb..efe6d260355 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Összezárás váltás", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Áldomain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "A mesterjelszót újra bekérő elemeket nem lehet automatikusan kitölteni az oldal betöltésekor. Az automatikus kitöltés az oldal betöltésekor kikapcsolásra kerül.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Az automatikus kitöltés az oldal betöltésekor az alapértelmezett beállítás használatára lett beállítva.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Kapcsoljuk ki a mesterjelszó újbóli bekérését a mező szerkesztéséhez.", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index 3891b1ddc37..f3fdd1a7c27 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json index 9af1f04b8e2..691e2484cba 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Comprimi/espandi", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Dominio alias" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Gli elementi che richiedono di inserire la password principale di nuovo non possono essere riempiti automaticamente al caricamento della pagina.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Il riempimento automatico al caricamento della pagina impostata per usare l'impostazione predefinita.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Disattiva l'inserimento della password principale di nuovo per modificare questo campo", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json index e02207a0051..c3762ae4ef8 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "開く/閉じる", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "エイリアスドメイン" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "マスターパスワードの再入力を促すアイテムは、ページ読み込み時に自動入力できません。ページ読み込み時の自動入力をオフにしました。", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "ページ読み込み時の自動入力はデフォルトの設定を使うよう設定しました。", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "このフィールドを編集するには、マスターパスワードの再入力をオフにしてください", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json index c6503b69df3..50a25ad0dd9 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json index c4f5aee4955..06f9461e5fd 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json index 795b47eca83..5921e579e24 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json index 8daba606fa6..425d0c98233 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json index f094022695c..624904d7213 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Pārslēgt sakļaušanu", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aizstājdomēns" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Vienumus ar galvenās paroles pārvaicāšanu nevar automātiski aizpildīt lapas ielādes brīdī. Automātiskā aizpilde lapas ielādes brīdī ir izslēgta.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automātiskā aizpilde lapas ielādes brīdī iestatīta izmantot noklusējuma iestatījumu.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Jāizslēdz galvenās paroles pārvaicāšana, lai labotu šo lauku", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json index 94e71f2d8f1..58d5b04fc8b 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/mr/messages.json b/apps/browser/src/_locales/mr/messages.json index 00a2e755376..8f8f58775f7 100644 --- a/apps/browser/src/_locales/mr/messages.json +++ b/apps/browser/src/_locales/mr/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/my/messages.json b/apps/browser/src/_locales/my/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/my/messages.json +++ b/apps/browser/src/_locales/my/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json index a69e43ddbd6..4dadbbc8a7b 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ne/messages.json b/apps/browser/src/_locales/ne/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/ne/messages.json +++ b/apps/browser/src/_locales/ne/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index d6dda3290e7..5915dad872a 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "In-/Uitklappen", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasdomein" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/or/messages.json b/apps/browser/src/_locales/or/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/or/messages.json +++ b/apps/browser/src/_locales/or/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json index 296c76ddbd1..2f28c87d801 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Zwiń/rozwiń", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Domena aliasu" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Elementy z pytaniem o hasło głównege nie mogą być automatycznie wypełniane przy wczytywaniu strony. Automatyczne wypełnianie po wczytywania strony zostało wyłączone.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automatyczne wypełnianie przy wczytywaniu strony zostało ustawione, aby używać ustawień domyślnych.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Wyłącz prośbę o podanie hasła głównego, aby edytować to pole", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json index 89ba426c960..ed62f893a19 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json index 496350bb995..735edf60afe 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -781,7 +781,7 @@ "message": "Gerir subscrição" }, "premiumManageAlert": { - "message": "Pode gerir a sua subscrição no cofre Web bitwarden.com. Pretende visitar o site agora?" + "message": "Pode gerir a sua subscrição no cofre web em bitwarden.com. Pretende visitar o site agora?" }, "premiumRefresh": { "message": "Atualizar subscrição" @@ -814,7 +814,7 @@ "message": "Adquirir Premium" }, "premiumPurchaseAlert": { - "message": "Pode adquirir uma subscrição Premium no cofre Web bitwarden.com. Pretende visitar o site agora?" + "message": "Pode adquirir uma subscrição Premium no cofre web em bitwarden.com. Pretende visitar o site agora?" }, "premiumCurrentMember": { "message": "É um membro Premium!" @@ -930,7 +930,7 @@ "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "duoOrganizationDesc": { - "message": "Verifique com a Duo Security para a sua organização utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "message": "Proteja a sua organização com a Duo Security utilizando a aplicação Duo Mobile, SMS, chamada telefónica ou uma chave de segurança U2F.", "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "webAuthnTitle": { @@ -1279,7 +1279,7 @@ "message": "Esta palavra-passe não foi encontrada em nenhuma violação de dados conhecida. A sua utilização deve ser segura." }, "baseDomain": { - "message": "Domínio base", + "message": "Domínio de base", "description": "Domain name. Ex. website.com" }, "domainName": { @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Alternar colapso", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias de domínio" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Os itens que voltem a pedir a palavra-passe mestra não podem ser preenchidos automaticamente no carregamento da página. Preenchimento automático no carregamento da página desativado.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Preenchimento automático no carregamento da página definido para utilizar a predefinição.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Desativar o pedido para reintroduzir a palavra-passe mestra para editar este campo", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json index cf8acef767b..f525f87b6c2 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -199,7 +199,7 @@ "message": "Centrul de Ajutor Bitwarden" }, "communityForums": { - "message": "Explorează forumurile comunității Bitwarden" + "message": "Explorați forumurile comunității Bitwarden" }, "contactSupport": { "message": "Contactați asistența Bitwarden" @@ -339,7 +339,7 @@ "message": "Altele" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "Configurați metoda de deblocare care să schimbe acțiunea de expirare a seifului." }, "rateExtension": { "message": "Evaluare extensie" @@ -634,7 +634,7 @@ "message": "Actualizare" }, "notificationUnlockDesc": { - "message": "Deblochează seiful Bitwarden pentru a finaliza solicitarea de completare automată." + "message": "Deblocați seiful Bitwarden pentru a finaliza solicitarea de auto-completare." }, "notificationUnlock": { "message": "Deblocare" @@ -772,7 +772,7 @@ "message": "Funcție indisponibilă" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Este necesară migrarea cheilor de criptare. Autentificați-vă prin intermediul seifului web pentru a vă actualiza cheia de criptare." }, "premiumMembership": { "message": "Abonament Premium" @@ -796,7 +796,7 @@ "message": "1 GB spațiu de stocare criptat pentru atașamente de fișiere." }, "premiumSignUpTwoStepOptions": { - "message": "Proprietary two-step login options such as YubiKey and Duo." + "message": "Opțiuni brevetate de conectare cu doi factori, cum ar fi YubiKey și Duo." }, "ppremiumSignUpReports": { "message": "Rapoarte privind igiena parolelor, sănătatea contului și breșele de date pentru a vă păstra seiful în siguranță." @@ -985,10 +985,10 @@ "message": "Dacă se detectează un formular de autentificare, completați-l automat la încărcarea paginii web." }, "experimentalFeature": { - "message": "Site-urile web compromise sau nesigure pot exploata funcția de autocompletare la încărcarea paginii." + "message": "Site-urile web compromise sau nesigure pot profita de auto-completarea la încărcare." }, "learnMoreAboutAutofill": { - "message": "Learn more about auto-fill" + "message": "Mai multe informații despre auto-completare" }, "defaultAutoFillOnPageLoad": { "message": "Setarea implicită de completare automată pentru articole de conectare" @@ -1468,16 +1468,16 @@ "message": "Articolul s-a completat automat " }, "insecurePageWarning": { - "message": "Avertisment: Aceasta este o pagină HTTP nesecurizată și orice informație pe care o trimiteți poate fi văzută și modificată de alte persoane. Această Parolă a fost salvată inițial pe o pagină securizată (HTTPS)." + "message": "Avertisment: Acesta este un site HTTP nesecurizat. Orice informație transmisă poate fi vizualizată și modificată de alte persoane. Această autentificare a fost salvată inițial pe un site securizat (HTTPS)." }, "insecurePageWarningFillPrompt": { - "message": "Do you still wish to fill this login?" + "message": "Încă mai doriți să completați acest login?" }, "autofillIframeWarning": { - "message": "The form is hosted by a different domain than the URI of your saved login. Choose OK to auto-fill anyway, or Cancel to stop." + "message": "Formularul este găzduit pe un alt domeniu decât adresa URI de autentificare salvată. Alegeți OK pentru completarea automată oricum sau Anulare pentru a opri." }, "autofillIframeWarningTip": { - "message": "To prevent this warning in the future, save this URI, $HOSTNAME$, to your Bitwarden login item for this site.", + "message": "Pe viitor, pentru a evita acest avertisment, înregistrați acest URI, $HOSTNAME$, în login-ul Bitwarden pentru acest site.", "placeholders": { "hostname": { "content": "$1", @@ -1489,13 +1489,13 @@ "message": "Setare parolă principală" }, "currentMasterPass": { - "message": "Current master password" + "message": "Parola principală actuală" }, "newMasterPass": { - "message": "New master password" + "message": "Noua parolă principală" }, "confirmNewMasterPass": { - "message": "Confirm new master password" + "message": "Confirmați noua parolă principală" }, "masterPasswordPolicyInEffect": { "message": "Una sau mai multe politici ale organizației necesită ca parola principală să îndeplinească următoarele cerințe:" @@ -1606,10 +1606,10 @@ "message": "Biometria browserului nu este acceptată pe acest dispozitiv." }, "biometricsFailedTitle": { - "message": "Biometrics failed" + "message": "Biometrica a eșuat" }, "biometricsFailedDesc": { - "message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support." + "message": "Verificarea biometrică nu poate fi finalizată. Încercați parola principală sau deconectați-vă. Dacă problema persistă, vă rugăm să contactați serviciul de asistență Bitwarden." }, "nativeMessaginPermissionErrorTitle": { "message": "Permisiunea nu a fost furnizată" @@ -1884,7 +1884,7 @@ "message": "Parola principală a fost schimbată recent de către un administrator din organizație. Pentru a accesa seiful, trebuie să o actualizați acum. Continuarea vă va deconecta de la sesiunea curentă, cerându-vă să vă conectați din nou. Sesiunile active de pe alte dispozitive pot continua să rămână active timp de până la o oră." }, "updateWeakMasterPasswordWarning": { - "message": "Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + "message": "Parola dvs. principală nu respectă una sau mai multe politici ale organizației. Pentru a accesa seiful, parola principală trebuie actualizată acum. În cazul în care continuați, veți fi deconectat din sesiunea curentă și va trebui să vă conectați din nou. Sesiunile active de pe alte dispozitive pot rămâne active timp de până la o oră." }, "resetPasswordPolicyAutoEnroll": { "message": "Înscrierea automată" @@ -1905,7 +1905,7 @@ "message": "Minute" }, "vaultTimeoutPolicyInEffect": { - "message": "Politicile organizației dvs vă afectează expirarea seifului. Timpul maxim permis de expirare a seifului este $HOURS$ oră (ore) și $MINUTES$ minut(e)", + "message": "Politicile organizației dvs. au stabilit timpul maxim de expirare permis pentru seif la $HOURS$ oră/ore și $MINUTES$ de minut(e).", "placeholders": { "hours": { "content": "$1", @@ -1918,7 +1918,7 @@ } }, "vaultTimeoutPolicyWithActionInEffect": { - "message": "Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is $HOURS$ hour(s) and $MINUTES$ minute(s). Your vault timeout action is set to $ACTION$.", + "message": "Politicile organizației dvs. afectează timpul de expirare al seifului. Timpul maxim de așteptare permis pentru seif este de $HOURS$ oră(e) și $MINUTES$ minut(e). Acțiunea de temporizare a seifului este setată la $ACTION$.", "placeholders": { "hours": { "content": "$1", @@ -1935,7 +1935,7 @@ } }, "vaultTimeoutActionPolicyInEffect": { - "message": "Your organization policies have set your vault timeout action to $ACTION$.", + "message": "Politicile organizației dvs. au setat acțiunea de expirare a seifului la $ACTION$.", "placeholders": { "action": { "content": "$1", @@ -1992,7 +1992,7 @@ "message": "Exportul seifului individual" }, "exportingIndividualVaultDescription": { - "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", + "message": "Se exportă numai intrările din seiful personal asociate cu $EMAIL$. Nu sunt incluse intrările de seif ale organizației. Se exportă numai informațiile despre intrările din seif. Acestea nu includ atașamentele asociate.", "placeholders": { "email": { "content": "$1", @@ -2093,7 +2093,7 @@ "message": "Versiune server" }, "selfHostedServer": { - "message": "self-hosted" + "message": "auto-găzduit" }, "thirdParty": { "message": "Parte terță" @@ -2132,52 +2132,52 @@ "message": "Memorare e-mail" }, "loginWithDevice": { - "message": "Log in with device" + "message": "Conectați-vă cu dispozitivul" }, "loginWithDeviceEnabledInfo": { - "message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?" + "message": "Conectarea cu dispozitivul trebuie să fie configurată în setările aplicației Bitwarden. Aveți nevoie de o altă opțiune?" }, "fingerprintPhraseHeader": { - "message": "Fingerprint phrase" + "message": "Fraza amprentă" }, "fingerprintMatchInfo": { - "message": "Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device." + "message": "Asigurați-vă că seiful este deblocat și că fraza amprentă se potrivește cu cea de pe celălalt dispozitiv." }, "resendNotification": { - "message": "Resend notification" + "message": "Reîntoarceți notificarea" }, "viewAllLoginOptions": { - "message": "View all log in options" + "message": "Afișați toate opțiunile de conectare" }, "notificationSentDevice": { - "message": "A notification has been sent to your device." + "message": "O notificare a fost trimisă pe dispozitivul dvs." }, "loginInitiated": { - "message": "Login initiated" + "message": "Conectare inițiată" }, "exposedMasterPassword": { - "message": "Exposed Master Password" + "message": "Parolă principală compromisă" }, "exposedMasterPasswordDesc": { - "message": "Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?" + "message": "Parola găsită în scurgerea de date. Folosiți o parolă unică pentru a vă proteja contul. Sunteți sigur că doriți să folosiți o parolă compromisă?" }, "weakAndExposedMasterPassword": { - "message": "Weak and Exposed Master Password" + "message": "Parolă principală slabă și compromisă" }, "weakAndBreachedMasterPasswordDesc": { - "message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?" + "message": "Parolă slabă identificată și găsită într-o scurgere de date. Folosiți o parolă puternică și unică pentru a vă proteja contul. Sunteți sigur că doriți să utilizați această parolă?" }, "checkForBreaches": { - "message": "Check known data breaches for this password" + "message": "Verificați scurgerile de date cunoscute pentru această parolă" }, "important": { "message": "Important:" }, "masterPasswordHint": { - "message": "Your master password cannot be recovered if you forget it!" + "message": "Parola principală nu poate fi recuperată dacă este uitată!" }, "characterMinimum": { - "message": "$LENGTH$ character minimum", + "message": "Minim $LENGTH$ caractere", "placeholders": { "length": { "content": "$1", @@ -2186,13 +2186,13 @@ } }, "autofillPageLoadPolicyActivated": { - "message": "Your organization policies have turned on auto-fill on page load." + "message": "Politicile organizației dvs. au activat auto-completarea la încărcarea paginii." }, "howToAutofill": { - "message": "How to auto-fill" + "message": "Instrucțiuni de auto-completare" }, "autofillSelectInfoWithCommand": { - "message": "Select an item from this page or use the shortcut: $COMMAND$", + "message": "Selectați un element din această pagină sau utilizați comanda rapidă: $COMMAND$", "placeholders": { "command": { "content": "$1", @@ -2201,22 +2201,22 @@ } }, "autofillSelectInfoWithoutCommand": { - "message": "Select an item from this page or set a shortcut in settings." + "message": "Selectați un element din această pagină sau setați o comandă rapidă în setări." }, "gotIt": { - "message": "Got it" + "message": "Am înțeles" }, "autofillSettings": { - "message": "Auto-fill settings" + "message": "Setări de auto-completare" }, "autofillShortcut": { - "message": "Auto-fill keyboard shortcut" + "message": "Scurtătură de tastatură pentru auto-completare" }, "autofillShortcutNotSet": { - "message": "The auto-fill shortcut is not set. Change this in the browser's settings." + "message": "Scurtătura de auto-completare nu este setată. Modificați acest lucru în setările browserului." }, "autofillShortcutText": { - "message": "The auto-fill shortcut is: $COMMAND$. Change this in the browser's settings.", + "message": "Scurtătura de auto-completare este: $COMMAND$. Modificați acest lucru în setările browserului.", "placeholders": { "command": { "content": "$1", @@ -2225,7 +2225,7 @@ } }, "autofillShortcutTextSafari": { - "message": "Default auto-fill shortcut: $COMMAND$.", + "message": "Scurtătură implicită de auto-completare: $COMMAND$.", "placeholders": { "command": { "content": "$1", @@ -2234,31 +2234,31 @@ } }, "loggingInOn": { - "message": "Logging in on" + "message": "Conectare la" }, "opensInANewWindow": { - "message": "Opens in a new window" + "message": "Se deschide într-o nouă fereastră" }, "deviceApprovalRequired": { - "message": "Device approval required. Select an approval option below:" + "message": "Este necesară aprobarea dispozitivului. Selectați o opțiune de autorizare de mai jos:" }, "rememberThisDevice": { - "message": "Remember this device" + "message": "Memorizează acest dispozitiv" }, "uncheckIfPublicDevice": { - "message": "Uncheck if using a public device" + "message": "Debifați dacă utilizați un dispozitiv public" }, "approveFromYourOtherDevice": { - "message": "Approve from your other device" + "message": "Aprobați de pe celălalt dispozitiv" }, "requestAdminApproval": { - "message": "Request admin approval" + "message": "Cereți aprobarea administratorului" }, "approveWithMasterPassword": { - "message": "Approve with master password" + "message": "Aprobați cu parola principală" }, "ssoIdentifierRequired": { - "message": "Organization SSO identifier is required." + "message": "Identificatorul SSO al organizației este necesar." }, "eu": { "message": "EU", @@ -2271,49 +2271,49 @@ "message": "bitwarden.eu" }, "accessDenied": { - "message": "Access denied. You do not have permission to view this page." + "message": "Acces refuzat. Nu aveți permisiunea de a vizualiza această pagină." }, "general": { "message": "General" }, "display": { - "message": "Display" + "message": "Afișare" }, "accountSuccessfullyCreated": { - "message": "Account successfully created!" + "message": "Cont creat cu succes!" }, "adminApprovalRequested": { - "message": "Admin approval requested" + "message": "Autorizație administrativă solicitată" }, "adminApprovalRequestSentToAdmins": { - "message": "Your request has been sent to your admin." + "message": "Cererea dvs. a fost trimisă administratorului." }, "youWillBeNotifiedOnceApproved": { - "message": "You will be notified once approved." + "message": "Veți primi o notificare după aprobare." }, "troubleLoggingIn": { - "message": "Trouble logging in?" + "message": "Aveți probleme la logare?" }, "loginApproved": { - "message": "Login approved" + "message": "Autentificare aprobată" }, "userEmailMissing": { - "message": "User email missing" + "message": "Lipsește e-mailul utilizatorului" }, "deviceTrusted": { - "message": "Device trusted" + "message": "Dispozitiv de încredere" }, "inputRequired": { - "message": "Input is required." + "message": "Este necesară o intrare." }, "required": { - "message": "required" + "message": "necesar" }, "search": { - "message": "Search" + "message": "Căutare" }, "inputMinLength": { - "message": "Input must be at least $COUNT$ characters long.", + "message": "Intrarea trebuie să aibă o lungime de cel puțin $COUNT$ caractere.", "placeholders": { "count": { "content": "$1", @@ -2322,7 +2322,7 @@ } }, "inputMaxLength": { - "message": "Input must not exceed $COUNT$ characters in length.", + "message": "Intrarea nu trebuie să fie mai lungă de $COUNT$ caractere.", "placeholders": { "count": { "content": "$1", @@ -2331,7 +2331,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Următoarele caractere nu sunt permise: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2340,7 +2340,7 @@ } }, "inputMinValue": { - "message": "Input value must be at least $MIN$.", + "message": "Valoarea de intrare trebuie să fie cel puțin $MIN$.", "placeholders": { "min": { "content": "$1", @@ -2349,7 +2349,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "Valoarea de intrare nu trebuie să depășească $MAX$.", "placeholders": { "max": { "content": "$1", @@ -2358,17 +2358,17 @@ } }, "multipleInputEmails": { - "message": "1 or more emails are invalid" + "message": "1 sau mai multe e-mailuri sunt invalide" }, "inputTrimValidator": { - "message": "Input must not contain only whitespace.", + "message": "Datele introduse nu trebuie să conțină numai spații.", "description": "Notification to inform the user that a form's input can't contain only whitespace." }, "inputEmail": { - "message": "Input is not an email address." + "message": "Intrarea nu este o adresă de e-mail." }, "fieldsNeedAttention": { - "message": "$COUNT$ field(s) above need your attention.", + "message": "$COUNT$ câmp(uri) de mai sus necesită atenție.", "placeholders": { "count": { "content": "$1", @@ -2377,22 +2377,22 @@ } }, "selectPlaceholder": { - "message": "-- Select --" + "message": "-- Selectați --" }, "multiSelectPlaceholder": { - "message": "-- Type to filter --" + "message": "-- Scrieți pentru a filtra --" }, "multiSelectLoading": { - "message": "Retrieving options..." + "message": "Recuperarea opțiunilor..." }, "multiSelectNotFound": { - "message": "No items found" + "message": "Niciun element găsit" }, "multiSelectClearAll": { - "message": "Clear all" + "message": "Ștergeți tot" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+ $QUANTITY$ mai mult", "placeholders": { "quantity": { "content": "$1", @@ -2401,10 +2401,25 @@ } }, "submenu": { - "message": "Submenu" + "message": "Submeniu" }, "toggleCollapse": { - "message": "Toggle collapse", + "message": "Comutare restrângere", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Elementele în care parola principală este solicitată din nou nu pot fi completate automat la încărcarea paginii. Completarea automată la încărcarea paginii este dezactivată.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Completarea automată la încărcarea paginii este setată la valoarea implicită.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Dezactivați reintroducerea parolei principale pentru a edita acest câmp", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json index 5dfbe64abc8..40452e56dce 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Свернуть/развернуть", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Псевдоним домена" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Элементы с повторным запросом мастер-пароля не могут быть автоматически заполнены при загрузке страницы. Автозаполнение при загрузке страницы выключено.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Автозаполнение при загрузке страницы использует настройку по умолчанию.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Для редактирования этого поля отключите повторный запрос мастер-пароля", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json index 2c9a44b2afe..04f2a619a82 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json index 405402ccac7..684c677c45b 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Prepnúť zbalenie", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias doména" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Položky, ktoré vyžadujú opätovné zadanie hlavného hesla sa nedajú automaticky vyplniť pri načítaní stránky. Automatické vypĺňanie pri načítaní stránky je vypnuté.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automatické vypĺňanie pri načítaní stránky nastavené na pôvodnú predvoľbu.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Vypnite výzvu na opätovné zadanie hlavného hesla na úpravu tohto poľa", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json index ee581226b0c..8878c308045 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json index a75cd39ebca..46e96c7d8df 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -772,7 +772,7 @@ "message": "Функција је недоступна" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Потребна је миграција кључа за шифровање. Пријавите се преко веб сефа да бисте ажурирали кључ за шифровање." }, "premiumMembership": { "message": "Премијум чланство" @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Промени проширење", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Ставке са упитом за поновно постављање главне лозинке не могу се ауто-попунити при учитавању странице. Ауто-попуњавање при учитавању странице је искључено.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Ауто-попуњавање при учитавању странице је подешено да користи подразумевано подешавање.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Искључите поновни упит главне лозинке да бисте уредили ово поље", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index 7a4816dfa96..680a3aac0bd 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasdomän" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/te/messages.json b/apps/browser/src/_locales/te/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/te/messages.json +++ b/apps/browser/src/_locales/te/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json index 20e234e4f8f..0db240ea797 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json index f40c94f1222..e52a2f59f26 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -339,7 +339,7 @@ "message": "Diğer" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "Kasa zaman aşımı eyleminizi değiştirmek için kilit açma yönteminizi ayarlayın." }, "rateExtension": { "message": "Uzantıyı değerlendirin" @@ -2277,7 +2277,7 @@ "message": "Genel" }, "display": { - "message": "Display" + "message": "Görünüm" }, "accountSuccessfullyCreated": { "message": "Hesap başarıyla oluşturuldu!" @@ -2304,16 +2304,16 @@ "message": "Cihaza güvenildi" }, "inputRequired": { - "message": "Input is required." + "message": "Girdi gerekli." }, "required": { - "message": "required" + "message": "gerekli" }, "search": { "message": "Ara" }, "inputMinLength": { - "message": "Input must be at least $COUNT$ characters long.", + "message": "Girdi en az $COUNT$ karakter uzunluğunda olmalıdır.", "placeholders": { "count": { "content": "$1", @@ -2322,7 +2322,7 @@ } }, "inputMaxLength": { - "message": "Input must not exceed $COUNT$ characters in length.", + "message": "Girdi $COUNT$ karakter uzunluğunu geçmemelidir.", "placeholders": { "count": { "content": "$1", @@ -2331,7 +2331,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Şu karakterlere izin verilmez: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2349,7 +2349,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "Girdi değeri en fazla $MAX$ olmalı.", "placeholders": { "max": { "content": "$1", @@ -2358,17 +2358,17 @@ } }, "multipleInputEmails": { - "message": "1 or more emails are invalid" + "message": "Bir veya daha fazla e-posta geçersiz" }, "inputTrimValidator": { - "message": "Input must not contain only whitespace.", + "message": "Girdi yalnızca boşluktan ibaret olamaz.", "description": "Notification to inform the user that a form's input can't contain only whitespace." }, "inputEmail": { - "message": "Input is not an email address." + "message": "Girdi bir e-posta adresi değil." }, "fieldsNeedAttention": { - "message": "$COUNT$ field(s) above need your attention.", + "message": "Yukarıdaki $COUNT$ alanla ilgilenmeniz gerekiyor.", "placeholders": { "count": { "content": "$1", @@ -2377,13 +2377,13 @@ } }, "selectPlaceholder": { - "message": "-- Select --" + "message": "-- Seçin --" }, "multiSelectPlaceholder": { - "message": "-- Type to filter --" + "message": "-- Filtrelemek için yazın --" }, "multiSelectLoading": { - "message": "Retrieving options..." + "message": "Seçenekler alınıyor..." }, "multiSelectNotFound": { "message": "Hiç kayıt bulunamadı" @@ -2392,7 +2392,7 @@ "message": "Tümünü temizle" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+ $QUANTITY$ tane daha", "placeholders": { "quantity": { "content": "$1", @@ -2401,10 +2401,25 @@ } }, "submenu": { - "message": "Submenu" + "message": "Alt menü" }, "toggleCollapse": { - "message": "Toggle collapse", + "message": "Daraltmayı aç/kapat", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias alan adı" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Ana parolayı yeniden isteyen kayıtlar sayfa yüklendiğinde otomatik olarak doldurulamaz. Sayfa yüklendiğinde otomatik doldurma kapatıldı.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Sayfa yüklendiğinde otomatik doldurma, varsayılan ayarı kullanacak şekilde ayarlandı.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Bu alanı düzenlemek için ana parolayı yeniden istemeyi kapatın", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json index 88a9dd902d2..6cb70bd76bd 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Згорнути/розгорнути", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 7f256311f16..e562a0b5d5d 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index 04c9d9484c6..b1d0aac7e4a 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "切换折叠", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "别名域" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "具有主密码重新提示的项目无法在页面加载时自动填充。页面加载时的自动填充功能已关闭。", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "页面加载时自动填充设置为默认设置。", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "关闭主密码重新提示以编辑此字段", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json index 3612d93edb3..58ca526bc68 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "使用主密碼重新提示的項目無法在頁面加載時自動填寫。已關閉頁面加載時的自動填入。", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "將頁面加載時的自動填入設置為使用默認設定。", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "關閉主密碼重新提示以編輯此欄位", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/autofill/background/notification.background.ts b/apps/browser/src/autofill/background/notification.background.ts index 1cb006fa3a2..73bdc2cd16f 100644 --- a/apps/browser/src/autofill/background/notification.background.ts +++ b/apps/browser/src/autofill/background/notification.background.ts @@ -464,7 +464,7 @@ export default class NotificationBackground { private async getDecryptedCipherById(cipherId: string) { const cipher = await this.cipherService.get(cipherId); if (cipher != null && cipher.type === CipherType.Login) { - return await cipher.decrypt(); + return await cipher.decrypt(await this.cipherService.getKeyForCipherKeyDecryption(cipher)); } return null; } diff --git a/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts b/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts index d7cac8d44b2..4532718809e 100644 --- a/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts +++ b/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts @@ -69,19 +69,20 @@ describe("CipherContextMenuHandler", () => { expect(mainContextMenuHandler.noLogins).toHaveBeenCalledTimes(1); }); - it("only adds login ciphers including ciphers that require reprompt", async () => { + it("only adds autofill ciphers including ciphers that require reprompt", async () => { authService.getAuthStatus.mockResolvedValue(AuthenticationStatus.Unlocked); mainContextMenuHandler.init.mockResolvedValue(true); - const realCipher = { + const loginCipher = { id: "5", type: CipherType.Login, reprompt: CipherRepromptType.None, name: "Test Cipher", login: { username: "Test Username" }, }; - const repromptCipher = { + + const repromptLoginCipher = { id: "6", type: CipherType.Login, reprompt: CipherRepromptType.Password, @@ -89,34 +90,49 @@ describe("CipherContextMenuHandler", () => { login: { username: "Test Username" }, }; + const cardCipher = { + id: "7", + type: CipherType.Card, + name: "Test Card Cipher", + card: { username: "Test Username" }, + }; + cipherService.getAllDecryptedForUrl.mockResolvedValue([ null, // invalid cipher undefined, // invalid cipher - { type: CipherType.Card }, // invalid cipher - realCipher, // valid cipher - repromptCipher, + { type: CipherType.SecureNote }, // invalid cipher + loginCipher, // valid cipher + repromptLoginCipher, + cardCipher, // valid cipher ] as any[]); await sut.update("https://test.com"); expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1); - expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com"); + expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com", [ + CipherType.Card, + CipherType.Identity, + ]); - expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(2); + expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(3); expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith( "Test Cipher (Test Username)", "5", - "https://test.com", - realCipher + loginCipher ); expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith( "Test Reprompt Cipher (Test Username)", "6", - "https://test.com", - repromptCipher + repromptLoginCipher + ); + + expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith( + "Test Card Cipher", + "7", + cardCipher ); }); }); diff --git a/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts b/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts index 6140db260f5..f46442c4192 100644 --- a/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts +++ b/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts @@ -18,6 +18,7 @@ import { cipherServiceFactory, CipherServiceInitOptions, } from "../../vault/background/service_factories/cipher-service.factory"; +import { AutofillCipherTypeId } from "../types"; import { MainContextMenuHandler } from "./main-context-menu-handler"; @@ -159,29 +160,67 @@ export class CipherContextMenuHandler { return; } - const ciphers = await this.cipherService.getAllDecryptedForUrl(url); + const ciphers = await this.cipherService.getAllDecryptedForUrl(url, [ + CipherType.Card, + CipherType.Identity, + ]); ciphers.sort((a, b) => this.cipherService.sortCiphersByLastUsedThenName(a, b)); - if (ciphers.length === 0) { - await this.mainContextMenuHandler.noLogins(url); - return; + const groupedCiphers: Record = ciphers.reduce( + (ciphersByType, cipher) => { + if (!cipher?.type) { + return ciphersByType; + } + + const existingCiphersOfType = ciphersByType[cipher.type as AutofillCipherTypeId] || []; + + return { + ...ciphersByType, + [cipher.type]: [...existingCiphersOfType, cipher], + }; + }, + { + [CipherType.Login]: [], + [CipherType.Card]: [], + [CipherType.Identity]: [], + } + ); + + if (groupedCiphers[CipherType.Login].length === 0) { + await this.mainContextMenuHandler.noLogins(); + } + + if (groupedCiphers[CipherType.Identity].length === 0) { + await this.mainContextMenuHandler.noIdentities(); + } + + if (groupedCiphers[CipherType.Card].length === 0) { + await this.mainContextMenuHandler.noCards(); } for (const cipher of ciphers) { - await this.updateForCipher(url, cipher); + await this.updateForCipher(cipher); } } - private async updateForCipher(url: string, cipher: CipherView) { - if (cipher == null || cipher.type !== CipherType.Login) { + private async updateForCipher(cipher: CipherView) { + if ( + cipher == null || + !new Set([CipherType.Login, CipherType.Card, CipherType.Identity]).has(cipher.type) + ) { return; } let title = cipher.name; - if (!Utils.isNullOrEmpty(title)) { + + if (cipher.type === CipherType.Login && !Utils.isNullOrEmpty(title) && cipher.login?.username) { title += ` (${cipher.login.username})`; } - await this.mainContextMenuHandler.loadOptions(title, cipher.id, url, cipher); + if (cipher.type === CipherType.Card && cipher.card?.subTitle) { + title += ` ${cipher.card.subTitle}`; + } + + await this.mainContextMenuHandler.loadOptions(title, cipher.id, cipher); } } diff --git a/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts b/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts index 021d15df89e..665c4e9acb8 100644 --- a/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts +++ b/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts @@ -10,6 +10,15 @@ import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { + AUTOFILL_ID, + COPY_PASSWORD_ID, + COPY_USERNAME_ID, + COPY_VERIFICATIONCODE_ID, + GENERATE_PASSWORD_ID, + NOOP_COMMAND_SUFFIX, +} from "../constants"; + import { CopyToClipboardAction, ContextMenuClickedHandler, @@ -17,13 +26,6 @@ import { GeneratePasswordToClipboardAction, AutofillAction, } from "./context-menu-clicked-handler"; -import { - AUTOFILL_ID, - COPY_PASSWORD_ID, - COPY_USERNAME_ID, - COPY_VERIFICATIONCODE_ID, - GENERATE_PASSWORD_ID, -} from "./main-context-menu-handler"; describe("ContextMenuClickedHandler", () => { const createData = ( @@ -51,6 +53,7 @@ describe("ContextMenuClickedHandler", () => { type: CipherType.Login, } as any) ); + cipherView.login.username = username ?? "USERNAME"; cipherView.login.password = password ?? "PASSWORD"; cipherView.login.totp = totp ?? "TOTP"; @@ -106,7 +109,7 @@ describe("ContextMenuClickedHandler", () => { const cipher = createCipher(); cipherService.getAllDecrypted.mockResolvedValue([cipher]); - await sut.run(createData("T_1", AUTOFILL_ID), { id: 5 } as any); + await sut.run(createData(`${AUTOFILL_ID}_1`, AUTOFILL_ID), { id: 5 } as any); expect(autofill).toBeCalledTimes(1); @@ -118,11 +121,16 @@ describe("ContextMenuClickedHandler", () => { createCipher({ username: "TEST_USERNAME" }), ]); - await sut.run(createData("T_1", COPY_USERNAME_ID)); + await sut.run(createData(`${COPY_USERNAME_ID}_1`, COPY_USERNAME_ID), { + url: "https://test.com", + } as any); expect(copyToClipboard).toBeCalledTimes(1); - expect(copyToClipboard).toHaveBeenCalledWith({ text: "TEST_USERNAME", options: undefined }); + expect(copyToClipboard).toHaveBeenCalledWith({ + text: "TEST_USERNAME", + tab: { url: "https://test.com" }, + }); }); it("copies password to clipboard", async () => { @@ -130,11 +138,16 @@ describe("ContextMenuClickedHandler", () => { createCipher({ password: "TEST_PASSWORD" }), ]); - await sut.run(createData("T_1", COPY_PASSWORD_ID)); + await sut.run(createData(`${COPY_PASSWORD_ID}_1`, COPY_PASSWORD_ID), { + url: "https://test.com", + } as any); expect(copyToClipboard).toBeCalledTimes(1); - expect(copyToClipboard).toHaveBeenCalledWith({ text: "TEST_PASSWORD", options: undefined }); + expect(copyToClipboard).toHaveBeenCalledWith({ + text: "TEST_PASSWORD", + tab: { url: "https://test.com" }, + }); }); it("copies totp code to clipboard", async () => { @@ -148,11 +161,16 @@ describe("ContextMenuClickedHandler", () => { return Promise.resolve("654321"); }); - await sut.run(createData("T_1", COPY_VERIFICATIONCODE_ID)); + await sut.run(createData(`${COPY_VERIFICATIONCODE_ID}_1`, COPY_VERIFICATIONCODE_ID), { + url: "https://test.com", + } as any); expect(totpService.getCode).toHaveBeenCalledTimes(1); - expect(copyToClipboard).toHaveBeenCalledWith({ text: "123456" }); + expect(copyToClipboard).toHaveBeenCalledWith({ + text: "123456", + tab: { url: "https://test.com" }, + }); }); it("attempts to find a cipher when noop but unlocked", async () => { @@ -163,11 +181,13 @@ describe("ContextMenuClickedHandler", () => { } as any, ]); - await sut.run(createData("T_noop", COPY_USERNAME_ID), { url: "https://test.com" } as any); + await sut.run(createData(`${COPY_USERNAME_ID}_${NOOP_COMMAND_SUFFIX}`, COPY_USERNAME_ID), { + url: "https://test.com", + } as any); expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1); - expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com"); + expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com", []); expect(copyToClipboard).toHaveBeenCalledTimes(1); @@ -185,11 +205,13 @@ describe("ContextMenuClickedHandler", () => { } as any, ]); - await sut.run(createData("T_noop", COPY_USERNAME_ID), { url: "https://test.com" } as any); + await sut.run(createData(`${COPY_USERNAME_ID}_${NOOP_COMMAND_SUFFIX}`, COPY_USERNAME_ID), { + url: "https://test.com", + } as any); expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1); - expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com"); + expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com", []); }); }); }); diff --git a/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts b/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts index 62c6c9c25a4..2df42fc2a90 100644 --- a/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts +++ b/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts @@ -8,6 +8,7 @@ import { StateFactory } from "@bitwarden/common/platform/factories/state-factory import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { @@ -30,16 +31,21 @@ import { import { autofillServiceFactory } from "../background/service_factories/autofill-service.factory"; import { copyToClipboard, GeneratePasswordToClipboardCommand } from "../clipboard"; import { AutofillTabCommand } from "../commands/autofill-tab-command"; - import { + AUTOFILL_CARD_ID, AUTOFILL_ID, + AUTOFILL_IDENTITY_ID, COPY_IDENTIFIER_ID, COPY_PASSWORD_ID, COPY_USERNAME_ID, COPY_VERIFICATIONCODE_ID, + CREATE_CARD_ID, + CREATE_IDENTITY_ID, + CREATE_LOGIN_ID, GENERATE_PASSWORD_ID, NOOP_COMMAND_SUFFIX, -} from "./main-context-menu-handler"; +} from "../constants"; +import { AutofillCipherTypeId } from "../types"; export type CopyToClipboardOptions = { text: string; tab: chrome.tabs.Tab }; export type CopyToClipboardAction = (options: CopyToClipboardOptions) => void; @@ -142,18 +148,16 @@ export class ContextMenuClickedHandler { ); } - async run(info: chrome.contextMenus.OnClickData, tab?: chrome.tabs.Tab) { + async run(info: chrome.contextMenus.OnClickData, tab: chrome.tabs.Tab) { + if (!tab) { + return; + } + switch (info.menuItemId) { case GENERATE_PASSWORD_ID: - if (!tab) { - return; - } await this.generatePasswordToClipboard(tab); break; case COPY_IDENTIFIER_ID: - if (!tab) { - return; - } this.copyToClipboard({ text: await this.getIdentifier(tab, info), tab: tab }); break; default: @@ -161,7 +165,11 @@ export class ContextMenuClickedHandler { } } - async cipherAction(info: chrome.contextMenus.OnClickData, tab?: chrome.tabs.Tab) { + async cipherAction(info: chrome.contextMenus.OnClickData, tab: chrome.tabs.Tab) { + if (!tab) { + return; + } + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { const retryMessage: LockedVaultPendingNotificationsItem = { commandToRetry: { @@ -182,32 +190,57 @@ export class ContextMenuClickedHandler { // NOTE: We don't actually use the first part of this ID, we further switch based on the parentMenuItemId // I would really love to not add it but that is a departure from how it currently works. - const id = (info.menuItemId as string).split("_")[1]; // We create all the ids, we can guarantee they are strings + const menuItemId = (info.menuItemId as string).split("_")[1]; // We create all the ids, we can guarantee they are strings let cipher: CipherView | undefined; - if (id === NOOP_COMMAND_SUFFIX) { + const isCreateCipherAction = [CREATE_LOGIN_ID, CREATE_IDENTITY_ID, CREATE_CARD_ID].includes( + menuItemId as string + ); + + if (isCreateCipherAction) { + // pass; defer to logic below + } else if (menuItemId === NOOP_COMMAND_SUFFIX) { + const additionalCiphersToGet = + info.parentMenuItemId === AUTOFILL_IDENTITY_ID + ? [CipherType.Identity] + : info.parentMenuItemId === AUTOFILL_CARD_ID + ? [CipherType.Card] + : []; + // This NOOP item has come through which is generally only for no access state but since we got here // we are actually unlocked we will do our best to find a good match of an item to autofill this is useful // in scenarios like unlock on autofill - const ciphers = await this.cipherService.getAllDecryptedForUrl(tab.url); + const ciphers = await this.cipherService.getAllDecryptedForUrl( + tab.url, + additionalCiphersToGet + ); + cipher = ciphers[0]; } else { const ciphers = await this.cipherService.getAllDecrypted(); - cipher = ciphers.find((c) => c.id === id); + cipher = ciphers.find(({ id }) => id === menuItemId); } - if (cipher == null) { + if (!cipher && !isCreateCipherAction) { return; } switch (info.parentMenuItemId) { case AUTOFILL_ID: - if (tab == null) { - return; + case AUTOFILL_IDENTITY_ID: + case AUTOFILL_CARD_ID: { + const cipherType = this.getCipherCreationType(menuItemId); + + if (cipherType) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType, + }); + break; } if (await this.isPasswordRepromptRequired(cipher)) { await BrowserApi.tabSendMessageData(tab, "passwordReprompt", { cipherId: cipher.id, + // The action here is passed on to the single-use reprompt window and doesn't change based on cipher type action: AUTOFILL_ID, }); } else { @@ -215,14 +248,29 @@ export class ContextMenuClickedHandler { } break; + } case COPY_USERNAME_ID: + if (menuItemId === CREATE_LOGIN_ID) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType: CipherType.Login, + }); + break; + } + this.copyToClipboard({ text: cipher.login.username, tab: tab }); break; case COPY_PASSWORD_ID: + if (menuItemId === CREATE_LOGIN_ID) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType: CipherType.Login, + }); + break; + } + if (await this.isPasswordRepromptRequired(cipher)) { await BrowserApi.tabSendMessageData(tab, "passwordReprompt", { cipherId: cipher.id, - action: COPY_PASSWORD_ID, + action: info.parentMenuItemId, }); } else { this.copyToClipboard({ text: cipher.login.password, tab: tab }); @@ -231,10 +279,17 @@ export class ContextMenuClickedHandler { break; case COPY_VERIFICATIONCODE_ID: + if (menuItemId === CREATE_LOGIN_ID) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType: CipherType.Login, + }); + break; + } + if (await this.isPasswordRepromptRequired(cipher)) { await BrowserApi.tabSendMessageData(tab, "passwordReprompt", { cipherId: cipher.id, - action: COPY_VERIFICATIONCODE_ID, + action: info.parentMenuItemId, }); } else { this.copyToClipboard({ @@ -254,6 +309,16 @@ export class ContextMenuClickedHandler { ); } + private getCipherCreationType(menuItemId?: string): AutofillCipherTypeId | null { + return menuItemId === CREATE_IDENTITY_ID + ? CipherType.Identity + : menuItemId === CREATE_CARD_ID + ? CipherType.Card + : menuItemId === CREATE_LOGIN_ID + ? CipherType.Login + : null; + } + private async getIdentifier(tab: chrome.tabs.Tab, info: chrome.contextMenus.OnClickData) { return new Promise((resolve, reject) => { BrowserApi.sendTabsMessage( diff --git a/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts b/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts index 6b599986b67..95916d2e6f1 100644 --- a/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts +++ b/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts @@ -60,7 +60,7 @@ describe("context-menu", () => { const createdMenu = await sut.init(); expect(createdMenu).toBeTruthy(); - expect(createSpy).toHaveBeenCalledTimes(7); + expect(createSpy).toHaveBeenCalledTimes(10); }); it("has menu enabled and has premium", async () => { @@ -70,7 +70,7 @@ describe("context-menu", () => { const createdMenu = await sut.init(); expect(createdMenu).toBeTruthy(); - expect(createSpy).toHaveBeenCalledTimes(8); + expect(createSpy).toHaveBeenCalledTimes(11); }); }); @@ -97,7 +97,7 @@ describe("context-menu", () => { }; it("is not a login cipher", async () => { - await sut.loadOptions("TEST_TITLE", "1", "", { + await sut.loadOptions("TEST_TITLE", "1", { ...createCipher(), type: CipherType.SecureNote, } as any); @@ -109,7 +109,6 @@ describe("context-menu", () => { await sut.loadOptions( "TEST_TITLE", "1", - "", createCipher({ username: "", totp: "", @@ -123,18 +122,18 @@ describe("context-menu", () => { it("create entry for each cipher piece", async () => { stateService.getCanAccessPremium.mockResolvedValue(true); - await sut.loadOptions("TEST_TITLE", "1", "", createCipher()); + await sut.loadOptions("TEST_TITLE", "1", createCipher()); // One for autofill, copy username, copy password, and copy totp code expect(createSpy).toHaveBeenCalledTimes(4); }); - it("creates noop item for no cipher", async () => { + it("creates a login/unlock item for each context menu action option when user is not authenticated", async () => { stateService.getCanAccessPremium.mockResolvedValue(true); - await sut.loadOptions("TEST_TITLE", "NOOP", ""); + await sut.loadOptions("TEST_TITLE", "NOOP"); - expect(createSpy).toHaveBeenCalledTimes(4); + expect(createSpy).toHaveBeenCalledTimes(6); }); }); }); diff --git a/apps/browser/src/autofill/browser/main-context-menu-handler.ts b/apps/browser/src/autofill/browser/main-context-menu-handler.ts index b9af3dd191f..cc5cc9a5166 100644 --- a/apps/browser/src/autofill/browser/main-context-menu-handler.ts +++ b/apps/browser/src/autofill/browser/main-context-menu-handler.ts @@ -21,22 +21,24 @@ import { StateServiceInitOptions, } from "../../platform/background/service-factories/state-service.factory"; import { BrowserStateService } from "../../platform/services/abstractions/browser-state.service"; - -export const ROOT_ID = "root"; - -export const AUTOFILL_ID = "autofill"; -export const COPY_USERNAME_ID = "copy-username"; -export const COPY_PASSWORD_ID = "copy-password"; -export const COPY_VERIFICATIONCODE_ID = "copy-totp"; -export const COPY_IDENTIFIER_ID = "copy-identifier"; - -const SEPARATOR_ID = "separator"; -export const GENERATE_PASSWORD_ID = "generate-password"; - -export const NOOP_COMMAND_SUFFIX = "noop"; +import { + AUTOFILL_CARD_ID, + AUTOFILL_ID, + AUTOFILL_IDENTITY_ID, + COPY_IDENTIFIER_ID, + COPY_PASSWORD_ID, + COPY_USERNAME_ID, + COPY_VERIFICATIONCODE_ID, + CREATE_CARD_ID, + CREATE_IDENTITY_ID, + CREATE_LOGIN_ID, + GENERATE_PASSWORD_ID, + NOOP_COMMAND_SUFFIX, + ROOT_ID, + SEPARATOR_ID, +} from "../constants"; export class MainContextMenuHandler { - // private initRunning = false; create: (options: chrome.contextMenus.CreateProperties) => Promise; @@ -120,7 +122,7 @@ export class MainContextMenuHandler { await create({ id: AUTOFILL_ID, parentId: ROOT_ID, - title: this.i18nService.t("autoFill"), + title: this.i18nService.t("autoFillLogin"), }); await create({ @@ -144,7 +146,25 @@ export class MainContextMenuHandler { } await create({ - id: SEPARATOR_ID, + id: SEPARATOR_ID + 1, + type: "separator", + parentId: ROOT_ID, + }); + + await create({ + id: AUTOFILL_IDENTITY_ID, + parentId: ROOT_ID, + title: this.i18nService.t("autoFillIdentity"), + }); + + await create({ + id: AUTOFILL_CARD_ID, + parentId: ROOT_ID, + title: this.i18nService.t("autoFillCard"), + }); + + await create({ + id: SEPARATOR_ID + 2, type: "separator", parentId: ROOT_ID, }); @@ -194,40 +214,52 @@ export class MainContextMenuHandler { }); } - async loadOptions(title: string, id: string, url: string, cipher?: CipherView | undefined) { - if (cipher != null && cipher.type !== CipherType.Login) { - return; - } - + async loadOptions(title: string, optionId: string, cipher?: CipherView) { try { const sanitizedTitle = MainContextMenuHandler.sanitizeContextMenuTitle(title); - const createChildItem = async (parent: string) => { - const menuItemId = `${parent}_${id}`; + const createChildItem = async (parentId: string) => { + const menuItemId = `${parentId}_${optionId}`; + return await this.create({ type: "normal", id: menuItemId, - parentId: parent, + parentId, title: sanitizedTitle, contexts: ["all"], }); }; - if (cipher == null || !Utils.isNullOrEmpty(cipher.login.password)) { + if ( + !cipher || + (cipher.type === CipherType.Login && !Utils.isNullOrEmpty(cipher.login?.password)) + ) { await createChildItem(AUTOFILL_ID); + if (cipher?.viewPassword ?? true) { await createChildItem(COPY_PASSWORD_ID); } } - if (cipher == null || !Utils.isNullOrEmpty(cipher.login.username)) { + if ( + !cipher || + (cipher.type === CipherType.Login && !Utils.isNullOrEmpty(cipher.login?.username)) + ) { await createChildItem(COPY_USERNAME_ID); } const canAccessPremium = await this.stateService.getCanAccessPremium(); - if (canAccessPremium && (cipher == null || !Utils.isNullOrEmpty(cipher.login.totp))) { + if (canAccessPremium && (!cipher || !Utils.isNullOrEmpty(cipher.login?.totp))) { await createChildItem(COPY_VERIFICATIONCODE_ID); } + + if ((!cipher || cipher.type === CipherType.Card) && optionId !== CREATE_LOGIN_ID) { + await createChildItem(AUTOFILL_CARD_ID); + } + + if ((!cipher || cipher.type === CipherType.Identity) && optionId !== CREATE_LOGIN_ID) { + await createChildItem(AUTOFILL_IDENTITY_ID); + } } catch (error) { this.logService.warning(error.message); } @@ -242,13 +274,72 @@ export class MainContextMenuHandler { const authed = await this.stateService.getIsAuthenticated(); await this.loadOptions( this.i18nService.t(authed ? "unlockVaultMenu" : "loginToVaultMenu"), - NOOP_COMMAND_SUFFIX, - "" + NOOP_COMMAND_SUFFIX ); } } - async noLogins(url: string) { - await this.loadOptions(this.i18nService.t("noMatchingLogins"), NOOP_COMMAND_SUFFIX, url); + async noCards() { + await this.create({ + id: `${AUTOFILL_CARD_ID}_NOTICE`, + enabled: false, + parentId: AUTOFILL_CARD_ID, + title: this.i18nService.t("noCards"), + type: "normal", + }); + + await this.create({ + id: `${AUTOFILL_CARD_ID}_${SEPARATOR_ID}`, + parentId: AUTOFILL_CARD_ID, + type: "separator", + }); + + await this.create({ + id: `${AUTOFILL_CARD_ID}_${CREATE_CARD_ID}`, + parentId: AUTOFILL_CARD_ID, + title: this.i18nService.t("addCardMenu"), + type: "normal", + }); + } + + async noIdentities() { + await this.create({ + id: `${AUTOFILL_IDENTITY_ID}_NOTICE`, + enabled: false, + parentId: AUTOFILL_IDENTITY_ID, + title: this.i18nService.t("noIdentities"), + type: "normal", + }); + + await this.create({ + id: `${AUTOFILL_IDENTITY_ID}_${SEPARATOR_ID}`, + parentId: AUTOFILL_IDENTITY_ID, + type: "separator", + }); + + await this.create({ + id: `${AUTOFILL_IDENTITY_ID}_${CREATE_IDENTITY_ID}`, + parentId: AUTOFILL_IDENTITY_ID, + title: this.i18nService.t("addIdentityMenu"), + type: "normal", + }); + } + + async noLogins() { + await this.create({ + id: `${AUTOFILL_ID}_NOTICE`, + enabled: false, + parentId: AUTOFILL_ID, + title: this.i18nService.t("noMatchingLogins"), + type: "normal", + }); + + await this.create({ + id: `${AUTOFILL_ID}_${SEPARATOR_ID}` + 1, + parentId: AUTOFILL_ID, + type: "separator", + }); + + await this.loadOptions(this.i18nService.t("addLoginMenu"), CREATE_LOGIN_ID); } } diff --git a/apps/browser/src/autofill/constants.ts b/apps/browser/src/autofill/constants.ts index 7f3637180b0..ef82035aef7 100644 --- a/apps/browser/src/autofill/constants.ts +++ b/apps/browser/src/autofill/constants.ts @@ -11,3 +11,19 @@ export const EVENTS = { KEYPRESS: "keypress", KEYUP: "keyup", } as const; + +/* Context Menu item Ids */ +export const AUTOFILL_CARD_ID = "autofill-card"; +export const AUTOFILL_ID = "autofill"; +export const AUTOFILL_IDENTITY_ID = "autofill-identity"; +export const COPY_IDENTIFIER_ID = "copy-identifier"; +export const COPY_PASSWORD_ID = "copy-password"; +export const COPY_USERNAME_ID = "copy-username"; +export const COPY_VERIFICATIONCODE_ID = "copy-totp"; +export const CREATE_CARD_ID = "create-card"; +export const CREATE_IDENTITY_ID = "create-identity"; +export const CREATE_LOGIN_ID = "create-login"; +export const GENERATE_PASSWORD_ID = "generate-password"; +export const NOOP_COMMAND_SUFFIX = "noop"; +export const ROOT_ID = "root"; +export const SEPARATOR_ID = "separator"; diff --git a/apps/browser/src/autofill/services/abstractions/autofill.service.ts b/apps/browser/src/autofill/services/abstractions/autofill.service.ts index ac7971768e4..bbd0b21d226 100644 --- a/apps/browser/src/autofill/services/abstractions/autofill.service.ts +++ b/apps/browser/src/autofill/services/abstractions/autofill.service.ts @@ -1,4 +1,5 @@ import { UriMatchType } from "@bitwarden/common/enums"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import AutofillField from "../../models/autofill-field"; @@ -55,5 +56,9 @@ export abstract class AutofillService { tab: chrome.tabs.Tab, fromCommand: boolean ) => Promise; - doAutoFillActiveTab: (pageDetails: PageDetail[], fromCommand: boolean) => Promise; + doAutoFillActiveTab: ( + pageDetails: PageDetail[], + fromCommand: boolean, + cipherType?: CipherType + ) => Promise; } diff --git a/apps/browser/src/autofill/services/autofill.service.spec.ts b/apps/browser/src/autofill/services/autofill.service.spec.ts index e6a629cfc9d..f8f12fa7ddb 100644 --- a/apps/browser/src/autofill/services/autofill.service.spec.ts +++ b/apps/browser/src/autofill/services/autofill.service.spec.ts @@ -780,6 +780,18 @@ describe("AutofillService", () => { ]; }); + it("returns a null vault without doing autofill if the page details does not contain fields ", async () => { + pageDetails[0].details.fields = []; + jest.spyOn(autofillService as any, "getActiveTab"); + jest.spyOn(autofillService, "doAutoFill"); + + const result = await autofillService.doAutoFillActiveTab(pageDetails, false); + + expect(autofillService["getActiveTab"]).not.toHaveBeenCalled(); + expect(autofillService.doAutoFill).not.toHaveBeenCalled(); + expect(result).toBeNull(); + }); + it("returns a null value without doing autofill if the active tab cannot be found", async () => { jest.spyOn(autofillService as any, "getActiveTab").mockResolvedValueOnce(undefined); jest.spyOn(autofillService, "doAutoFill"); diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index c494b8ece0f..ee233c42524 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -205,6 +205,7 @@ export default class AutofillService implements AutofillServiceInterface { if ( options.cipher.type !== CipherType.Login || + // eslint-disable-next-line @typescript-eslint/no-misused-promises totpPromise || !options.cipher.login.totp || (!canAccessPremium && !options.cipher.organizationUseTotp) @@ -303,21 +304,51 @@ export default class AutofillService implements AutofillServiceInterface { } /** - * Autofill the active tab with the next login item from the cache + * Autofill the active tab with the next cipher from the cache * @param {PageDetail[]} pageDetails The data scraped from the page * @param {boolean} fromCommand Whether the autofill is triggered by a keyboard shortcut (`true`) or autofill on page load (`false`) * @returns {Promise} The TOTP code of the successfully autofilled login, if any */ async doAutoFillActiveTab( pageDetails: PageDetail[], - fromCommand: boolean + fromCommand: boolean, + cipherType?: CipherType ): Promise { + if (!pageDetails[0]?.details?.fields?.length) { + return null; + } + const tab = await this.getActiveTab(); + if (!tab || !tab.url) { return null; } - return await this.doAutoFillOnTab(pageDetails, tab, fromCommand); + if (!cipherType || cipherType === CipherType.Login) { + return await this.doAutoFillOnTab(pageDetails, tab, fromCommand); + } + + // Cipher is a non-login type + const cipher: CipherView = ( + (await this.cipherService.getAllDecryptedForUrl(tab.url, [cipherType])) || [] + ).find(({ type }) => type === cipherType); + + if (!cipher || cipher.reprompt !== CipherRepromptType.None) { + return null; + } + + return await this.doAutoFill({ + tab: tab, + cipher: cipher, + pageDetails: pageDetails, + skipLastUsed: !fromCommand, + skipUsernameOnlyFill: !fromCommand, + onlyEmptyFields: !fromCommand, + onlyVisibleFields: !fromCommand, + fillNewPassword: false, + allowUntrustedIframe: fromCommand, + allowTotpAutofill: false, + }); } /** diff --git a/apps/browser/src/autofill/types/index.ts b/apps/browser/src/autofill/types/index.ts index 8bab87709d2..8a97e397477 100644 --- a/apps/browser/src/autofill/types/index.ts +++ b/apps/browser/src/autofill/types/index.ts @@ -1,5 +1,6 @@ import { Region } from "@bitwarden/common/platform/abstractions/environment.service"; import { VaultTimeoutAction } from "@bitwarden/common/src/enums/vault-timeout-action.enum"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; export type UserSettings = { avatarColor: string | null; @@ -58,3 +59,5 @@ export type FillableFormFieldElement = HTMLInputElement | HTMLSelectElement | HT export type FormFieldElement = FillableFormFieldElement | HTMLSpanElement; export type FormElementWithAttribute = FormFieldElement & Record; + +export type AutofillCipherTypeId = CipherType.Login | CipherType.Card | CipherType.Identity; diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 3aba0c77679..7a9863f3a70 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -322,23 +322,6 @@ export default class MainBackground { ); this.searchService = new SearchService(this.logService, this.i18nService); - this.cipherService = new CipherService( - this.cryptoService, - this.settingsService, - this.apiService, - this.i18nService, - this.searchService, - this.stateService, - this.encryptService, - this.cipherFileUploadService - ); - this.folderService = new BrowserFolderService( - this.cryptoService, - this.i18nService, - this.cipherService, - this.stateService - ); - this.folderApiService = new FolderApiService(this.folderService, this.apiService); this.collectionService = new CollectionService( this.cryptoService, this.i18nService, @@ -362,14 +345,6 @@ export default class MainBackground { this.cryptoFunctionService, logoutCallback ); - this.vaultFilterService = new VaultFilterService( - this.stateService, - this.organizationService, - this.folderService, - this.cipherService, - this.collectionService, - this.policyService - ); this.passwordStrengthService = new PasswordStrengthService(); @@ -436,6 +411,36 @@ export default class MainBackground { this.userVerificationApiService ); + this.configApiService = new ConfigApiService(this.apiService, this.authService); + + this.configService = new BrowserConfigService( + this.stateService, + this.configApiService, + this.authService, + this.environmentService, + this.logService, + true + ); + + this.cipherService = new CipherService( + this.cryptoService, + this.settingsService, + this.apiService, + this.i18nService, + this.searchService, + this.stateService, + this.encryptService, + this.cipherFileUploadService, + this.configService + ); + this.folderService = new BrowserFolderService( + this.cryptoService, + this.i18nService, + this.cipherService, + this.stateService + ); + this.folderApiService = new FolderApiService(this.folderService, this.apiService); + this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService( this.cryptoService, this.tokenService, @@ -444,6 +449,15 @@ export default class MainBackground { this.userVerificationService ); + this.vaultFilterService = new VaultFilterService( + this.stateService, + this.organizationService, + this.folderService, + this.cipherService, + this.collectionService, + this.policyService + ); + this.vaultTimeoutService = new VaultTimeoutService( this.cipherService, this.folderService, @@ -533,16 +547,6 @@ export default class MainBackground { this.messagingService ); - this.configApiService = new ConfigApiService(this.apiService, this.authService); - - this.configService = new BrowserConfigService( - this.stateService, - this.configApiService, - this.authService, - this.environmentService, - this.logService, - true - ); this.browserPopoutWindowService = new BrowserPopoutWindowService(); const systemUtilsServiceReloadCallback = () => { diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index dcf828ef4a0..dc7ea9a69f9 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -6,6 +6,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { SystemService } from "@bitwarden/common/platform/abstractions/system.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { AutofillService } from "../autofill/services/abstractions/autofill.service"; import { BrowserApi } from "../platform/browser/browser-api"; @@ -123,12 +124,28 @@ export default class RuntimeBackground { } break; case "openAddEditCipher": { - const addEditCipherUrl = - cipherId == null - ? "popup/index.html#/edit-cipher" - : "popup/index.html#/edit-cipher?cipherId=" + cipherId; + const isNewCipher = !cipherId; + const cipherType = msg.data?.cipherType; + const senderTab = sender.tab; + + if (!senderTab) { + break; + } + + if (isNewCipher) { + await this.browserPopoutWindowService.openCipherCreation(senderTab.windowId, { + cipherType, + senderTabId: senderTab.id, + senderTabURI: senderTab.url, + }); + } else { + await this.browserPopoutWindowService.openCipherEdit(senderTab.windowId, { + cipherId, + senderTabId: senderTab.id, + senderTabURI: senderTab.url, + }); + } - BrowserApi.openBitwardenExtensionTab(addEditCipherUrl, true); break; } case "closeTab": @@ -174,6 +191,34 @@ export default class RuntimeBackground { } break; } + case "autofill_card": { + await this.autofillService.doAutoFillActiveTab( + [ + { + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }, + ], + false, + CipherType.Card + ); + break; + } + case "autofill_identity": { + await this.autofillService.doAutoFillActiveTab( + [ + { + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }, + ], + false, + CipherType.Identity + ); + break; + } case "contextMenu": clearTimeout(this.autofillTimeout); this.pageDetailsToAutoFill.push({ diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index 7bd5e9f5a06..41efa59632b 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2023.9.1", + "version": "2023.9.2", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index 7a42aa0ffae..ba8668984de 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -3,7 +3,7 @@ "minimum_chrome_version": "102.0", "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2023.9.1", + "version": "2023.9.2", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/browser/src/platform/background/service-factories/config-api.service.factory.ts b/apps/browser/src/platform/background/service-factories/config-api.service.factory.ts new file mode 100644 index 00000000000..e9e1b86488a --- /dev/null +++ b/apps/browser/src/platform/background/service-factories/config-api.service.factory.ts @@ -0,0 +1,32 @@ +import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; +import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; + +import { + authServiceFactory, + AuthServiceInitOptions, +} from "../../../auth/background/service-factories/auth-service.factory"; + +import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory"; +import { FactoryOptions, CachedServices, factory } from "./factory-options"; + +type ConfigApiServiceFactoyOptions = FactoryOptions; + +export type ConfigApiServiceInitOptions = ConfigApiServiceFactoyOptions & + ApiServiceInitOptions & + AuthServiceInitOptions; + +export function configApiServiceFactory( + cache: { configApiService?: ConfigApiServiceAbstraction } & CachedServices, + opts: ConfigApiServiceInitOptions +): Promise { + return factory( + cache, + "configApiService", + opts, + async () => + new ConfigApiService( + await apiServiceFactory(cache, opts), + await authServiceFactory(cache, opts) + ) + ); +} diff --git a/apps/browser/src/platform/background/service-factories/config-service.factory.ts b/apps/browser/src/platform/background/service-factories/config-service.factory.ts new file mode 100644 index 00000000000..a5dc6016c65 --- /dev/null +++ b/apps/browser/src/platform/background/service-factories/config-service.factory.ts @@ -0,0 +1,49 @@ +import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; +import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; + +import { + authServiceFactory, + AuthServiceInitOptions, +} from "../../../auth/background/service-factories/auth-service.factory"; + +import { configApiServiceFactory, ConfigApiServiceInitOptions } from "./config-api.service.factory"; +import { + environmentServiceFactory, + EnvironmentServiceInitOptions, +} from "./environment-service.factory"; +import { FactoryOptions, CachedServices, factory } from "./factory-options"; +import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory"; +import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory"; + +type ConfigServiceFactoryOptions = FactoryOptions & { + configServiceOptions?: { + subscribe?: boolean; + }; +}; + +export type ConfigServiceInitOptions = ConfigServiceFactoryOptions & + StateServiceInitOptions & + ConfigApiServiceInitOptions & + AuthServiceInitOptions & + EnvironmentServiceInitOptions & + LogServiceInitOptions; + +export function configServiceFactory( + cache: { configService?: ConfigServiceAbstraction } & CachedServices, + opts: ConfigServiceInitOptions +): Promise { + return factory( + cache, + "configService", + opts, + async () => + new ConfigService( + await stateServiceFactory(cache, opts), + await configApiServiceFactory(cache, opts), + await authServiceFactory(cache, opts), + await environmentServiceFactory(cache, opts), + await logServiceFactory(cache, opts), + opts.configServiceOptions?.subscribe ?? true + ) + ); +} diff --git a/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts b/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts index 0b3f55ee990..0ded45bea94 100644 --- a/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts +++ b/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts @@ -1,3 +1,5 @@ +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; + interface BrowserPopoutWindowService { openUnlockPrompt(senderWindowId: number): Promise; closeUnlockPrompt(): Promise; @@ -9,6 +11,22 @@ interface BrowserPopoutWindowService { senderTabId: number; } ): Promise; + openCipherCreation( + senderWindowId: number, + promptData: { + cipherType?: CipherType; + senderTabId: number; + senderTabURI: string; + } + ): Promise; + openCipherEdit( + senderWindowId: number, + promptData: { + cipherId: string; + senderTabId: number; + senderTabURI: string; + } + ): Promise; closePasswordRepromptPrompt(): Promise; } diff --git a/apps/browser/src/platform/popup/browser-popout-window.service.ts b/apps/browser/src/platform/popup/browser-popout-window.service.ts index ee03e3a2ec4..f5ac2f3128e 100644 --- a/apps/browser/src/platform/popup/browser-popout-window.service.ts +++ b/apps/browser/src/platform/popup/browser-popout-window.service.ts @@ -1,3 +1,5 @@ +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; + import { BrowserApi } from "../browser/browser-api"; import { BrowserPopoutWindowService as BrowserPopupWindowServiceInterface } from "./abstractions/browser-popout-window.service"; @@ -45,6 +47,50 @@ class BrowserPopoutWindowService implements BrowserPopupWindowServiceInterface { await this.openSingleActionPopout(senderWindowId, promptWindowPath, "passwordReprompt"); } + async openCipherCreation( + senderWindowId: number, + { + cipherType = CipherType.Login, + senderTabId, + senderTabURI, + }: { + cipherType?: CipherType; + senderTabId: number; + senderTabURI: string; + } + ) { + const promptWindowPath = + "popup/index.html#/edit-cipher" + + "?uilocation=popout" + + `&type=${cipherType}` + + `&senderTabId=${senderTabId}` + + `&uri=${senderTabURI}`; + + await this.openSingleActionPopout(senderWindowId, promptWindowPath, "cipherCreation"); + } + + async openCipherEdit( + senderWindowId: number, + { + cipherId, + senderTabId, + senderTabURI, + }: { + cipherId: string; + senderTabId: number; + senderTabURI: string; + } + ) { + const promptWindowPath = + "popup/index.html#/edit-cipher" + + "?uilocation=popout" + + `&cipherId=${cipherId}` + + `&senderTabId=${senderTabId}` + + `&uri=${senderTabURI}`; + + await this.openSingleActionPopout(senderWindowId, promptWindowPath, "cipherEdit"); + } + async closePasswordRepromptPrompt() { await this.closeSingleActionPopout("passwordReprompt"); } diff --git a/apps/browser/src/tools/popup/generator/generator.component.html b/apps/browser/src/tools/popup/generator/generator.component.html index 13d35b6cd7a..cf7a2949f24 100644 --- a/apps/browser/src/tools/popup/generator/generator.component.html +++ b/apps/browser/src/tools/popup/generator/generator.component.html @@ -378,7 +378,7 @@ />
- +
+
+ + +
@@ -424,7 +434,7 @@ />
- + { + this.senderTabId = parseInt(params?.senderTabId, 10) || undefined; + this.uilocation = params?.uilocation; + if (params.cipherId) { this.cipherId = params.cipherId; } @@ -128,6 +134,8 @@ export class AddEditComponent extends BaseAddEditComponent { this.openAttachmentsInPopup = this.popupUtilsService.inPopup(window); }); + this.inPopout = this.uilocation === "popout" || this.popupUtilsService.inPopout(window); + if (!this.editMode) { const tabs = await BrowserApi.tabsQuery({ windowType: "normal" }); this.currentUris = @@ -162,6 +170,11 @@ export class AddEditComponent extends BaseAddEditComponent { return true; } + if (this.senderTabId && this.inPopout) { + setTimeout(() => this.close(), 1000); + return true; + } + if (this.cloneMode) { this.router.navigate(["/tabs/vault"]); } else { @@ -194,6 +207,11 @@ export class AddEditComponent extends BaseAddEditComponent { cancel() { super.cancel(); + if (this.senderTabId && this.inPopout) { + this.close(); + return; + } + if (this.popupUtilsService.inTab(window)) { this.messagingService.send("closeTab"); return; @@ -202,6 +220,14 @@ export class AddEditComponent extends BaseAddEditComponent { this.location.back(); } + // Used for closing single-action views + close() { + BrowserApi.focusTab(this.senderTabId); + window.close(); + + return; + } + async generateUsername(): Promise { const confirmed = await super.generateUsername(); if (confirmed) { diff --git a/apps/cli/config/development.json b/apps/cli/config/development.json index b04d1531a2f..f57c3d9bc38 100644 --- a/apps/cli/config/development.json +++ b/apps/cli/config/development.json @@ -1,3 +1,5 @@ { - "flags": {} + "flags": { + "enableCipherKeyEncryption": false + } } diff --git a/apps/cli/config/production.json b/apps/cli/config/production.json index b04d1531a2f..f57c3d9bc38 100644 --- a/apps/cli/config/production.json +++ b/apps/cli/config/production.json @@ -1,3 +1,5 @@ { - "flags": {} + "flags": { + "enableCipherKeyEncryption": false + } } diff --git a/apps/cli/package.json b/apps/cli/package.json index 153b8d9ce89..02f7f6086d4 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/cli", "description": "A secure and free password manager for all of your devices.", - "version": "2023.9.0", + "version": "2023.9.1", "keywords": [ "bitwarden", "password", diff --git a/apps/cli/src/admin-console/commands/share.command.ts b/apps/cli/src/admin-console/commands/share.command.ts index 68bd8a18056..88fe256af18 100644 --- a/apps/cli/src/admin-console/commands/share.command.ts +++ b/apps/cli/src/admin-console/commands/share.command.ts @@ -45,11 +45,15 @@ export class ShareCommand { if (cipher.organizationId != null) { return Response.badRequest("This item already belongs to an organization."); } - const cipherView = await cipher.decrypt(); + const cipherView = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); try { await this.cipherService.shareWithServer(cipherView, organizationId, req); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { diff --git a/apps/cli/src/bw.ts b/apps/cli/src/bw.ts index 42ba158ee72..ca501690193 100644 --- a/apps/cli/src/bw.ts +++ b/apps/cli/src/bw.ts @@ -25,11 +25,13 @@ import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.ser import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service"; import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service"; import { ClientType, KeySuffixOptions, LogLevelType } from "@bitwarden/common/enums"; +import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; import { Account } from "@bitwarden/common/platform/models/domain/account"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { AppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { BroadcasterService } from "@bitwarden/common/platform/services/broadcaster.service"; +import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation"; @@ -75,6 +77,7 @@ import { } from "@bitwarden/importer"; import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service"; +import { CliConfigService } from "./platform/services/cli-config.service"; import { CliPlatformUtilsService } from "./platform/services/cli-platform-utils.service"; import { ConsoleLogService } from "./platform/services/console-log.service"; import { I18nService } from "./platform/services/i18n.service"; @@ -147,6 +150,8 @@ export class Main { devicesApiService: DevicesApiServiceAbstraction; deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction; authRequestCryptoService: AuthRequestCryptoServiceAbstraction; + configApiService: ConfigApiServiceAbstraction; + configService: CliConfigService; constructor() { let p = null; @@ -252,28 +257,8 @@ export class Main { this.searchService = new SearchService(this.logService, this.i18nService); - this.cipherService = new CipherService( - this.cryptoService, - this.settingsService, - this.apiService, - this.i18nService, - this.searchService, - this.stateService, - this.encryptService, - this.cipherFileUploadService - ); - this.broadcasterService = new BroadcasterService(); - this.folderService = new FolderService( - this.cryptoService, - this.i18nService, - this.cipherService, - this.stateService - ); - - this.folderApiService = new FolderApiService(this.folderService, this.apiService); - this.collectionService = new CollectionService( this.cryptoService, this.i18nService, @@ -349,6 +334,38 @@ export class Main { this.authRequestCryptoService ); + this.configApiService = new ConfigApiService(this.apiService, this.authService); + + this.configService = new CliConfigService( + this.stateService, + this.configApiService, + this.authService, + this.environmentService, + this.logService, + true + ); + + this.cipherService = new CipherService( + this.cryptoService, + this.settingsService, + this.apiService, + this.i18nService, + this.searchService, + this.stateService, + this.encryptService, + this.cipherFileUploadService, + this.configService + ); + + this.folderService = new FolderService( + this.cryptoService, + this.i18nService, + this.cipherService, + this.stateService + ); + + this.folderApiService = new FolderApiService(this.folderService, this.apiService); + const lockedCallback = async (userId?: string) => await this.cryptoService.clearStoredUserKey(KeySuffixOptions.Auto); @@ -472,6 +489,7 @@ export class Main { const locale = await this.stateService.getLocale(); await this.i18nService.init(locale); this.twoFactorService.init(); + this.configService.init(); const installedVersion = await this.stateService.getInstalledVersion(); const currentVersion = await this.platformUtilsService.getApplicationVersion(); diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts index 960b0999146..60e5ee7936e 100644 --- a/apps/cli/src/commands/edit.command.ts +++ b/apps/cli/src/commands/edit.command.ts @@ -77,7 +77,9 @@ export class EditCommand { return Response.notFound(); } - let cipherView = await cipher.decrypt(); + let cipherView = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); if (cipherView.isDeleted) { return Response.badRequest("You may not edit a deleted item. Use the restore command first."); } @@ -86,7 +88,9 @@ export class EditCommand { try { await this.cipherService.updateWithServer(encCipher); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { @@ -109,7 +113,9 @@ export class EditCommand { try { await this.cipherService.saveCollectionsWithServer(cipher); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts index 265e24c9d4e..4a84f1efefd 100644 --- a/apps/cli/src/commands/get.command.ts +++ b/apps/cli/src/commands/get.command.ts @@ -103,7 +103,9 @@ export class GetCommand extends DownloadCommand { if (Utils.isGuid(id)) { const cipher = await this.cipherService.get(id); if (cipher != null) { - decCipher = await cipher.decrypt(); + decCipher = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); } } else if (id.trim() !== "") { let ciphers = await this.cipherService.getAllDecrypted(); diff --git a/apps/cli/src/platform/services/cli-config.service.ts b/apps/cli/src/platform/services/cli-config.service.ts new file mode 100644 index 00000000000..6faa1b12e8a --- /dev/null +++ b/apps/cli/src/platform/services/cli-config.service.ts @@ -0,0 +1,9 @@ +import { NEVER } from "rxjs"; + +import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; + +export class CliConfigService extends ConfigService { + // The rxjs timer uses setTimeout/setInterval under the hood, which prevents the node process from exiting + // when the command is finished. Cli should never be alive long enough to use the timer, so we disable it. + protected refreshTimer$ = NEVER; +} diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts index 3f4d53e9737..01217dbc307 100644 --- a/apps/cli/src/vault/create.command.ts +++ b/apps/cli/src/vault/create.command.ts @@ -80,7 +80,9 @@ export class CreateCommand { try { await this.cipherService.createWithServer(cipher); const newCipher = await this.cipherService.get(cipher.id); - const decCipher = await newCipher.decrypt(); + const decCipher = await newCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(newCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { @@ -141,7 +143,9 @@ export class CreateCommand { new Uint8Array(fileBuf).buffer ); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); return Response.success(new CipherResponse(decCipher)); } catch (e) { return Response.error(e); diff --git a/apps/desktop/config/base.json b/apps/desktop/config/base.json index 3ae895a19cf..cb408a87d87 100644 --- a/apps/desktop/config/base.json +++ b/apps/desktop/config/base.json @@ -1,6 +1,7 @@ { "dev_flags": {}, "flags": { - "multithreadDecryption": false + "multithreadDecryption": false, + "enableCipherKeyEncryption": false } } diff --git a/apps/desktop/config/development.json b/apps/desktop/config/development.json index b587e9ecfb9..d2b10738124 100644 --- a/apps/desktop/config/development.json +++ b/apps/desktop/config/development.json @@ -1,6 +1,7 @@ { "devFlags": {}, "flags": { - "showDDGSetting": true + "showDDGSetting": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/desktop/config/production.json b/apps/desktop/config/production.json index 56f19341304..39b78094d0f 100644 --- a/apps/desktop/config/production.json +++ b/apps/desktop/config/production.json @@ -1,5 +1,6 @@ { "flags": { - "showDDGSetting": true + "showDDGSetting": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock index 09ffcd4fd9f..75e8e076f21 100644 --- a/apps/desktop/desktop_native/Cargo.lock +++ b/apps/desktop/desktop_native/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -28,6 +28,23 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "arboard" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac57f2b058a76363e357c056e4f74f1945bf734d37b8b3ef49066c4787dde0fc" +dependencies = [ + "clipboard-win", + "log", + "objc", + "objc-foundation", + "objc_id", + "parking_lot", + "thiserror", + "winapi", + "x11rb", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -48,9 +65,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.2.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" @@ -72,9 +95,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cbc" @@ -87,17 +110,21 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-expr" -version = "0.14.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35b255461940a32985c627ce82900867c61db1659764d3675ea81963f72a4c6" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ "smallvec", + "target-lexicon", ] [[package]] @@ -116,6 +143,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -153,9 +191,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -172,19 +210,19 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b" +checksum = "1f34ba9a9bcb8645379e9de8cb3ecfcf4d1c85ba66d90deb3259206fa5aa193b" dependencies = [ "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] name = "cxx" -version = "1.0.94" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +checksum = "bbe98ba1789d56fb3db3bee5e032774d4f421b685de7ba703643584ba24effbe" dependencies = [ "cc", "cxxbridge-flags", @@ -194,9 +232,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.94" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +checksum = "5c0c11acd0e63bae27dcd2afced407063312771212b7a823b4fd72d633be30fb" dependencies = [ "cc", "codespan-reporting", @@ -204,24 +242,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] name = "cxxbridge-flags" -version = "1.0.94" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" +checksum = "20888d9e1d2298e2ff473cee30efe7d5036e437857ab68bbfea84c74dba91da2" [[package]] name = "cxxbridge-macro" -version = "1.0.94" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +checksum = "2fa16a70dd58129e4dfffdff535fb1bce66673f7bbeec4a5a1765a504e1ccd84" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] @@ -230,6 +268,7 @@ version = "0.0.0" dependencies = [ "aes", "anyhow", + "arboard", "base64", "cbc", "core-foundation", @@ -254,14 +293,30 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -302,7 +357,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] @@ -336,10 +391,20 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.2.9" +name = "gethostname" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -368,9 +433,9 @@ dependencies = [ [[package]] name = "gio-sys" -version = "0.17.4" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1d43b0d7968b48455244ecafe41192871257f5740aa6b095eb19db78e362a5" +checksum = "0ccf87c30a12c469b6d958950f6a9c09f2be20b7773f7e70d20b867fdf2628c3" dependencies = [ "glib-sys", "gobject-sys", @@ -381,9 +446,9 @@ dependencies = [ [[package]] name = "glib" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f1de7cbde31ea4f0a919453a2dcece5d54d5b70e08f8ad254dc4840f5f09b6" +checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b" dependencies = [ "bitflags 1.3.2", "futures-channel", @@ -404,9 +469,9 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7206c5c03851ef126ea1444990e81fdd6765fb799d5bc694e4897ca01bb97f" +checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26" dependencies = [ "anyhow", "heck", @@ -419,9 +484,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.17.4" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f00ad0a1bf548e61adfff15d83430941d9e1bb620e334f779edd1c745680a5" +checksum = "d80aa6ea7bba0baac79222204aa786a6293078c210abe69ef1336911d4bdc4f0" dependencies = [ "libc", "system-deps", @@ -429,9 +494,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.17.4" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e75b0000a64632b2d8ca3cf856af9308e3a970844f6e9659bd197f026793d0" +checksum = "cd34c3317740a6358ec04572c1bcfd3ac0b5b6529275fae255b237b314bb8062" dependencies = [ "glib-sys", "libc", @@ -440,9 +505,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "heck" @@ -452,20 +517,17 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "indexmap" -version = "1.9.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] @@ -502,9 +564,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.141" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" @@ -546,18 +608,18 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" dependencies = [ "cc", ] [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -565,29 +627,43 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "cfg-if", + "libc", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -596,7 +672,7 @@ version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7f0a2e93526dd9c8c522d72a4d0c88678be8966fabe9fb8f2947fde6339b682" dependencies = [ - "bitflags 2.2.1", + "bitflags 2.4.0", "ctor", "napi-derive", "napi-sys", @@ -649,20 +725,61 @@ dependencies = [ ] [[package]] -name = "num_cpus" -version = "1.15.0" +name = "nix" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] [[package]] -name = "once_cell" -version = "1.17.1" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "parking_lot" @@ -676,22 +793,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -701,9 +818,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "ppv-lite86" @@ -747,18 +864,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -795,18 +912,30 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.7.3" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -815,9 +944,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "retry" @@ -836,9 +965,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "security-framework" @@ -865,21 +994,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] [[package]] name = "serde_spanned" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] @@ -906,18 +1049,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" @@ -929,6 +1072,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "syn" version = "1.0.109" @@ -942,9 +1091,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.14" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -953,9 +1102,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.0.4" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555fc8147af6256f3931a36bb83ad0023240ce9cf2b319dec8236fd1f220b05f" +checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" dependencies = [ "cfg-expr", "heck", @@ -965,10 +1114,16 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.2.0" +name = "target-lexicon" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -990,7 +1145,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] @@ -1009,7 +1164,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1020,14 +1175,14 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] name = "toml" -version = "0.7.3" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -1037,18 +1192,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "serde", @@ -1065,9 +1220,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" @@ -1077,9 +1232,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "version-compare" @@ -1101,9 +1256,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -1123,9 +1278,18 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" dependencies = [ "winapi", ] @@ -1142,16 +1306,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", + "windows-targets", ] [[package]] @@ -1160,128 +1315,93 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.1" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" dependencies = [ "memchr", ] + +[[package]] +name = "x11rb" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" +dependencies = [ + "gethostname", + "nix", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" +dependencies = [ + "nix", +] diff --git a/apps/desktop/desktop_native/Cargo.toml b/apps/desktop/desktop_native/Cargo.toml index 15b0cb632e0..9dd36d32040 100644 --- a/apps/desktop/desktop_native/Cargo.toml +++ b/apps/desktop/desktop_native/Cargo.toml @@ -15,6 +15,7 @@ manual_test = [] [dependencies] aes = "=0.8.2" anyhow = "=1.0.71" +arboard = { version = "=3.2.1", default-features = false } base64 = "=0.21.2" cbc = { version = "=0.1.2", features = ["alloc"] } napi = { version = "=2.13.1", features = ["async"] } @@ -31,7 +32,7 @@ typenum = "=1.16.0" napi-build = "=2.0.1" [target.'cfg(windows)'.dependencies] -widestring = "=0.5.1" +widestring = "=1.0.2" windows = { version = "=0.48.0", features = [ "Foundation", "Security_Credentials_UI", diff --git a/apps/desktop/desktop_native/index.d.ts b/apps/desktop/desktop_native/index.d.ts index 573e2e49300..abfc998de04 100644 --- a/apps/desktop/desktop_native/index.d.ts +++ b/apps/desktop/desktop_native/index.d.ts @@ -37,3 +37,7 @@ export namespace biometrics { ivB64: string } } +export namespace clipboards { + export function read(): Promise + export function write(text: string, password: boolean): Promise +} diff --git a/apps/desktop/desktop_native/index.js b/apps/desktop/desktop_native/index.js index 8b48ac99402..1cf7ea9434e 100644 --- a/apps/desktop/desktop_native/index.js +++ b/apps/desktop/desktop_native/index.js @@ -206,7 +206,8 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { passwords, biometrics } = nativeBinding +const { passwords, biometrics, clipboards } = nativeBinding module.exports.passwords = passwords module.exports.biometrics = biometrics +module.exports.clipboards = clipboards diff --git a/apps/desktop/desktop_native/src/biometric/windows.rs b/apps/desktop/desktop_native/src/biometric/windows.rs index 0ed39b98e04..54abea7281c 100644 --- a/apps/desktop/desktop_native/src/biometric/windows.rs +++ b/apps/desktop/desktop_native/src/biometric/windows.rs @@ -7,8 +7,8 @@ use rand::RngCore; use retry::delay::Fixed; use sha2::{Digest, Sha256}; use windows::{ - h, core::{factory, HSTRING}, + h, Foundation::IAsyncOperation, Security::{ Credentials::{ @@ -241,7 +241,9 @@ fn set_focus(window: HWND) { impl KeyMaterial { fn digest_material(&self) -> String { match self.client_key_part_b64.as_deref() { - Some(client_key_part_b64) => format!("{}|{}", self.os_key_part_b64, client_key_part_b64), + Some(client_key_part_b64) => { + format!("{}|{}", self.os_key_part_b64, client_key_part_b64) + } None => self.os_key_part_b64.clone(), } } @@ -419,7 +421,14 @@ mod tests { let mut key_material = key_material(); key_material.client_key_part_b64 = None; let result = key_material.derive_key().unwrap(); - assert_eq!(result, [81, 100, 62, 172, 151, 119, 182, 58, 123, 38, 129, 116, 209, 253, 66, 118, 218, 237, 236, 155, 201, 234, 11, 198, 229, 171, 246, 144, 71, 188, 84, 246].into()); + assert_eq!( + result, + [ + 81, 100, 62, 172, 151, 119, 182, 58, 123, 38, 129, 116, 209, 253, 66, 118, 218, + 237, 236, 155, 201, 234, 11, 198, 229, 171, 246, 144, 71, 188, 84, 246 + ] + .into() + ); } #[test] diff --git a/apps/desktop/desktop_native/src/clipboard.rs b/apps/desktop/desktop_native/src/clipboard.rs new file mode 100644 index 00000000000..cecf2478656 --- /dev/null +++ b/apps/desktop/desktop_native/src/clipboard.rs @@ -0,0 +1,56 @@ +use anyhow::Result; +use arboard::{Clipboard, Set}; + +pub fn read() -> Result { + let mut clipboard = Clipboard::new()?; + + Ok(clipboard.get_text()?) +} + +pub fn write(text: &str, password: bool) -> Result<()> { + let mut clipboard = Clipboard::new()?; + + let set = clipboard_set(clipboard.set(), password); + + set.text(text)?; + Ok(()) +} + +// Exclude from windows clipboard history +#[cfg(target_os = "windows")] +fn clipboard_set(set: Set, password: bool) -> Set { + use arboard::SetExtWindows; + + if password { + set.exclude_from_cloud().exclude_from_history() + } else { + set + } +} + +// Wait for clipboard to be available on linux +#[cfg(target_os = "linux")] +fn clipboard_set(set: Set, _password: bool) -> Set { + use arboard::SetExtLinux; + + set.wait() +} + +#[cfg(target_os = "macos")] +fn clipboard_set(set: Set, _password: bool) -> Set { + set +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(any(feature = "manual_test", not(target_os = "linux")))] + fn test_write_read() { + let message = "Hello world!"; + + write(message, false).unwrap(); + assert_eq!(message, read().unwrap()); + } +} diff --git a/apps/desktop/desktop_native/src/lib.rs b/apps/desktop/desktop_native/src/lib.rs index fefede4f749..d00b95c47f2 100644 --- a/apps/desktop/desktop_native/src/lib.rs +++ b/apps/desktop/desktop_native/src/lib.rs @@ -2,6 +2,7 @@ extern crate napi_derive; mod biometric; +mod clipboard; mod crypto; mod error; mod password; @@ -107,3 +108,17 @@ pub mod biometrics { pub iv_b64: String, } } + +#[napi] +pub mod clipboards { + #[napi] + pub async fn read() -> napi::Result { + super::clipboard::read().map_err(|e| napi::Error::from_reason(e.to_string())) + } + + #[napi] + pub async fn write(text: String, password: bool) -> napi::Result<()> { + super::clipboard::write(&text, password) + .map_err(|e| napi::Error::from_reason(e.to_string())) + } +} diff --git a/apps/desktop/desktop_native/src/password/windows.rs b/apps/desktop/desktop_native/src/password/windows.rs index 6e644b34962..9a92ae7cc85 100644 --- a/apps/desktop/desktop_native/src/password/windows.rs +++ b/apps/desktop/desktop_native/src/password/windows.rs @@ -95,7 +95,7 @@ pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> let credential = CREDENTIALW { Flags: CRED_FLAGS(CRED_FLAGS_NONE), Type: CRED_TYPE_GENERIC, - TargetName: PWSTR(unsafe { target_name.as_mut_ptr() }), + TargetName: PWSTR(target_name.as_mut_ptr()), Comment: PWSTR::null(), LastWritten: last_written, CredentialBlobSize: credential_len, @@ -104,7 +104,7 @@ pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> AttributeCount: 0, Attributes: std::ptr::null_mut(), TargetAlias: PWSTR::null(), - UserName: PWSTR(unsafe { user_name.as_mut_ptr() }), + UserName: PWSTR(user_name.as_mut_ptr()), }; let result = unsafe { CredWriteW(&credential, 0) }; diff --git a/apps/desktop/electron-builder.json b/apps/desktop/electron-builder.json index f1768f9b03b..6f760ef2b1e 100644 --- a/apps/desktop/electron-builder.json +++ b/apps/desktop/electron-builder.json @@ -19,7 +19,7 @@ "**/node_modules/@bitwarden/desktop-native/index.js", "**/node_modules/@bitwarden/desktop-native/desktop_native.${platform}-${arch}*.node" ], - "electronVersion": "24.8.3", + "electronVersion": "24.8.5", "generateUpdatesFilesForAllChannels": true, "publish": { "provider": "generic", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 719e680dd22..444753e9206 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/desktop", "description": "A secure and free password manager for all of your devices.", - "version": "2023.9.1", + "version": "2023.9.2", "keywords": [ "bitwarden", "password", @@ -18,7 +18,7 @@ "scripts": { "postinstall": "electron-rebuild", "start": "cross-env ELECTRON_IS_DEV=0 ELECTRON_NO_UPDATER=1 electron ./build", - "build-native": "cargo build --manifest-path=./desktop_native/Cargo.toml", + "build-native": "cd desktop_native && npm run build", "build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"", "build:dev": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main:dev\" \"npm run build:renderer:dev\"", "build:main": "cross-env NODE_ENV=production webpack --config webpack.main.js", diff --git a/apps/desktop/src/app/tools/generator.component.html b/apps/desktop/src/app/tools/generator.component.html index 93d82d4d949..1b2ee9df42e 100644 --- a/apps/desktop/src/app/tools/generator.component.html +++ b/apps/desktop/src/app/tools/generator.component.html @@ -405,7 +405,7 @@ />
- +
+
+ + +
@@ -451,7 +461,7 @@ />
- + (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/apps/desktop/src/platform/main/clipboard.main.ts b/apps/desktop/src/platform/main/clipboard.main.ts new file mode 100644 index 00000000000..c60932b33ba --- /dev/null +++ b/apps/desktop/src/platform/main/clipboard.main.ts @@ -0,0 +1,17 @@ +import { ipcMain } from "electron"; + +import { clipboards } from "@bitwarden/desktop-native"; + +import { ClipboardWriteMessage } from "../types/clipboard"; + +export class ClipboardMain { + init() { + ipcMain.handle("clipboard.read", async (_event: any, _message: any) => { + return await clipboards.read(); + }); + + ipcMain.handle("clipboard.write", async (_event: any, message: ClipboardWriteMessage) => { + return await clipboards.write(message.text, message.password ?? false); + }); + } +} diff --git a/apps/desktop/src/platform/services/electron-platform-utils.service.ts b/apps/desktop/src/platform/services/electron-platform-utils.service.ts index 6f4f55b4f4b..dbc35de9311 100644 --- a/apps/desktop/src/platform/services/electron-platform-utils.service.ts +++ b/apps/desktop/src/platform/services/electron-platform-utils.service.ts @@ -1,12 +1,16 @@ -import { clipboard, ipcRenderer, shell } from "electron"; +import { ipcRenderer, shell } from "electron"; import { ClientType, DeviceType } from "@bitwarden/common/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { + ClipboardOptions, + PlatformUtilsService, +} from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { BiometricMessage, BiometricStorageAction } from "../../types/biometric-message"; import { isDev, isMacAppStore } from "../../utils"; +import { ClipboardWriteMessage } from "../types/clipboard"; export class ElectronPlatformUtilsService implements PlatformUtilsService { private deviceCache: DeviceType = null; @@ -117,24 +121,26 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService { return false; } - copyToClipboard(text: string, options?: any): void { - const type = options ? options.type : null; - const clearing = options ? !!options.clearing : false; - const clearMs: number = options && options.clearMs ? options.clearMs : null; - clipboard.writeText(text, type); + copyToClipboard(text: string, options?: ClipboardOptions): void { + const clearing = options?.clearing === true; + const clearMs = options?.clearMs ?? null; + + ipcRenderer.invoke("clipboard.write", { + text: text, + password: (options?.allowHistory ?? false) === false, // default to false + } satisfies ClipboardWriteMessage); + if (!clearing) { this.messagingService.send("copiedToClipboard", { clipboardValue: text, clearMs: clearMs, - type: type, clearing: clearing, }); } } - readFromClipboard(options?: any): Promise { - const type = options ? options.type : null; - return Promise.resolve(clipboard.readText(type)); + readFromClipboard(): Promise { + return ipcRenderer.invoke("clipboard.read"); } async supportsBiometric(): Promise { diff --git a/apps/desktop/src/platform/types/clipboard.ts b/apps/desktop/src/platform/types/clipboard.ts new file mode 100644 index 00000000000..6317c32be40 --- /dev/null +++ b/apps/desktop/src/platform/types/clipboard.ts @@ -0,0 +1,4 @@ +export type ClipboardWriteMessage = { + text: string; + password?: boolean; +}; diff --git a/apps/desktop/src/services/encrypted-message-handler.service.ts b/apps/desktop/src/services/encrypted-message-handler.service.ts index 1889bfc7451..1ce52cfecc0 100644 --- a/apps/desktop/src/services/encrypted-message-handler.service.ts +++ b/apps/desktop/src/services/encrypted-message-handler.service.ts @@ -190,7 +190,9 @@ export class EncryptedMessageHandlerService { if (cipher === null) { return { status: "failure" }; } - const cipherView = await cipher.decrypt(); + const cipherView = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); cipherView.name = credentialUpdatePayload.name; cipherView.login.password = credentialUpdatePayload.password; cipherView.login.username = credentialUpdatePayload.userName; diff --git a/apps/desktop/src/services/native-messaging.service.ts b/apps/desktop/src/services/native-messaging.service.ts index c18a67e6b43..bb92beca782 100644 --- a/apps/desktop/src/services/native-messaging.service.ts +++ b/apps/desktop/src/services/native-messaging.service.ts @@ -116,6 +116,7 @@ export class NativeMessagingService { switch (message.command) { case "biometricUnlock": { + // eslint-disable-next-line @typescript-eslint/no-misused-promises if (!this.platformUtilService.supportsBiometric()) { return this.send({ command: "biometricUnlock", response: "not supported" }, appId); } diff --git a/apps/web/.eslintrc.json b/apps/web/.eslintrc.json index 69dae5e732f..459c7a0b622 100644 --- a/apps/web/.eslintrc.json +++ b/apps/web/.eslintrc.json @@ -13,7 +13,8 @@ "**/organizations/settings/*", "**/organizations/policies/*", "@bitwarden/web-vault/*", - "src/**/*" + "src/**/*", + "bitwarden_license" ], "paths": ["@fluffy-spoon/substitute"] } diff --git a/apps/web/config/base.json b/apps/web/config/base.json index ed0bc0a850d..a377298c637 100644 --- a/apps/web/config/base.json +++ b/apps/web/config/base.json @@ -12,6 +12,7 @@ }, "flags": { "secretsManager": false, - "showPasswordless": false + "showPasswordless": false, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/cloud.json b/apps/web/config/cloud.json index 45269d18c63..6e5c65af1d3 100644 --- a/apps/web/config/cloud.json +++ b/apps/web/config/cloud.json @@ -18,6 +18,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/development.json b/apps/web/config/development.json index 7aeffe55d0d..e3107f8788b 100644 --- a/apps/web/config/development.json +++ b/apps/web/config/development.json @@ -11,6 +11,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/euprd.json b/apps/web/config/euprd.json index 19864cdab66..4b6c9fa9098 100644 --- a/apps/web/config/euprd.json +++ b/apps/web/config/euprd.json @@ -12,6 +12,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/qa.json b/apps/web/config/qa.json index 6f514079010..be9911cc578 100644 --- a/apps/web/config/qa.json +++ b/apps/web/config/qa.json @@ -12,6 +12,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/selfhosted.json b/apps/web/config/selfhosted.json index 8ffbc0f9e5a..6b290baa6b5 100644 --- a/apps/web/config/selfhosted.json +++ b/apps/web/config/selfhosted.json @@ -8,6 +8,7 @@ }, "flags": { "secretsManager": false, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/package.json b/apps/web/package.json index ef42fafd79a..37c95cc6dcd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/web-vault", - "version": "2023.9.1", + "version": "2023.9.2", "scripts": { "build:oss": "webpack", "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", diff --git a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html index 4116f56de79..6d41249d6e1 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html +++ b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html @@ -19,13 +19,12 @@ {{ "resetPasswordLoggedOutWarning" | i18n : loggedOutWarningName }} - - +
diff --git a/apps/web/src/app/admin-console/organizations/members/members.module.ts b/apps/web/src/app/admin-console/organizations/members/members.module.ts index 71f5692a119..083fe354ff1 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.module.ts +++ b/apps/web/src/app/admin-console/organizations/members/members.module.ts @@ -1,5 +1,7 @@ import { NgModule } from "@angular/core"; +import { PasswordCalloutComponent } from "@bitwarden/auth"; + import { LooseComponentsModule } from "../../../shared"; import { SharedOrganizationModule } from "../shared"; @@ -19,6 +21,7 @@ import { PeopleComponent } from "./people.component"; LooseComponentsModule, MembersRoutingModule, UserDialogModule, + PasswordCalloutComponent, ], declarations: [ BulkConfirmComponent, diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html index f8d07581f42..613e2a7a922 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html @@ -1,52 +1,19 @@ - +
+ + {{ "enrollAccountRecovery" | i18n }} +
+ + {{ "resetPasswordEnrollmentWarning" | i18n }} + + +
+ + + + +
+
diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts index 535d7d375ab..8e2b5c70523 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts @@ -1,7 +1,7 @@ -import { Component } from "@angular/core"; +import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog"; +import { Component, Inject } from "@angular/core"; +import { FormControl, FormGroup, Validators } from "@angular/forms"; -import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; -import { ModalConfig } from "@bitwarden/angular/services/modal.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/abstractions/organization-user/requests"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; @@ -14,71 +14,83 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Verification } from "@bitwarden/common/types/verification"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; +import { DialogService } from "@bitwarden/components"; + +interface EnrollMasterPasswordResetData { + organization: Organization; +} @Component({ selector: "app-enroll-master-password-reset", templateUrl: "enroll-master-password-reset.component.html", }) export class EnrollMasterPasswordReset { - organization: Organization; + protected organization: Organization; - verification: Verification; - formPromise: Promise; + protected formGroup = new FormGroup({ + verification: new FormControl(null, Validators.required), + }); constructor( + private dialogRef: DialogRef, + @Inject(DIALOG_DATA) protected data: EnrollMasterPasswordResetData, private userVerificationService: UserVerificationService, private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, private cryptoService: CryptoService, private syncService: SyncService, private logService: LogService, - private modalRef: ModalRef, - config: ModalConfig, private organizationApiService: OrganizationApiServiceAbstraction, private organizationUserService: OrganizationUserService ) { - this.organization = config.data.organization; + this.organization = data.organization; } - async submit() { + submit = async () => { let toastStringRef = "withdrawPasswordResetSuccess"; - this.formPromise = this.userVerificationService - .buildRequest(this.verification, OrganizationUserResetPasswordEnrollmentRequest) - .then(async (request) => { - // Set variables - let keyString: string = null; - - // Retrieve Public Key - const orgKeys = await this.organizationApiService.getKeys(this.organization.id); - if (orgKeys == null) { - throw new Error(this.i18nService.t("resetPasswordOrgKeysError")); - } - - const publicKey = Utils.fromB64ToArray(orgKeys.publicKey); - - // RSA Encrypt user's encKey.key with organization public key - const userKey = await this.cryptoService.getUserKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); - keyString = encryptedKey.encryptedString; - toastStringRef = "enrollPasswordResetSuccess"; - - // Create request and execute enrollment - request.resetPasswordKey = keyString; - await this.organizationUserService.putOrganizationUserResetPasswordEnrollment( - this.organization.id, - this.organization.userId, - request - ); - - await this.syncService.fullSync(true); - }); try { - await this.formPromise; + await this.userVerificationService + .buildRequest( + this.formGroup.value.verification, + OrganizationUserResetPasswordEnrollmentRequest + ) + .then(async (request) => { + // Set variables + let keyString: string = null; + + // Retrieve Public Key + const orgKeys = await this.organizationApiService.getKeys(this.organization.id); + if (orgKeys == null) { + throw new Error(this.i18nService.t("resetPasswordOrgKeysError")); + } + + const publicKey = Utils.fromB64ToArray(orgKeys.publicKey); + + // RSA Encrypt user's encKey.key with organization public key + const userKey = await this.cryptoService.getUserKey(); + const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); + keyString = encryptedKey.encryptedString; + toastStringRef = "enrollPasswordResetSuccess"; + + // Create request and execute enrollment + request.resetPasswordKey = keyString; + await this.organizationUserService.putOrganizationUserResetPasswordEnrollment( + this.organization.id, + this.organization.userId, + request + ); + + await this.syncService.fullSync(true); + }); this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef)); - this.modalRef.close(); + this.dialogRef.close(); } catch (e) { this.logService.error(e); } + }; + + static open(dialogService: DialogService, data: EnrollMasterPasswordResetData) { + return dialogService.open(EnrollMasterPasswordReset, { data }); } } diff --git a/apps/web/src/app/auth/register-form/register-form.component.html b/apps/web/src/app/auth/register-form/register-form.component.html index e53c963c938..481140a7d2e 100644 --- a/apps/web/src/app/auth/register-form/register-form.component.html +++ b/apps/web/src/app/auth/register-form/register-form.component.html @@ -25,12 +25,8 @@
- - + + {{ "masterPass" | i18n }}
- - + +
diff --git a/apps/web/src/app/auth/settings/change-password.component.html b/apps/web/src/app/auth/settings/change-password.component.html index 4672207038e..37a4ad5b59a 100644 --- a/apps/web/src/app/auth/settings/change-password.component.html +++ b/apps/web/src/app/auth/settings/change-password.component.html @@ -3,12 +3,8 @@
{{ "loggedOutWarning" | i18n }} - - + +