diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index 33f44c60579..0146fb2a000 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -186,7 +186,7 @@ "message": "Salin catatan" }, "copy": { - "message": "Copy", + "message": "Salin", "description": "Copy to clipboard" }, "fill": { @@ -380,7 +380,7 @@ "message": "Sunting Folder" }, "editFolderWithName": { - "message": "Edit folder: $FOLDERNAME$", + "message": "Sunting folder: $FOLDERNAME$", "placeholders": { "foldername": { "content": "$1", @@ -462,16 +462,16 @@ "message": "Buat frasa sandi" }, "passwordGenerated": { - "message": "Password generated" + "message": "Kata sandi dibuat" }, "passphraseGenerated": { - "message": "Passphrase generated" + "message": "Frasa sandi dibuat" }, "usernameGenerated": { - "message": "Username generated" + "message": "Nama pengguna dibuat" }, "emailGenerated": { - "message": "Email generated" + "message": "Surel dibuat" }, "regeneratePassword": { "message": "Buat Ulang Kata Sandi" @@ -653,7 +653,7 @@ "message": "Peramban Anda tidak mendukung menyalin clipboard dengan mudah. Salin secara manual." }, "verifyYourIdentity": { - "message": "Verify your identity" + "message": "Verifikasikan identitas Anda" }, "weDontRecognizeThisDevice": { "message": "We don't recognize this device. Enter the code sent to your email to verify your identity." @@ -905,7 +905,7 @@ "message": "Tidak" }, "location": { - "message": "Location" + "message": "Lokasi" }, "unexpectedError": { "message": "Terjadi kesalahan yang tak diduga." @@ -2461,7 +2461,7 @@ "message": "Change this in settings" }, "change": { - "message": "Change" + "message": "Ubah" }, "changeButtonTitle": { "message": "Change password - $ITEMNAME$", @@ -4784,7 +4784,7 @@ "message": "Text Sends" }, "accountActions": { - "message": "Account actions" + "message": "Tindakan akun" }, "showNumberOfAutofillSuggestions": { "message": "Show number of login autofill suggestions on extension icon" @@ -4793,22 +4793,22 @@ "message": "Show quick copy actions on Vault" }, "systemDefault": { - "message": "System default" + "message": "Baku sistem" }, "enterprisePolicyRequirementsApplied": { - "message": "Enterprise policy requirements have been applied to this setting" + "message": "Persyaratan kebijakan perusahaan telah diterapkan ke pengaturan ini" }, "sshPrivateKey": { - "message": "Private key" + "message": "Kunci privat" }, "sshPublicKey": { - "message": "Public key" + "message": "Kunci publik" }, "sshFingerprint": { - "message": "Fingerprint" + "message": "Sidik jari" }, "sshKeyAlgorithm": { - "message": "Key type" + "message": "Tipe kunci" }, "sshKeyAlgorithmED25519": { "message": "ED25519" @@ -4823,7 +4823,7 @@ "message": "RSA 4096-Bit" }, "retry": { - "message": "Retry" + "message": "Coba lagi" }, "vaultCustomTimeoutMinimum": { "message": "Minimum custom timeout is 1 minute." @@ -5075,16 +5075,16 @@ } }, "newDeviceVerificationNoticePageOneEmailAccessNo": { - "message": "No, I do not" + "message": "Tidak" }, "newDeviceVerificationNoticePageOneEmailAccessYes": { - "message": "Yes, I can reliably access my email" + "message": "Ya, saya dapat mengakses surel saya secara handla" }, "turnOnTwoStepLogin": { "message": "Turn on two-step login" }, "changeAcctEmail": { - "message": "Change account email" + "message": "Ubah surel akun" }, "extensionWidth": { "message": "Lebar ekstensi" @@ -5096,31 +5096,31 @@ "message": "Ekstra lebar" }, "sshKeyWrongPassword": { - "message": "The password you entered is incorrect." + "message": "Kata sandi yang Anda masukkan tidak benar." }, "importSshKey": { - "message": "Import" + "message": "Impor" }, "confirmSshKeyPassword": { - "message": "Confirm password" + "message": "Konfirmasi kata sandi" }, "enterSshKeyPasswordDesc": { - "message": "Enter the password for the SSH key." + "message": "Masukkan kata sandi untuk kunci SSH." }, "enterSshKeyPassword": { - "message": "Enter password" + "message": "Masukkan kata sandi" }, "invalidSshKey": { - "message": "The SSH key is invalid" + "message": "Kunci SSH tidak valid" }, "sshKeyTypeUnsupported": { - "message": "The SSH key type is not supported" + "message": "Tipe kunci SSH tidak didukung" }, "importSshKeyFromClipboard": { - "message": "Import key from clipboard" + "message": "Impor kunci dari papan klip" }, "sshKeyImported": { - "message": "SSH key imported successfully" + "message": "Kunci SSH sukses diimpor" }, "cannotRemoveViewOnlyCollections": { "message": "Anda tidak dapat menghapus koleksi dengan izin hanya lihat: $COLLECTIONS$", @@ -5132,12 +5132,12 @@ } }, "updateDesktopAppOrDisableFingerprintDialogTitle": { - "message": "Please update your desktop application" + "message": "Harap perbarui aplikasi desktop Anda" }, "updateDesktopAppOrDisableFingerprintDialogMessage": { - "message": "To use biometric unlock, please update your desktop application, or disable fingerprint unlock in the desktop settings." + "message": "Untuk memakai pembuka kunci biometrik, harap perbarui aplikasi desktop Anda, atau matikan buka kunci sidik jari dalam pengaturan desktop." }, "changeAtRiskPassword": { - "message": "Change at-risk password" + "message": "Ubah kata sandi yang berrisiko" } } diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index 65d8d6f740f..1c2b09ca3e3 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -81,7 +81,7 @@ "message": "Hoofdwachtwoordhint (optioneel)" }, "passwordStrengthScore": { - "message": "Score wachtwoordsterkte $SCORE$", + "message": "Wachtwoordsterkte score $SCORE$", "placeholders": { "score": { "content": "$1", @@ -878,10 +878,10 @@ "message": "Druk op je YubiKey om te verifiëren" }, "duoTwoFactorRequiredPageSubtitle": { - "message": "Jouw account vereist Duo-tweestapsaanmelding. Volg de onderstaande stappen om het inloggen te voltooien." + "message": "Jouw account vereist Duo tweestapslogin. Volg de onderstaande stappen om het inloggen te voltooien." }, "followTheStepsBelowToFinishLoggingIn": { - "message": "Volg de onderstaande stappen om in te loggen." + "message": "Volg de onderstaande stappen om het inloggen af te ronden." }, "restartRegistration": { "message": "Registratie herstarten" @@ -1040,7 +1040,7 @@ "message": "Klik op items om automatisch in te vullen op de kluisweergave" }, "clickToAutofill": { - "message": "Klik op gesuggereerde items om deze automatisch invullen" + "message": "Klik items in de automatisch invullen suggestie om in te vullen" }, "clearClipboard": { "message": "Klembord wissen", @@ -1075,7 +1075,7 @@ "description": "Shown to user after login is updated." }, "saveAsNewLoginAction": { - "message": "Als nieuwe login opslaan", + "message": "Opslaan als nieuwe login", "description": "Button text for saving login details as a new entry." }, "updateLoginAction": { @@ -1422,7 +1422,7 @@ "message": "Mijn gegevens onthouden" }, "dontAskAgainOnThisDeviceFor30Days": { - "message": "30 dagen niet meer vragen op dit apparaat" + "message": "30 dagen niet opnieuw vragen op dit apparaat" }, "sendVerificationCodeEmailAgain": { "message": "E-mail met verificatiecode opnieuw versturen" @@ -1459,7 +1459,7 @@ "message": "Beveiligingssleutel lezen" }, "awaitingSecurityKeyInteraction": { - "message": "Wacht op interactie met beveiligingssleutel..." + "message": "Wacht op interactie met beveiligingssleutel…" }, "loginUnavailable": { "message": "Login niet beschikbaar" @@ -1474,7 +1474,7 @@ "message": "Opties voor tweestapsaanmelding" }, "selectTwoStepLoginMethod": { - "message": "Kies methode voor tweestapsaanmelding" + "message": "Kies methode voor tweestapslogin" }, "recoveryCodeDesc": { "message": "Ben je de toegang tot al je tweestapsaanbieders verloren? Gebruik dan je herstelcode om alle tweestapsaanbieders op je account uit te schakelen." @@ -2164,7 +2164,7 @@ "description": "This will be used as part of a larger sentence, broken up to include the generator icon. The full sentence will read 'Use the generator [GENERATOR_ICON] to create a strong unique password'" }, "vaultCustomization": { - "message": "Kluis-aanpassingen" + "message": "Kluis aanpassingen" }, "vaultTimeoutAction": { "message": "Actie bij time-out" @@ -2176,10 +2176,10 @@ "message": "Nieuwe aanpassingsopties" }, "newCustomizationOptionsCalloutContent": { - "message": "Personaliseer je kluiservaring met snelle kopieeracties, compacte modus en meer!" + "message": "Pas je kluis ervaring aan met snelle kopieeracties, compacte modus en meer!" }, "newCustomizationOptionsCalloutLink": { - "message": "Alle personalisatie-instellingen bekijken" + "message": "Alle weergave-instellingen bekijken" }, "lock": { "message": "Vergrendelen", @@ -2498,7 +2498,7 @@ } }, "atRiskPasswordsDescMultiOrgPlural": { - "message": "Je organisatie(s) vragen je de $COUNT$ wachtwoorden te wijzigen omdat ze een risico vormen.", + "message": "Je organisaties vragen je de $COUNT$ wachtwoorden te wijzigen omdat ze een risico vormen.", "placeholders": { "count": { "content": "$1", @@ -2531,14 +2531,14 @@ "message": "Risicovolle wachtwoorden bekijken" }, "reviewAtRiskLoginsSlideDesc": { - "message": "De wachtwoorden van je organisatie zijn in gevaar omdat ze zwak, hergebruikt en/of blootgelegd zijn.", + "message": "De wachtwoorden van je organisatie zijn in gevaar omdat ze zwak, hergebruikt en/of gelekt zijn.", "description": "Description of the review at-risk login slide on the at-risk password page carousel" }, "reviewAtRiskLoginSlideImgAlt": { "message": "Voorbeeld van een lijst van risicovolle logins" }, "generatePasswordSlideDesc": { - "message": "Genereer snel een sterk, uniek wachtwoord met het automatisch invulmenu van Bitwaren op de risicovolle website.", + "message": "Genereer snel een sterk, uniek wachtwoord met het automatisch invulmenu van Bitwarden op de risicovolle website.", "description": "Description of the generate password slide on the at-risk password page carousel" }, "generatePasswordSlideImgAlt": { @@ -2552,7 +2552,7 @@ "description": "Description of the update in Bitwarden slide on the at-risk password page carousel" }, "updateInBitwardenSlideImgAlt": { - "message": "Voorbeeld van een Bitwarden-melding die de gebruiker aanspoort tot het bijwerken van de login" + "message": "Voorbeeld van een Bitwarden melding die de gebruiker aanspoort tot het bijwerken van de login" }, "turnOnAutofill": { "message": "Automatisch invullen inschakelen" @@ -4080,7 +4080,7 @@ "message": "Actief account" }, "bitwardenAccount": { - "message": "Bitwarden-account" + "message": "Bitwarden account" }, "availableAccounts": { "message": "Beschikbare accounts" @@ -5096,7 +5096,7 @@ "message": "Extra breed" }, "sshKeyWrongPassword": { - "message": "Het door jou ingevoerde wachtwoord is onjuist." + "message": "Het wachtwoord dat je hebt ingevoerd is onjuist." }, "importSshKey": { "message": "Importeren" @@ -5117,7 +5117,7 @@ "message": "Het type SSH-sleutel is niet ondersteund" }, "importSshKeyFromClipboard": { - "message": "Sleutel van klembord importeren" + "message": "Sleutel importeren van klembord" }, "sshKeyImported": { "message": "SSH-sleutel succesvol geïmporteerd" diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index 4595b20ddbf..bdfaeb92531 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -2208,7 +2208,7 @@ "message": "项目已恢复" }, "alreadyHaveAccount": { - "message": "已经拥有账户了吗?" + "message": "已经有账户了吗?" }, "vaultTimeoutLogOutConfirmation": { "message": "超时后注销账户将解除对密码库的所有访问权限,并需要进行在线身份验证。确定使用此设置吗?" @@ -3628,7 +3628,7 @@ "message": "正在获取选项..." }, "multiSelectNotFound": { - "message": "未找到任何条目" + "message": "未找到任何项目" }, "multiSelectClearAll": { "message": "清除全部" @@ -4209,7 +4209,7 @@ "message": "建议的项目" }, "autofillSuggestionsTip": { - "message": "将此站点保存为登录项目以用于自动填充" + "message": "为这个站点保存一个登录项目以自动填充" }, "yourVaultIsEmpty": { "message": "您的密码库是空的" diff --git a/apps/desktop/desktop_native/macos_provider/src/assertion.rs b/apps/desktop/desktop_native/macos_provider/src/assertion.rs index 762ceaaed48..c5b43bb87fa 100644 --- a/apps/desktop/desktop_native/macos_provider/src/assertion.rs +++ b/apps/desktop/desktop_native/macos_provider/src/assertion.rs @@ -2,11 +2,22 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; -use crate::{BitwardenError, Callback, UserVerification}; +use crate::{BitwardenError, Callback, Position, UserVerification}; #[derive(uniffi::Record, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PasskeyAssertionRequest { + rp_id: String, + client_data_hash: Vec, + user_verification: UserVerification, + allowed_credentials: Vec>, + window_xy: Position, + //extension_input: Vec, TODO: Implement support for extensions +} + +#[derive(uniffi::Record, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PasskeyAssertionWithoutUserInterfaceRequest { rp_id: String, credential_id: Vec, user_name: String, @@ -14,6 +25,7 @@ pub struct PasskeyAssertionRequest { record_identifier: Option, client_data_hash: Vec, user_verification: UserVerification, + window_xy: Position, } #[derive(uniffi::Record, Serialize, Deserialize)] diff --git a/apps/desktop/desktop_native/macos_provider/src/lib.rs b/apps/desktop/desktop_native/macos_provider/src/lib.rs index 5623436d874..8f2499ae68d 100644 --- a/apps/desktop/desktop_native/macos_provider/src/lib.rs +++ b/apps/desktop/desktop_native/macos_provider/src/lib.rs @@ -15,7 +15,10 @@ uniffi::setup_scaffolding!(); mod assertion; mod registration; -use assertion::{PasskeyAssertionRequest, PreparePasskeyAssertionCallback}; +use assertion::{ + PasskeyAssertionRequest, PasskeyAssertionWithoutUserInterfaceRequest, + PreparePasskeyAssertionCallback, +}; use registration::{PasskeyRegistrationRequest, PreparePasskeyRegistrationCallback}; #[derive(uniffi::Enum, Debug, Serialize, Deserialize)] @@ -26,6 +29,13 @@ pub enum UserVerification { Discouraged, } +#[derive(uniffi::Record, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Position { + pub x: i32, + pub y: i32, +} + #[derive(Debug, uniffi::Error, Serialize, Deserialize)] pub enum BitwardenError { Internal(String), @@ -141,6 +151,14 @@ impl MacOSProviderClient { ) { self.send_message(request, Box::new(callback)); } + + pub fn prepare_passkey_assertion_without_user_interface( + &self, + request: PasskeyAssertionWithoutUserInterfaceRequest, + callback: Arc, + ) { + self.send_message(request, Box::new(callback)); + } } #[derive(Serialize, Deserialize)] diff --git a/apps/desktop/desktop_native/macos_provider/src/registration.rs b/apps/desktop/desktop_native/macos_provider/src/registration.rs index d484af58b6c..9e697b75c16 100644 --- a/apps/desktop/desktop_native/macos_provider/src/registration.rs +++ b/apps/desktop/desktop_native/macos_provider/src/registration.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; -use crate::{BitwardenError, Callback, UserVerification}; +use crate::{BitwardenError, Callback, Position, UserVerification}; #[derive(uniffi::Record, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -13,6 +13,7 @@ pub struct PasskeyRegistrationRequest { client_data_hash: Vec, user_verification: UserVerification, supported_algorithms: Vec, + window_xy: Position, } #[derive(uniffi::Record, Serialize, Deserialize)] diff --git a/apps/desktop/desktop_native/napi/index.d.ts b/apps/desktop/desktop_native/napi/index.d.ts index 92f31cf5f89..ca1fe29e254 100644 --- a/apps/desktop/desktop_native/napi/index.d.ts +++ b/apps/desktop/desktop_native/napi/index.d.ts @@ -118,6 +118,10 @@ export declare namespace autofill { Required = 'required', Discouraged = 'discouraged' } + export interface Position { + x: number + y: number + } export interface PasskeyRegistrationRequest { rpId: string userName: string @@ -125,6 +129,7 @@ export declare namespace autofill { clientDataHash: Array userVerification: UserVerification supportedAlgorithms: Array + windowXy: Position } export interface PasskeyRegistrationResponse { rpId: string @@ -133,6 +138,13 @@ export declare namespace autofill { attestationObject: Array } export interface PasskeyAssertionRequest { + rpId: string + clientDataHash: Array + userVerification: UserVerification + allowedCredentials: Array> + windowXy: Position + } + export interface PasskeyAssertionWithoutUserInterfaceRequest { rpId: string credentialId: Array userName: string @@ -140,6 +152,7 @@ export declare namespace autofill { recordIdentifier?: string clientDataHash: Array userVerification: UserVerification + windowXy: Position } export interface PasskeyAssertionResponse { rpId: string @@ -156,7 +169,7 @@ export declare namespace autofill { * @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client. * @param callback This function will be called whenever a message is received from a client. */ - static listen(name: string, registrationCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyRegistrationRequest) => void, assertionCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionRequest) => void): Promise + static listen(name: string, registrationCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyRegistrationRequest) => void, assertionCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionRequest) => void, assertionWithoutUserInterfaceCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionWithoutUserInterfaceRequest) => void): Promise /** Return the path to the IPC server. */ getPath(): string /** Stop the IPC server. */ diff --git a/apps/desktop/desktop_native/napi/src/lib.rs b/apps/desktop/desktop_native/napi/src/lib.rs index d0c859d427c..f02be2b27b6 100644 --- a/apps/desktop/desktop_native/napi/src/lib.rs +++ b/apps/desktop/desktop_native/napi/src/lib.rs @@ -515,6 +515,14 @@ pub mod autofill { pub value: Result, } + #[napi(object)] + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct Position { + pub x: i32, + pub y: i32, + } + #[napi(object)] #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -525,6 +533,7 @@ pub mod autofill { pub client_data_hash: Vec, pub user_verification: UserVerification, pub supported_algorithms: Vec, + pub window_xy: Position, } #[napi(object)] @@ -541,6 +550,18 @@ pub mod autofill { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PasskeyAssertionRequest { + pub rp_id: String, + pub client_data_hash: Vec, + pub user_verification: UserVerification, + pub allowed_credentials: Vec>, + pub window_xy: Position, + //extension_input: Vec, TODO: Implement support for extensions + } + + #[napi(object)] + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct PasskeyAssertionWithoutUserInterfaceRequest { pub rp_id: String, pub credential_id: Vec, pub user_name: String, @@ -548,6 +569,7 @@ pub mod autofill { pub record_identifier: Option, pub client_data_hash: Vec, pub user_verification: UserVerification, + pub window_xy: Position, } #[napi(object)] @@ -592,6 +614,13 @@ pub mod autofill { (u32, u32, PasskeyAssertionRequest), ErrorStrategy::CalleeHandled, >, + #[napi( + ts_arg_type = "(error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionWithoutUserInterfaceRequest) => void" + )] + assertion_without_user_interface_callback: ThreadsafeFunction< + (u32, u32, PasskeyAssertionWithoutUserInterfaceRequest), + ErrorStrategy::CalleeHandled, + >, ) -> napi::Result { let (send, mut recv) = tokio::sync::mpsc::channel::(32); tokio::spawn(async move { @@ -628,6 +657,25 @@ pub mod autofill { } } + match serde_json::from_str::< + PasskeyMessage, + >(&message) + { + Ok(msg) => { + let value = msg + .value + .map(|value| (client_id, msg.sequence_number, value)) + .map_err(|e| napi::Error::from_reason(format!("{e:?}"))); + + assertion_without_user_interface_callback + .call(value, ThreadsafeFunctionCallMode::NonBlocking); + continue; + } + Err(e) => { + println!("[ERROR] Error deserializing message1: {e}"); + } + } + match serde_json::from_str::>( &message, ) { diff --git a/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib b/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib index ace3497a58b..1e47cc54de2 100644 --- a/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib +++ b/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib @@ -1,22 +1,23 @@ - + - + + - + - +