mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-15 10:35:20 +01:00
Merge branch 'main' into auth/pm-7930/add-pop-out-option-to-tde
This commit is contained in:
commit
98a9b00808
@ -226,7 +226,7 @@
|
||||
"message": "Help & feedback"
|
||||
},
|
||||
"helpCenter": {
|
||||
"message": "Bitwarden Help center"
|
||||
"message": "Bitwarden Help centre"
|
||||
},
|
||||
"communityForums": {
|
||||
"message": "Explore Bitwarden community forums"
|
||||
@ -728,7 +728,7 @@
|
||||
"message": "Change the application's colour theme."
|
||||
},
|
||||
"themeDescAlt": {
|
||||
"message": "Change the application's color theme. Applies to all logged in accounts."
|
||||
"message": "Change the application's colour theme. Applies to all logged in accounts."
|
||||
},
|
||||
"dark": {
|
||||
"message": "Dark",
|
||||
@ -1165,7 +1165,7 @@
|
||||
"message": "Show a recognizable image next to each login."
|
||||
},
|
||||
"faviconDescAlt": {
|
||||
"message": "Show a recognizable image next to each login. Applies to all logged in accounts."
|
||||
"message": "Show a recognisable image next to each login. Applies to all logged in accounts."
|
||||
},
|
||||
"enableBadgeCounter": {
|
||||
"message": "Show badge counter"
|
||||
@ -1730,7 +1730,7 @@
|
||||
"message": "An organization policy is affecting your ownership options."
|
||||
},
|
||||
"personalOwnershipPolicyInEffectImports": {
|
||||
"message": "An organization policy has blocked importing items into your individual vault."
|
||||
"message": "An organisation policy has blocked importing items into your individual vault."
|
||||
},
|
||||
"excludedDomains": {
|
||||
"message": "Excluded Domains"
|
||||
@ -1990,7 +1990,7 @@
|
||||
"message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it 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."
|
||||
},
|
||||
"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": "Your master password does not meet one or more of your organisation 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."
|
||||
},
|
||||
"resetPasswordPolicyAutoEnroll": {
|
||||
"message": "Automatic Enrollment"
|
||||
@ -2006,11 +2006,11 @@
|
||||
"description": "Used as a message within the notification bar when no folders are found"
|
||||
},
|
||||
"orgPermissionsUpdatedMustSetPassword": {
|
||||
"message": "Your organization permissions were updated, requiring you to set a master password.",
|
||||
"message": "Your organisation permissions were updated, requiring you to set a master password.",
|
||||
"description": "Used as a card title description on the set password page to explain why the user is there"
|
||||
},
|
||||
"orgRequiresYouToSetPassword": {
|
||||
"message": "Your organization requires you to set a master password.",
|
||||
"message": "Your organisation requires you to set a master password.",
|
||||
"description": "Used as a card title description on the set password page to explain why the user is there"
|
||||
},
|
||||
"verificationRequired": {
|
||||
@ -2037,7 +2037,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": "Your organisation 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$.",
|
||||
"placeholders": {
|
||||
"hours": {
|
||||
"content": "$1",
|
||||
@ -2054,7 +2054,7 @@
|
||||
}
|
||||
},
|
||||
"vaultTimeoutActionPolicyInEffect": {
|
||||
"message": "Your organization policies have set your vault timeout action to $ACTION$.",
|
||||
"message": "Your organisation policies have set your vault timeout action to $ACTION$.",
|
||||
"placeholders": {
|
||||
"action": {
|
||||
"content": "$1",
|
||||
@ -2111,7 +2111,7 @@
|
||||
"message": "Exporting Personal Vault"
|
||||
},
|
||||
"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": "Only the individual vault items associated with $EMAIL$ will be exported. Organisation vault items will not be included. Only vault item information will be exported and will not include associated attachments.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
@ -2305,7 +2305,7 @@
|
||||
}
|
||||
},
|
||||
"autofillPageLoadPolicyActivated": {
|
||||
"message": "Your organization policies have turned on auto-fill on page load."
|
||||
"message": "Your organisation policies have turned on auto-fill on page load."
|
||||
},
|
||||
"howToAutofill": {
|
||||
"message": "How to auto-fill"
|
||||
@ -2377,7 +2377,7 @@
|
||||
"message": "Approve with master password"
|
||||
},
|
||||
"ssoIdentifierRequired": {
|
||||
"message": "Organization SSO identifier is required."
|
||||
"message": "Organisation SSO identifier is required."
|
||||
},
|
||||
"eu": {
|
||||
"message": "EU",
|
||||
@ -2688,7 +2688,7 @@
|
||||
"message": "Total"
|
||||
},
|
||||
"importWarning": {
|
||||
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organization. Do you want to proceed?",
|
||||
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organisation. Do you want to proceed?",
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
@ -3007,10 +3007,10 @@
|
||||
"message": "Passkey removed"
|
||||
},
|
||||
"unassignedItemsBannerNotice": {
|
||||
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console."
|
||||
"message": "Notice: Unassigned organisation items are no longer visible in the All Vaults view and only accessible via the Admin Console."
|
||||
},
|
||||
"unassignedItemsBannerSelfHostNotice": {
|
||||
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console."
|
||||
"message": "Notice: On May 16, 2024, unassigned organisation items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console."
|
||||
},
|
||||
"unassignedItemsBannerCTAPartOne": {
|
||||
"message": "Assign these items to a collection from the",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"message": "Bitwarden"
|
||||
},
|
||||
"extName": {
|
||||
"message": "Bitwarden Password Manager",
|
||||
"message": "Bitwarden - Administrador de contraseñas",
|
||||
"description": "Extension name, MUST be less than 40 characters (Safari restriction)"
|
||||
},
|
||||
"extDesc": {
|
||||
@ -2962,27 +2962,27 @@
|
||||
"description": "Label indicating the most common import formats"
|
||||
},
|
||||
"overrideDefaultBrowserAutofillTitle": {
|
||||
"message": "¿Quiere hacer de Bitwarden su gestor de contraseñas predeterminado?",
|
||||
"message": "¿Hacer de Bitwarden su administrador de contraseñas predeterminado?",
|
||||
"description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior"
|
||||
},
|
||||
"overrideDefaultBrowserAutofillDescription": {
|
||||
"message": "Pasar por alto esta opción puede causar conflictos entre el menú de relleno automático de Bitwarden y el del navegador.",
|
||||
"message": "Pasar por alto esta opción puede causar conflictos entre el menú de autocompletar de Bitwarden y el de tu navegador.",
|
||||
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
|
||||
},
|
||||
"overrideDefaultBrowserAutoFillSettings": {
|
||||
"message": "Hacer de Bitwarden su gestor de contraseñas predeterminado",
|
||||
"message": "Hacer de Bitwarden tu administrador de contraseñas predeterminado",
|
||||
"description": "Label for the setting that allows overriding the default browser autofill settings"
|
||||
},
|
||||
"privacyPermissionAdditionNotGrantedTitle": {
|
||||
"message": "No se pudo establecer Bitwarden como el gestor de contraseñas predeterminado",
|
||||
"message": "No se puede establecer Bitwarden como el administrador de contraseñas predeterminado",
|
||||
"description": "Title for the dialog that appears when the user has not granted the extension permission to set privacy settings"
|
||||
},
|
||||
"privacyPermissionAdditionNotGrantedDescription": {
|
||||
"message": "Debe otorgar los permisos de privacidad del navegador a Bitwarden para establecerlo como gestor de contraseñas predeterminado.",
|
||||
"message": "Debes otorgar permisos de privacidad del navegador a Bitwarden para establecerlo como administrador de contraseñas predeterminado.",
|
||||
"description": "Description for the dialog that appears when the user has not granted the extension permission to set privacy settings"
|
||||
},
|
||||
"makeDefault": {
|
||||
"message": "Predeterminar",
|
||||
"message": "Establecer como predeterminado",
|
||||
"description": "Button text for the setting that allows overriding the default browser autofill settings"
|
||||
},
|
||||
"saveCipherAttemptSuccess": {
|
||||
@ -2998,7 +2998,7 @@
|
||||
"description": "Notification message for when saving credentials has failed."
|
||||
},
|
||||
"success": {
|
||||
"message": "Success"
|
||||
"message": "Éxito"
|
||||
},
|
||||
"removePasskey": {
|
||||
"message": "Eliminar passkey"
|
||||
@ -3013,20 +3013,20 @@
|
||||
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console."
|
||||
},
|
||||
"unassignedItemsBannerCTAPartOne": {
|
||||
"message": "Assign these items to a collection from the",
|
||||
"message": "Asignar estos elementos a una colección de",
|
||||
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
|
||||
},
|
||||
"unassignedItemsBannerCTAPartTwo": {
|
||||
"message": "to make them visible.",
|
||||
"message": "para hcerlos visibles.",
|
||||
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
|
||||
},
|
||||
"adminConsole": {
|
||||
"message": "Admin Console"
|
||||
"message": "Consola de administrador"
|
||||
},
|
||||
"errorAssigningTargetCollection": {
|
||||
"message": "Error assigning target collection."
|
||||
"message": "Error al asignar la colección de destino."
|
||||
},
|
||||
"errorAssigningTargetFolder": {
|
||||
"message": "Error assigning target folder."
|
||||
"message": "Error al asignar la carpeta de destino."
|
||||
}
|
||||
}
|
||||
|
@ -173,10 +173,10 @@
|
||||
"message": "Keisti pagrindinį slaptažodį"
|
||||
},
|
||||
"continueToWebApp": {
|
||||
"message": "Continue to web app?"
|
||||
"message": "Tęsti į žiniatinklio programėlę?"
|
||||
},
|
||||
"changeMasterPasswordOnWebConfirmation": {
|
||||
"message": "You can change your master password on the Bitwarden web app."
|
||||
"message": "Pagrindinį slaptažodį galite pakeisti „Bitwarden“ žiniatinklio programėlėje."
|
||||
},
|
||||
"fingerprintPhrase": {
|
||||
"message": "Pirštų atspaudų frazė",
|
||||
@ -2998,7 +2998,7 @@
|
||||
"description": "Notification message for when saving credentials has failed."
|
||||
},
|
||||
"success": {
|
||||
"message": "Success"
|
||||
"message": "Sėkmė"
|
||||
},
|
||||
"removePasskey": {
|
||||
"message": "Pašalinti slaptaraktį"
|
||||
@ -3007,26 +3007,26 @@
|
||||
"message": "Pašalintas slaptaraktis"
|
||||
},
|
||||
"unassignedItemsBannerNotice": {
|
||||
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console."
|
||||
"message": "Pranešimas: nepriskirti organizacijos elementai nebėra matomi peržiūros rodinyje Visi saugyklos ir yra pasiekiami tik per Administratoriaus konsolę."
|
||||
},
|
||||
"unassignedItemsBannerSelfHostNotice": {
|
||||
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console."
|
||||
"message": "Pranešimas: 2024 m. gegužės 16 d. nepriskirti organizacijos elementai nebėra matomi peržiūros rodinyje Visi saugyklos ir yra pasiekiami tik per Administratoriaus konsolę."
|
||||
},
|
||||
"unassignedItemsBannerCTAPartOne": {
|
||||
"message": "Assign these items to a collection from the",
|
||||
"message": "Priskirkite šiuos elementus kolekcijai iš",
|
||||
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
|
||||
},
|
||||
"unassignedItemsBannerCTAPartTwo": {
|
||||
"message": "to make them visible.",
|
||||
"message": ", kad jie būtų matomi.",
|
||||
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
|
||||
},
|
||||
"adminConsole": {
|
||||
"message": "Admin Console"
|
||||
"message": "Administratoriaus konsolės"
|
||||
},
|
||||
"errorAssigningTargetCollection": {
|
||||
"message": "Error assigning target collection."
|
||||
"message": "Klaida priskiriant tikslinę kolekciją."
|
||||
},
|
||||
"errorAssigningTargetFolder": {
|
||||
"message": "Error assigning target folder."
|
||||
"message": "Klaida priskiriant tikslinį aplanką."
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
KeyGenerationServiceInitOptions,
|
||||
keyGenerationServiceFactory,
|
||||
} from "../../../platform/background/service-factories/key-generation-service.factory";
|
||||
import { logServiceFactory } from "../../../platform/background/service-factories/log-service.factory";
|
||||
import {
|
||||
PlatformUtilsServiceInitOptions,
|
||||
platformUtilsServiceFactory,
|
||||
@ -88,6 +89,7 @@ export function deviceTrustServiceFactory(
|
||||
await stateProviderFactory(cache, opts),
|
||||
await secureStorageServiceFactory(cache, opts),
|
||||
await userDecryptionOptionsServiceFactory(cache, opts),
|
||||
await logServiceFactory(cache, opts),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -631,6 +631,7 @@ export default class MainBackground {
|
||||
this.stateProvider,
|
||||
this.secureStorageService,
|
||||
this.userDecryptionOptionsService,
|
||||
this.logService,
|
||||
);
|
||||
|
||||
this.devicesService = new DevicesServiceImplementation(this.devicesApiService);
|
||||
|
@ -124,7 +124,7 @@
|
||||
<value>At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.</value>
|
||||
</data>
|
||||
<data name="Description" xml:space="preserve">
|
||||
<value>Recognized as the best password manager by PCMag, WIRED, The Verge, CNET, G2, and more!
|
||||
<value>Recognised as the best password manager by PCMag, WIRED, The Verge, CNET, G2, and more!
|
||||
|
||||
SECURE YOUR DIGITAL LIFE
|
||||
Secure your digital life and protect against data breaches by generating and saving unique, strong passwords for every account. Maintain everything in an end-to-end encrypted password vault that only you can access.
|
||||
@ -146,7 +146,7 @@ More reasons to choose Bitwarden:
|
||||
World-Class Encryption
|
||||
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
|
||||
|
||||
3rd-party Audits
|
||||
3rd-Party Audits
|
||||
Bitwarden regularly conducts comprehensive third-party security audits with notable security firms. These annual audits include source code assessments and penetration testing across Bitwarden IPs, servers, and web applications.
|
||||
|
||||
Advanced 2FA
|
||||
@ -159,13 +159,13 @@ Built-in Generator
|
||||
Create long, complex, and distinct passwords and unique usernames for every site you visit. Integrate with email alias providers for additional privacy.
|
||||
|
||||
Global Translations
|
||||
Bitwarden translations exist for more than 60 languages, translated by the global community though Crowdin.
|
||||
Bitwarden translations exist for more than 60 languages, translated by the global community through Crowdin.
|
||||
|
||||
Cross-Platform Applications
|
||||
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
|
||||
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, desktop OS, and more.
|
||||
|
||||
Bitwarden secures more than just passwords
|
||||
End-to-end encrypted credential management solutions from Bitwarden empower organizations to secure everything, including developer secrets and passkey experiences. Visit Bitwarden.com to learn more about Bitwarden Secrets Manager and Bitwarden Passwordless.dev!
|
||||
End-to-end encrypted credential management solutions from Bitwarden empower organisations to secure everything, including developer secrets and passkey experiences. Visit Bitwarden.com to learn more about Bitwarden Secrets Manager and Bitwarden Passwordless.dev!
|
||||
</value>
|
||||
</data>
|
||||
<data name="AssetTitle" xml:space="preserve">
|
||||
|
@ -133,7 +133,7 @@ ACCESS YOUR DATA, ANYWHERE, ANYTIME, ON ANY DEVICE
|
||||
Easily manage, store, secure, and share unlimited passwords across unlimited devices without restrictions.
|
||||
|
||||
EVERYONE SHOULD HAVE THE TOOLS TO STAY SAFE ONLINE
|
||||
Utilize Bitwarden for free with no ads or selling data. Bitwarden believes everyone should have the ability to stay safe online. Premium plans offer access to advanced features.
|
||||
Utilise Bitwarden for free with no ads or selling data. Bitwarden believes everyone should have the ability to stay safe online. Premium plans offer access to advanced features.
|
||||
|
||||
EMPOWER YOUR TEAMS WITH BITWARDEN
|
||||
Plans for Teams and Enterprise come with professional business features. Some examples include SSO integration, self-hosting, directory integration and SCIM provisioning, global policies, API access, event logs, and more.
|
||||
@ -165,7 +165,7 @@ Cross-Platform Applications
|
||||
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
|
||||
|
||||
Bitwarden secures more than just passwords
|
||||
End-to-end encrypted credential management solutions from Bitwarden empower organizations to secure everything, including developer secrets and passkey experiences. Visit Bitwarden.com to learn more about Bitwarden Secrets Manager and Bitwarden Passwordless.dev!
|
||||
End-to-end encrypted credential management solutions from Bitwarden empower organisations to secure everything, including developer secrets and passkey experiences. Visit Bitwarden.com to learn more about Bitwarden Secrets Manager and Bitwarden Passwordless.dev!
|
||||
</value>
|
||||
</data>
|
||||
<data name="AssetTitle" xml:space="preserve">
|
||||
|
@ -118,10 +118,10 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Bitwarden Password Manager</value>
|
||||
<value>Bitwarden - Administrador de contraseñas</value>
|
||||
</data>
|
||||
<data name="Summary" xml:space="preserve">
|
||||
<value>At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.</value>
|
||||
<value>En casa, en el trabajo o en el viaje, Bitwarden asegura fácilmente todas sus contraseñas, claves de acceso e información confidencial.</value>
|
||||
</data>
|
||||
<data name="Description" xml:space="preserve">
|
||||
<value>Recognized as the best password manager by PCMag, WIRED, The Verge, CNET, G2, and more!
|
||||
@ -169,7 +169,7 @@ End-to-end encrypted credential management solutions from Bitwarden empower orga
|
||||
</value>
|
||||
</data>
|
||||
<data name="AssetTitle" xml:space="preserve">
|
||||
<value>At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.</value>
|
||||
<value>En casa, en el trabajo o mientras viaja, Bitwarden protege fácilmente todas sus contraseñas, claves de acceso e información confidencial.</value>
|
||||
</data>
|
||||
<data name="ScreenshotSync" xml:space="preserve">
|
||||
<value>Sincroniza y accede a tu caja fuerte desde múltiples dispositivos</value>
|
||||
|
@ -165,7 +165,7 @@ Aplicações multiplataforma
|
||||
Proteja e partilhe dados confidenciais dentro do seu cofre Bitwarden a partir de qualquer navegador, dispositivo móvel, ou SO de computador, e muito mais.
|
||||
|
||||
O Bitwarden protege mais do que apenas palavras-passe
|
||||
As soluções de gestão de credenciais encriptadas ponto a ponto do Bitwarden permitem que as organizações protejam tudo, incluindo segredos de programadores e experiências com chaves de acesso. Visite Bitwarden.com para saber mais sobre o Gestor de Segredos do Bitwarden e o Bitwarden Passwordless.dev!
|
||||
As soluções de gestão de credenciais encriptadas ponto a ponto do Bitwarden permitem que as organizações protejam tudo, incluindo segredos de programadores e experiências com chaves de acesso. Visite Bitwarden.com para saber mais sobre o Bitwarden - Gestor de Segredos e o Bitwarden Passwordless.dev!
|
||||
</value>
|
||||
</data>
|
||||
<data name="AssetTitle" xml:space="preserve">
|
||||
|
@ -486,6 +486,7 @@ export class Main {
|
||||
this.stateProvider,
|
||||
this.secureStorageService,
|
||||
this.userDecryptionOptionsService,
|
||||
this.logService,
|
||||
);
|
||||
|
||||
this.authRequestService = new AuthRequestService(
|
||||
|
@ -1549,11 +1549,11 @@
|
||||
"message": "Set master password"
|
||||
},
|
||||
"orgPermissionsUpdatedMustSetPassword": {
|
||||
"message": "Your organization permissions were updated, requiring you to set a master password.",
|
||||
"message": "Your organisation permissions were updated, requiring you to set a master password.",
|
||||
"description": "Used as a card title description on the set password page to explain why the user is there"
|
||||
},
|
||||
"orgRequiresYouToSetPassword": {
|
||||
"message": "Your organization requires you to set a master password.",
|
||||
"message": "Your organisation requires you to set a master password.",
|
||||
"description": "Used as a card title description on the set password page to explain why the user is there"
|
||||
},
|
||||
"verificationRequired": {
|
||||
@ -1699,7 +1699,7 @@
|
||||
"message": "An organisation policy is affecting your ownership options."
|
||||
},
|
||||
"personalOwnershipPolicyInEffectImports": {
|
||||
"message": "An organization policy has blocked importing items into your individual vault."
|
||||
"message": "An organisation policy has blocked importing items into your individual vault."
|
||||
},
|
||||
"allSends": {
|
||||
"message": "All Sends",
|
||||
@ -1895,7 +1895,7 @@
|
||||
"message": "Your master password was recently changed by an administrator in your organisation. In order to access the vault, you must update it 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."
|
||||
},
|
||||
"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": "Your master password does not meet one or more of your organisation 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."
|
||||
},
|
||||
"tryAgain": {
|
||||
"message": "Try again"
|
||||
@ -1953,7 +1953,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": "Your organisation 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$.",
|
||||
"placeholders": {
|
||||
"hours": {
|
||||
"content": "$1",
|
||||
@ -1970,7 +1970,7 @@
|
||||
}
|
||||
},
|
||||
"vaultTimeoutActionPolicyInEffect": {
|
||||
"message": "Your organization policies have set your vault timeout action to $ACTION$.",
|
||||
"message": "Your organisation policies have set your vault timeout action to $ACTION$.",
|
||||
"placeholders": {
|
||||
"action": {
|
||||
"content": "$1",
|
||||
@ -2060,7 +2060,7 @@
|
||||
"message": "Exporting individual vault"
|
||||
},
|
||||
"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": "Only the individual vault items associated with $EMAIL$ will be exported. Organisation vault items will not be included. Only vault item information will be exported and will not include associated attachments.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
@ -2346,7 +2346,7 @@
|
||||
"message": "Region"
|
||||
},
|
||||
"ssoIdentifierRequired": {
|
||||
"message": "Organization SSO identifier is required."
|
||||
"message": "Organisation SSO identifier is required."
|
||||
},
|
||||
"eu": {
|
||||
"message": "EU",
|
||||
@ -2532,7 +2532,7 @@
|
||||
"message": "Total"
|
||||
},
|
||||
"importWarning": {
|
||||
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organization. Do you want to proceed?",
|
||||
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organisation. Do you want to proceed?",
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
|
@ -1549,11 +1549,11 @@
|
||||
"message": "Set master password"
|
||||
},
|
||||
"orgPermissionsUpdatedMustSetPassword": {
|
||||
"message": "Your organization permissions were updated, requiring you to set a master password.",
|
||||
"message": "Your organisation permissions were updated, requiring you to set a master password.",
|
||||
"description": "Used as a card title description on the set password page to explain why the user is there"
|
||||
},
|
||||
"orgRequiresYouToSetPassword": {
|
||||
"message": "Your organization requires you to set a master password.",
|
||||
"message": "Your organisation requires you to set a master password.",
|
||||
"description": "Used as a card title description on the set password page to explain why the user is there"
|
||||
},
|
||||
"verificationRequired": {
|
||||
@ -1699,7 +1699,7 @@
|
||||
"message": "An organization policy is affecting your ownership options."
|
||||
},
|
||||
"personalOwnershipPolicyInEffectImports": {
|
||||
"message": "An organization policy has blocked importing items into your individual vault."
|
||||
"message": "An organisation policy has blocked importing items into your individual vault."
|
||||
},
|
||||
"allSends": {
|
||||
"message": "All Sends",
|
||||
@ -1895,7 +1895,7 @@
|
||||
"message": "Your master password was recently changed by an administrator in your organization. In order to access the vault, you must update it 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."
|
||||
},
|
||||
"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": "Your master password does not meet one or more of your organisation 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."
|
||||
},
|
||||
"tryAgain": {
|
||||
"message": "Try again"
|
||||
@ -1953,7 +1953,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": "Your organisation 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$.",
|
||||
"placeholders": {
|
||||
"hours": {
|
||||
"content": "$1",
|
||||
@ -1970,7 +1970,7 @@
|
||||
}
|
||||
},
|
||||
"vaultTimeoutActionPolicyInEffect": {
|
||||
"message": "Your organization policies have set your vault timeout action to $ACTION$.",
|
||||
"message": "Your organisation policies have set your vault timeout action to $ACTION$.",
|
||||
"placeholders": {
|
||||
"action": {
|
||||
"content": "$1",
|
||||
@ -2060,7 +2060,7 @@
|
||||
"message": "Exporting individual vault"
|
||||
},
|
||||
"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": "Only the individual vault items associated with $EMAIL$ will be exported. Organisation vault items will not be included. Only vault item information will be exported and will not include associated attachments.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
@ -2346,7 +2346,7 @@
|
||||
"message": "Region"
|
||||
},
|
||||
"ssoIdentifierRequired": {
|
||||
"message": "Organization SSO identifier is required."
|
||||
"message": "Organisation SSO identifier is required."
|
||||
},
|
||||
"eu": {
|
||||
"message": "EU",
|
||||
@ -2532,7 +2532,7 @@
|
||||
"message": "Total"
|
||||
},
|
||||
"importWarning": {
|
||||
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organization. Do you want to proceed?",
|
||||
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organisation. Do you want to proceed?",
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { concatMap, takeUntil, map } from "rxjs";
|
||||
import { concatMap, takeUntil, map, lastValueFrom } from "rxjs";
|
||||
import { tap } from "rxjs/operators";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
@ -8,12 +8,15 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorDuoComponent } from "../../../auth/settings/two-factor-duo.component";
|
||||
import { TwoFactorSetupComponent as BaseTwoFactorSetupComponent } from "../../../auth/settings/two-factor-setup.component";
|
||||
import { TwoFactorVerifyComponent } from "../../../auth/settings/two-factor-verify.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-two-factor-setup",
|
||||
@ -63,9 +66,18 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent {
|
||||
async manage(type: TwoFactorProviderType) {
|
||||
switch (type) {
|
||||
case TwoFactorProviderType.OrganizationDuo: {
|
||||
const twoFactorVerifyDialogRef = TwoFactorVerifyComponent.open(this.dialogService, {
|
||||
data: { type: type, organizationId: this.organizationId },
|
||||
});
|
||||
const result: AuthResponse<TwoFactorDuoResponse> = await lastValueFrom(
|
||||
twoFactorVerifyDialogRef.closed,
|
||||
);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
const duoComp = await this.openModal(this.duoModalRef, TwoFactorDuoComponent);
|
||||
duoComp.type = TwoFactorProviderType.OrganizationDuo;
|
||||
duoComp.organizationId = this.organizationId;
|
||||
duoComp.auth(result);
|
||||
duoComp.onUpdated.pipe(takeUntil(this.destroy$)).subscribe((enabled: boolean) => {
|
||||
this.updateStatus(enabled, TwoFactorProviderType.OrganizationDuo);
|
||||
});
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "$ID$ silinməzdən əvvəl bütün müştəriləri (client) ayırmalısınız",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Трябва да разкачите всички клиенти, преди да можете да изтриете $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Трябва да разкачите всички клиенти, преди да можете да изтриете $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Heu de desenllaçar tots els clients abans de poder suprimir $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Před smazáním $ID$ musíte odpojit všechny klienty",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Před smazáním $ID$ musíte odpojit všechny klienty.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Alle klienttilknytninger skal fjernes, før $ID$ kan slettes",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Alle klienttilknytninger skal fjernes, før $ID$ kan slettes.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -6481,7 +6481,7 @@
|
||||
"message": "Gewähre Zugriff auf Sammlungen, indem du diese zu dieser Gruppe hinzufügst."
|
||||
},
|
||||
"editGroupCollectionsRestrictionsDesc": {
|
||||
"message": "You can only assign collections you manage."
|
||||
"message": "Du kannst nur von dir verwaltete Sammlungen zuweisen."
|
||||
},
|
||||
"accessAllCollectionsDesc": {
|
||||
"message": "Gewähre Zugriff auf alle aktuellen und zukünftigen Sammlungen."
|
||||
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Du musst die Verknüpfung zu allen Kunden aufheben, bevor du $ID$ löschen kannst",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -579,7 +579,7 @@
|
||||
"message": "Acceso"
|
||||
},
|
||||
"accessLevel": {
|
||||
"message": "Access level"
|
||||
"message": "Nivel de acceso"
|
||||
},
|
||||
"loggedOut": {
|
||||
"message": "Sesión terminada"
|
||||
@ -1359,11 +1359,11 @@
|
||||
"description": "This will be part of a larger sentence, that will read like this: If you don't have any data to import, you can create a new item instead. (Optional second half: You may need to wait until your administrator confirms your organization membership.)"
|
||||
},
|
||||
"onboardingImportDataDetailsPartTwoNoOrgs": {
|
||||
"message": " instead.",
|
||||
"message": " en su lugar.",
|
||||
"description": "This will be part of a larger sentence, that will read like this: If you don't have any data to import, you can create a new item instead."
|
||||
},
|
||||
"onboardingImportDataDetailsPartTwoWithOrgs": {
|
||||
"message": " instead. You may need to wait until your administrator confirms your organization membership.",
|
||||
"message": " en su lugar. Es posible que tenga que esperar hasta que su administrador confirme la pertenencia a su organización.",
|
||||
"description": "This will be part of a larger sentence, that will read like this: If you don't have any data to import, you can create a new item instead. You may need to wait until your administrator confirms your organization membership."
|
||||
},
|
||||
"importError": {
|
||||
@ -1810,7 +1810,7 @@
|
||||
"message": "Sitios web no seguros encontrados"
|
||||
},
|
||||
"unsecuredWebsitesFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ with unsecured URIs. You should change their URI scheme to https:// if the website allows it.",
|
||||
"message": "Hemos encontrado $COUNT$ elementos en su $VAULT$ con URIs no seguros. Deberías cambiar su esquema URI a https:// si el sitio web lo permite.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1835,7 +1835,7 @@
|
||||
"message": "Inicios de sesión sin 2FA encontrados"
|
||||
},
|
||||
"inactive2faFoundReportDesc": {
|
||||
"message": "We found $COUNT$ website(s) in your $VAULT$ that may not be configured with two-step login (according to 2fa.directory). To further protect these accounts, you should set up two-step login.",
|
||||
"message": "Hemos encontrado $COUNT$ sitio(s) web en su $VAULT$ que pueden no estar configurados con inicio de sesión en dos pasos (según 2fa.directory). Para proteger aún más estas cuentas, debe configurar el inicio de sesión en dos pasos.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1863,7 +1863,7 @@
|
||||
"message": "Contraseñas comprometidas encontradas"
|
||||
},
|
||||
"exposedPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ that have passwords that were exposed in known data breaches. You should change them to use a new password.",
|
||||
"message": "Hemos encontrado $COUNT$ elementos en su $VAULT$ que tienen contraseñas que fueron expuestas en violaciones de datos conocidas. Deberías cambiarlas para utilizar una contraseña nueva.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1900,7 +1900,7 @@
|
||||
"message": "Contraseñas débiles encontradas"
|
||||
},
|
||||
"weakPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ with passwords that are not strong. You should update them to use stronger passwords.",
|
||||
"message": "Hemos encontrado $COUNT$ elementos en su $VAULT$ con contraseñas que no son seguras. Debe actualizarlos para utilizar contraseñas más seguras.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1925,7 +1925,7 @@
|
||||
"message": "Contraseñas reutilizadas encontradas"
|
||||
},
|
||||
"reusedPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ passwords that are being reused in your $VAULT$. You should change them to a unique value.",
|
||||
"message": "Hemos encontrado $COUNT$ contraseñas que están siendo reutilizadas en tu $VAULT$. Deberías cambiarlas por un valor único.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -4971,13 +4971,13 @@
|
||||
"message": "Cree una nueva organización de clientes que estará asociada a usted como proveedor. Usted poddrá acceder y gestionar esta organización."
|
||||
},
|
||||
"newClient": {
|
||||
"message": "New client"
|
||||
"message": "Nuevo cliente"
|
||||
},
|
||||
"addExistingOrganization": {
|
||||
"message": "Añadir una organización existente"
|
||||
},
|
||||
"addNewOrganization": {
|
||||
"message": "Add new organization"
|
||||
"message": "Añadir nueva organización"
|
||||
},
|
||||
"myProvider": {
|
||||
"message": "Mi proveedor"
|
||||
@ -5233,7 +5233,7 @@
|
||||
"message": "Set a unique SP entity ID"
|
||||
},
|
||||
"spUniqueEntityIdDesc": {
|
||||
"message": "Generate an identifier that is unique to your organization"
|
||||
"message": "Genera un identificador único para su organización"
|
||||
},
|
||||
"idpEntityId": {
|
||||
"message": "ID de la entidad"
|
||||
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -1810,7 +1810,7 @@
|
||||
"message": "Suojaamattomia verkkosivustoja löytyi"
|
||||
},
|
||||
"unsecuredWebsitesFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ with unsecured URIs. You should change their URI scheme to https:// if the website allows it.",
|
||||
"message": "Löysimme holv(e)istasi $COUNT$ kohdetta suojaamattomilla URI-osoitteilla. Nämä tulisi muuttaa suojattuun \"https://\" -muotoon, jos sivustot sen mahdollistavat.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1835,7 +1835,7 @@
|
||||
"message": "Löytyi kirjautumistietoja, joille ei ole määritetty kaksivaiheista kirjautumista"
|
||||
},
|
||||
"inactive2faFoundReportDesc": {
|
||||
"message": "We found $COUNT$ website(s) in your $VAULT$ that may not be configured with two-step login (according to 2fa.directory). To further protect these accounts, you should set up two-step login.",
|
||||
"message": "Löysimme holv(e)istasi $COUNT$ sivustoa, joita ei ehkä ole määritetty käyttämään kaksivaiheista tunnistautumista (2fa.directory-sivuston mukaan). Nämä tilit tulisi suojata paremmin määrittämällä niille kaksivaiheinen tunnistautuminen.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1863,7 +1863,7 @@
|
||||
"message": "Paljastuneita salasanoja löytyi"
|
||||
},
|
||||
"exposedPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ that have passwords that were exposed in known data breaches. You should change them to use a new password.",
|
||||
"message": "Löysimme holv(e)istasi $COUNT$ kohdetta, joiden salasanat ovat paljastuneet tunnetuissa tietovuodoissa. Nämä salasanat tulisi vaihtaa.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1900,7 +1900,7 @@
|
||||
"message": "Heikkoja salasanoja löytyi"
|
||||
},
|
||||
"weakPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ with passwords that are not strong. You should update them to use stronger passwords.",
|
||||
"message": "Löysimme holv(e)istasi $COUNT$ kohdetta, joiden salasanat eivät ole vahvoja. Nämä tulisi korvata vahvemmilla salasanoilla.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -1925,7 +1925,7 @@
|
||||
"message": "Toistuvia salasanoja löytyi"
|
||||
},
|
||||
"reusedPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ passwords that are being reused in your $VAULT$. You should change them to a unique value.",
|
||||
"message": "Löysimme holv(e)istasi $COUNT$ toistuvasti käytettyä salasanaa. Ne tulisi korvata yksilöllisillä salasanoilla.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -6481,7 +6481,7 @@
|
||||
"message": "Myönnä käyttöoikeudet kokoelmiin lisäämällä heidät tähän ryhmään."
|
||||
},
|
||||
"editGroupCollectionsRestrictionsDesc": {
|
||||
"message": "You can only assign collections you manage."
|
||||
"message": "Voit määrittää vain hallitsemiasi kokoelmia."
|
||||
},
|
||||
"accessAllCollectionsDesc": {
|
||||
"message": "Myönnä käyttöoikeudet kaikkiin nykyisiin ja tuleviin kokoelmiin"
|
||||
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Kaikki liitetyt asiakkaat on poistettava ennen toimittajan $ID$ poistoa.",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
@ -8074,6 +8074,6 @@
|
||||
"message": "Valitse kokoelman kohde"
|
||||
},
|
||||
"manageBillingFromProviderPortalMessage": {
|
||||
"message": "Manage billing from the Provider Portal"
|
||||
"message": "Hallitse laskutusta Toimittajaportaaliista"
|
||||
}
|
||||
}
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Vous devez dissocier tous les clients avant de pouvoir supprimer $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "$ID$ törlése előtt le kell választani az összes klienst.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -1863,7 +1863,7 @@
|
||||
"message": "Password esposte trovate"
|
||||
},
|
||||
"exposedPasswordsFoundReportDesc": {
|
||||
"message": "We found $COUNT$ items in your $VAULT$ that have passwords that were exposed in known data breaches. You should change them to use a new password.",
|
||||
"message": "Abbiamo trovato $COUNT$ elementi nella tua cassaforte che hanno password che sono state esposte a violazioni di dati note. Dovresti cambiarli per usare una nuova password.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Devi scollegare tutti i client prima di poter eliminare $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Devi scollegare tutti i client prima di poter eliminare $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "$ID$ を削除する前に、すべてのクライアントのリンクを解除してください",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "$ID$ を削除するには、まずすべてのクライアントのリンクを解除してください。",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Ir jāatsaista visi klienti, pirms var izdzēst $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Je moet alle clients ontkoppelen voordat je $ID$ kunt verwijderen",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Je moet alle clients ontkoppelen voordat je $ID$ kunt verwijderen.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Musisz odłączyć wszystkich klientów zanim będziesz mógł usunąć $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Musisz odłączyć wszystkich klientów zanim będziesz mógł usunąć $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Você deve desvincular todos os clientes antes de excluir $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -1288,7 +1288,7 @@
|
||||
"message": "Definições da chave de encriptação alteradas"
|
||||
},
|
||||
"dangerZone": {
|
||||
"message": "Zona de perigo"
|
||||
"message": "Zona de risco"
|
||||
},
|
||||
"dangerZoneDesc": {
|
||||
"message": "Cuidado, estas ações são irreversíveis!"
|
||||
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "É necessário desvincular todos os clientes antes de poder eliminar $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "É necessário desvincular todos os clientes antes de poder eliminar $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Перед удалением $ID$ необходимо отвязать всех клиентов",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Перед удалением $ID$ необходимо отвязать всех клиентов.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Pred tým než budete môcť odstrániť $ID$, musíte odpojiť všetkých klientov",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Морате прекинути везу са свим клијентима да бисте могли да избришете $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "Перш ніж видалити $ID$, ви повинні від'єднати всіх клієнтів",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "Перш ніж видалити $ID$, ви повинні від'єднати всіх клієнтів.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -579,7 +579,7 @@
|
||||
"message": "Quyền truy cập"
|
||||
},
|
||||
"accessLevel": {
|
||||
"message": "Access level"
|
||||
"message": "Cấp độ truy cập"
|
||||
},
|
||||
"loggedOut": {
|
||||
"message": "Đã đăng xuất"
|
||||
@ -609,7 +609,7 @@
|
||||
"message": "Đăng nhập bằng thiết bị"
|
||||
},
|
||||
"loginWithDeviceEnabledNote": {
|
||||
"message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?"
|
||||
"message": "Đăng nhập bằng thiết bị phải được thiết lập trong cài đặt của ứng dụng Bitwarden. Dùng cách khác?"
|
||||
},
|
||||
"loginWithMasterPassword": {
|
||||
"message": "Đăng nhập bằng mật khẩu chính"
|
||||
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -7961,7 +7961,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "删除 $ID$ 之前,您必须取消链接所有的客户端。",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
@ -7996,7 +7996,7 @@
|
||||
"message": "集成"
|
||||
},
|
||||
"integrationsDesc": {
|
||||
"message": "通过 Bitwarden 机密管理器将机密自动同步到第三方服务。"
|
||||
"message": "自动将机密从 Bitwarden 机密管理器同步到第三方服务。"
|
||||
},
|
||||
"sdks": {
|
||||
"message": "SDK"
|
||||
|
@ -7961,8 +7961,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteProviderWarningDesc": {
|
||||
"message": "You must unlink all clients before you can delete $ID$",
|
||||
"deleteProviderWarningDescription": {
|
||||
"message": "You must unlink all clients before you can delete $ID$.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
|
@ -81,8 +81,9 @@ export class AccountComponent {
|
||||
if (providerClients.data != null && providerClients.data.length > 0) {
|
||||
await this.dialogService.openSimpleDialog({
|
||||
title: { key: "deleteProviderName", placeholders: [this.provider.name] },
|
||||
content: { key: "deleteProviderWarningDesc", placeholders: [this.provider.name] },
|
||||
content: { key: "deleteProviderWarningDescription", placeholders: [this.provider.name] },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: { key: "close" },
|
||||
type: "danger",
|
||||
});
|
||||
|
||||
|
@ -272,6 +272,7 @@ export class BaseLoginDecryptionOptionsComponent implements OnInit, OnDestroy {
|
||||
|
||||
// this.loading to support clients without async-actions-support
|
||||
this.loading = true;
|
||||
// errors must be caught in child components to prevent navigation
|
||||
try {
|
||||
const { publicKey, privateKey } = await this.cryptoService.initAccount();
|
||||
const keysRequest = new KeysRequest(publicKey, privateKey.encryptedString);
|
||||
@ -288,8 +289,6 @@ export class BaseLoginDecryptionOptionsComponent implements OnInit, OnDestroy {
|
||||
if (this.rememberDeviceForm.value.rememberDevice) {
|
||||
await this.deviceTrustService.trustDevice(this.activeAccountId);
|
||||
}
|
||||
} catch (error) {
|
||||
this.validationService.showError(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
|
||||
await this.userDecryptionOptionsService.setUserDecryptionOptions(userDecryptionOpts);
|
||||
await this.kdfConfigService.setKdfConfig(this.userId, this.kdfConfig);
|
||||
await this.masterPasswordService.setMasterKey(masterKey, this.userId);
|
||||
await this.cryptoService.setUserKey(userKey[0]);
|
||||
await this.cryptoService.setUserKey(userKey[0], this.userId);
|
||||
|
||||
// Set private key only for new JIT provisioned users in MP encryption orgs
|
||||
// Existing TDE users will have private key set on sync or on login
|
||||
@ -253,7 +253,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
|
||||
this.forceSetPasswordReason !=
|
||||
ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission
|
||||
) {
|
||||
await this.cryptoService.setPrivateKey(keyPair[1].encryptedString);
|
||||
await this.cryptoService.setPrivateKey(keyPair[1].encryptedString, this.userId);
|
||||
}
|
||||
|
||||
const localMasterKeyHash = await this.cryptoService.hashMasterKey(
|
||||
|
@ -967,6 +967,7 @@ const safeProviders: SafeProvider[] = [
|
||||
StateProvider,
|
||||
SECURE_STORAGE,
|
||||
UserDecryptionOptionsServiceAbstraction,
|
||||
LogService,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
|
@ -140,7 +140,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
expect(cryptoService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(tokenResponse.key);
|
||||
expect(cryptoService.setUserKey).toHaveBeenCalledWith(userKey);
|
||||
expect(deviceTrustService.trustDeviceIfRequired).toHaveBeenCalled();
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, mockUserId);
|
||||
});
|
||||
|
||||
it("sets keys after a successful authentication when only userKey provided in login credentials", async () => {
|
||||
@ -164,7 +164,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
// setMasterKeyEncryptedUserKey, setUserKey, and setPrivateKey should still be called
|
||||
expect(cryptoService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(tokenResponse.key);
|
||||
expect(cryptoService.setUserKey).toHaveBeenCalledWith(decUserKey);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, mockUserId);
|
||||
|
||||
// trustDeviceIfRequired should be called
|
||||
expect(deviceTrustService.trustDeviceIfRequired).not.toHaveBeenCalled();
|
||||
|
@ -161,9 +161,13 @@ export class AuthRequestLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(response: IdentityTokenResponse): Promise<void> {
|
||||
protected override async setPrivateKey(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.cryptoService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount()),
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ export abstract class LoginStrategy {
|
||||
|
||||
await this.setMasterKey(response, userId);
|
||||
await this.setUserKey(response, userId);
|
||||
await this.setPrivateKey(response);
|
||||
await this.setPrivateKey(response, userId);
|
||||
|
||||
this.messagingService.send("loggedIn");
|
||||
|
||||
@ -262,7 +262,7 @@ export abstract class LoginStrategy {
|
||||
// The keys comes from different sources depending on the login strategy
|
||||
protected abstract setMasterKey(response: IdentityTokenResponse, userId: UserId): Promise<void>;
|
||||
protected abstract setUserKey(response: IdentityTokenResponse, userId: UserId): Promise<void>;
|
||||
protected abstract setPrivateKey(response: IdentityTokenResponse): Promise<void>;
|
||||
protected abstract setPrivateKey(response: IdentityTokenResponse, userId: UserId): Promise<void>;
|
||||
|
||||
// Old accounts used master key for encryption. We are forcing migrations but only need to
|
||||
// check on password logins
|
||||
@ -270,9 +270,10 @@ export abstract class LoginStrategy {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected async createKeyPairForOldAccount() {
|
||||
protected async createKeyPairForOldAccount(userId: UserId) {
|
||||
try {
|
||||
const [publicKey, privateKey] = await this.cryptoService.makeKeyPair();
|
||||
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(userId);
|
||||
const [publicKey, privateKey] = await this.cryptoService.makeKeyPair(userKey);
|
||||
await this.apiService.postAccountKeys(new KeysRequest(publicKey, privateKey.encryptedString));
|
||||
return privateKey.encryptedString;
|
||||
} catch (e) {
|
||||
|
@ -178,7 +178,7 @@ describe("PasswordLoginStrategy", () => {
|
||||
userId,
|
||||
);
|
||||
expect(cryptoService.setUserKey).toHaveBeenCalledWith(userKey, userId);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, userId);
|
||||
});
|
||||
|
||||
it("does not force the user to update their master password when there are no requirements", async () => {
|
||||
|
@ -233,9 +233,13 @@ export class PasswordLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(response: IdentityTokenResponse): Promise<void> {
|
||||
protected override async setPrivateKey(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.cryptoService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount()),
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -241,7 +241,7 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
if (userDecryptionOptions?.trustedDeviceOption) {
|
||||
await this.trySetUserKeyWithApprovedAdminRequestIfExists(userId);
|
||||
|
||||
const hasUserKey = await this.cryptoService.hasUserKey();
|
||||
const hasUserKey = await this.cryptoService.hasUserKey(userId);
|
||||
|
||||
// Only try to set user key with device key if admin approval request was not successful
|
||||
if (!hasUserKey) {
|
||||
@ -354,12 +354,16 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
await this.cryptoService.setUserKey(userKey);
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(tokenResponse: IdentityTokenResponse): Promise<void> {
|
||||
protected override async setPrivateKey(
|
||||
tokenResponse: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
const newSsoUser = tokenResponse.key == null;
|
||||
|
||||
if (!newSsoUser) {
|
||||
await this.cryptoService.setPrivateKey(
|
||||
tokenResponse.privateKey ?? (await this.createKeyPairForOldAccount()),
|
||||
tokenResponse.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ describe("UserApiLoginStrategy", () => {
|
||||
await apiLogInStrategy.logIn(credentials);
|
||||
|
||||
expect(cryptoService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(tokenResponse.key);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, userId);
|
||||
});
|
||||
|
||||
it("gets and sets the master key if Key Connector is enabled", async () => {
|
||||
|
@ -116,9 +116,13 @@ export class UserApiLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(response: IdentityTokenResponse): Promise<void> {
|
||||
protected override async setPrivateKey(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.cryptoService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount()),
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ describe("WebAuthnLoginStrategy", () => {
|
||||
mockPrfPrivateKey,
|
||||
);
|
||||
expect(cryptoService.setUserKey).toHaveBeenCalledWith(mockUserKey, userId);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(idTokenResponse.privateKey);
|
||||
expect(cryptoService.setPrivateKey).toHaveBeenCalledWith(idTokenResponse.privateKey, userId);
|
||||
|
||||
// Master key and private key should not be set
|
||||
expect(masterPasswordService.mock.setMasterKey).not.toHaveBeenCalled();
|
||||
|
@ -139,9 +139,13 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async setPrivateKey(response: IdentityTokenResponse): Promise<void> {
|
||||
protected override async setPrivateKey(
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.cryptoService.setPrivateKey(
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount()),
|
||||
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../platform/abstractions/encrypt.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { KeyGenerationService } from "../../platform/abstractions/key-generation.service";
|
||||
import { LogService } from "../../platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service";
|
||||
import { AbstractStorageService } from "../../platform/abstractions/storage.service";
|
||||
import { StorageLocation } from "../../platform/enums";
|
||||
@ -61,6 +62,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
private stateProvider: StateProvider,
|
||||
private secureStorageService: AbstractStorageService,
|
||||
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||
private logService: LogService,
|
||||
) {
|
||||
this.supportsDeviceTrust$ = this.userDecryptionOptionsService.userDecryptionOptions$.pipe(
|
||||
map((options) => options?.trustedDeviceOption != null ?? false),
|
||||
@ -110,7 +112,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
}
|
||||
|
||||
// Attempt to get user key
|
||||
const userKey: UserKey = await this.cryptoService.getUserKey();
|
||||
const userKey: UserKey = await this.cryptoService.getUserKey(userId);
|
||||
|
||||
// If user key is not found, throw error
|
||||
if (!userKey) {
|
||||
@ -223,19 +225,23 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
throw new Error("UserId is required. Cannot get device key.");
|
||||
}
|
||||
|
||||
if (this.platformSupportsSecureStorage) {
|
||||
const deviceKeyB64 = await this.secureStorageService.get<
|
||||
ReturnType<SymmetricCryptoKey["toJSON"]>
|
||||
>(`${userId}${this.deviceKeySecureStorageKey}`, this.getSecureStorageOptions(userId));
|
||||
try {
|
||||
if (this.platformSupportsSecureStorage) {
|
||||
const deviceKeyB64 = await this.secureStorageService.get<
|
||||
ReturnType<SymmetricCryptoKey["toJSON"]>
|
||||
>(`${userId}${this.deviceKeySecureStorageKey}`, this.getSecureStorageOptions(userId));
|
||||
|
||||
const deviceKey = SymmetricCryptoKey.fromJSON(deviceKeyB64) as DeviceKey;
|
||||
const deviceKey = SymmetricCryptoKey.fromJSON(deviceKeyB64) as DeviceKey;
|
||||
|
||||
return deviceKey;
|
||||
}
|
||||
|
||||
const deviceKey = await firstValueFrom(this.stateProvider.getUserState$(DEVICE_KEY, userId));
|
||||
|
||||
return deviceKey;
|
||||
} catch (e) {
|
||||
this.logService.error("Failed to get device key", e);
|
||||
}
|
||||
|
||||
const deviceKey = await firstValueFrom(this.stateProvider.getUserState$(DEVICE_KEY, userId));
|
||||
|
||||
return deviceKey;
|
||||
}
|
||||
|
||||
private async setDeviceKey(userId: UserId, deviceKey: DeviceKey | null): Promise<void> {
|
||||
@ -243,16 +249,20 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
throw new Error("UserId is required. Cannot set device key.");
|
||||
}
|
||||
|
||||
if (this.platformSupportsSecureStorage) {
|
||||
await this.secureStorageService.save<DeviceKey>(
|
||||
`${userId}${this.deviceKeySecureStorageKey}`,
|
||||
deviceKey,
|
||||
this.getSecureStorageOptions(userId),
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (this.platformSupportsSecureStorage) {
|
||||
await this.secureStorageService.save<DeviceKey>(
|
||||
`${userId}${this.deviceKeySecureStorageKey}`,
|
||||
deviceKey,
|
||||
this.getSecureStorageOptions(userId),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.stateProvider.setUserState(DEVICE_KEY, deviceKey?.toJSON(), userId);
|
||||
await this.stateProvider.setUserState(DEVICE_KEY, deviceKey?.toJSON(), userId);
|
||||
} catch (e) {
|
||||
this.logService.error("Failed to set device key", e);
|
||||
}
|
||||
}
|
||||
|
||||
private async makeDeviceKey(): Promise<DeviceKey> {
|
||||
@ -293,6 +303,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
|
||||
return new SymmetricCryptoKey(userKey) as UserKey;
|
||||
} catch (e) {
|
||||
// If either decryption effort fails, we want to remove the device key
|
||||
this.logService.error("Failed to decrypt using device key. Removing device key.");
|
||||
await this.setDeviceKey(userId, null);
|
||||
|
||||
return null;
|
||||
|
@ -14,6 +14,7 @@ import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../platform/abstractions/encrypt.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { KeyGenerationService } from "../../platform/abstractions/key-generation.service";
|
||||
import { LogService } from "../../platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service";
|
||||
import { AbstractStorageService } from "../../platform/abstractions/storage.service";
|
||||
import { StorageLocation } from "../../platform/enums";
|
||||
@ -48,6 +49,7 @@ describe("deviceTrustService", () => {
|
||||
const i18nService = mock<I18nService>();
|
||||
const platformUtilsService = mock<PlatformUtilsService>();
|
||||
const secureStorageService = mock<AbstractStorageService>();
|
||||
const logService = mock<LogService>();
|
||||
|
||||
const userDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
|
||||
const decryptionOptions = new BehaviorSubject<UserDecryptionOptions>(null);
|
||||
@ -726,6 +728,7 @@ describe("deviceTrustService", () => {
|
||||
stateProvider,
|
||||
secureStorageService,
|
||||
userDecryptionOptionsService,
|
||||
logService,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -155,7 +155,7 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
await this.cryptoService.setUserKey(userKey[0], userId);
|
||||
await this.cryptoService.setMasterKeyEncryptedUserKey(userKey[1].encryptedString, userId);
|
||||
|
||||
const [pubKey, privKey] = await this.cryptoService.makeKeyPair();
|
||||
const [pubKey, privKey] = await this.cryptoService.makeKeyPair(userKey[0]);
|
||||
|
||||
try {
|
||||
const keyConnectorUrl =
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { ProfileOrganizationResponse } from "../../admin-console/models/response/profile-organization.response";
|
||||
import { ProfileProviderOrganizationResponse } from "../../admin-console/models/response/profile-provider-organization.response";
|
||||
import { ProfileProviderResponse } from "../../admin-console/models/response/profile-provider.response";
|
||||
import { UserId } from "../../types/guid";
|
||||
|
||||
import { BaseResponse } from "./base.response";
|
||||
|
||||
export class ProfileResponse extends BaseResponse {
|
||||
id: string;
|
||||
id: UserId;
|
||||
name: string;
|
||||
email: string;
|
||||
emailVerified: boolean;
|
||||
|
@ -54,13 +54,23 @@ export abstract class CryptoService {
|
||||
* for encryption of data instead of the user key.
|
||||
*/
|
||||
abstract isLegacyUser(masterKey?: MasterKey, userId?: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Use for encryption/decryption of data in order to support legacy
|
||||
* encryption models. It will return the user key if available,
|
||||
* if not it will return the master key.
|
||||
*
|
||||
* @deprecated Please provide the userId of the user you want the user key for.
|
||||
*/
|
||||
abstract getUserKeyWithLegacySupport(): Promise<UserKey>;
|
||||
|
||||
/**
|
||||
* Use for encryption/decryption of data in order to support legacy
|
||||
* encryption models. It will return the user key if available,
|
||||
* if not it will return the master key.
|
||||
* @param userId The desired user
|
||||
*/
|
||||
abstract getUserKeyWithLegacySupport(userId?: string): Promise<UserKey>;
|
||||
abstract getUserKeyWithLegacySupport(userId: UserId): Promise<UserKey>;
|
||||
/**
|
||||
* Retrieves the user key from storage
|
||||
* @param keySuffix The desired version of the user's key to retrieve
|
||||
@ -169,10 +179,12 @@ export abstract class CryptoService {
|
||||
* organization keys currently in memory
|
||||
* @param orgs The organizations to set keys for
|
||||
* @param providerOrgs The provider organizations to set keys for
|
||||
* @param userId The user id of the user to set the org keys for
|
||||
*/
|
||||
abstract setOrgKeys(
|
||||
orgs: ProfileOrganizationResponse[],
|
||||
providerOrgs: ProfileProviderOrganizationResponse[],
|
||||
userId: UserId,
|
||||
): Promise<void>;
|
||||
abstract activeUserOrgKeys$: Observable<Record<OrganizationId, OrgKey>>;
|
||||
/**
|
||||
@ -200,7 +212,13 @@ export abstract class CryptoService {
|
||||
* @param providers The providers to set keys for
|
||||
*/
|
||||
abstract activeUserProviderKeys$: Observable<Record<ProviderId, ProviderKey>>;
|
||||
abstract setProviderKeys(orgs: ProfileProviderResponse[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Stores the provider keys for a given user.
|
||||
* @param orgs The provider orgs for which to save the keys from.
|
||||
* @param userId The user id of the user for which to store the keys for.
|
||||
*/
|
||||
abstract setProviderKeys(orgs: ProfileProviderResponse[], userId: UserId): Promise<void>;
|
||||
/**
|
||||
* @param providerId The desired provider
|
||||
* @returns The provider's symmetric key
|
||||
@ -228,7 +246,7 @@ export abstract class CryptoService {
|
||||
* Note: does not clear the private key if null is provided
|
||||
* @param encPrivateKey An encrypted private key
|
||||
*/
|
||||
abstract setPrivateKey(encPrivateKey: string): Promise<void>;
|
||||
abstract setPrivateKey(encPrivateKey: string, userId: UserId): Promise<void>;
|
||||
/**
|
||||
* Returns the private key from memory. If not available, decrypts it
|
||||
* from storage and stores it in memory
|
||||
@ -247,8 +265,9 @@ export abstract class CryptoService {
|
||||
* @param key A key to encrypt the private key with. If not provided,
|
||||
* defaults to the user key
|
||||
* @returns A new keypair: [publicKey in Base64, encrypted privateKey]
|
||||
* @throws If the provided key is a null-ish value.
|
||||
*/
|
||||
abstract makeKeyPair(key?: SymmetricCryptoKey): Promise<[string, EncString]>;
|
||||
abstract makeKeyPair(key: SymmetricCryptoKey): Promise<[string, EncString]>;
|
||||
/**
|
||||
* @param pin The user's pin
|
||||
* @param salt The user's salt
|
||||
|
@ -395,12 +395,11 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
|
||||
async setOrgKeys(
|
||||
orgs: ProfileOrganizationResponse[] = [],
|
||||
providerOrgs: ProfileProviderOrganizationResponse[] = [],
|
||||
orgs: ProfileOrganizationResponse[],
|
||||
providerOrgs: ProfileProviderOrganizationResponse[],
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.activeUserEncryptedOrgKeysState.update((_) => {
|
||||
await this.stateProvider.getUser(userId, USER_ENCRYPTED_ORGANIZATION_KEYS).update(() => {
|
||||
const encOrgKeyData: { [orgId: string]: EncryptedOrganizationKeyData } = {};
|
||||
|
||||
orgs.forEach((org) => {
|
||||
@ -450,8 +449,8 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
await this.stateProvider.setUserState(USER_ENCRYPTED_ORGANIZATION_KEYS, null, userId);
|
||||
}
|
||||
|
||||
async setProviderKeys(providers: ProfileProviderResponse[]): Promise<void> {
|
||||
await this.activeUserEncryptedProviderKeysState.update((_) => {
|
||||
async setProviderKeys(providers: ProfileProviderResponse[], userId: UserId): Promise<void> {
|
||||
await this.stateProvider.getUser(userId, USER_ENCRYPTED_PROVIDER_KEYS).update(() => {
|
||||
const encProviderKeys: { [providerId: ProviderId]: EncryptedString } = {};
|
||||
|
||||
providers.forEach((provider) => {
|
||||
@ -494,12 +493,14 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return [encShareKey, shareKey as T];
|
||||
}
|
||||
|
||||
async setPrivateKey(encPrivateKey: EncryptedString): Promise<void> {
|
||||
async setPrivateKey(encPrivateKey: EncryptedString, userId: UserId): Promise<void> {
|
||||
if (encPrivateKey == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.activeUserEncryptedPrivateKeyState.update(() => encPrivateKey);
|
||||
await this.stateProvider
|
||||
.getUser(userId, USER_ENCRYPTED_PRIVATE_KEY)
|
||||
.update(() => encPrivateKey);
|
||||
}
|
||||
|
||||
async getPrivateKey(): Promise<Uint8Array> {
|
||||
@ -523,9 +524,10 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
return this.hashPhrase(userFingerprint);
|
||||
}
|
||||
|
||||
async makeKeyPair(key?: SymmetricCryptoKey): Promise<[string, EncString]> {
|
||||
// Default to user key
|
||||
key ||= await this.getUserKeyWithLegacySupport();
|
||||
async makeKeyPair(key: SymmetricCryptoKey): Promise<[string, EncString]> {
|
||||
if (key == null) {
|
||||
throw new Error("'key' is a required parameter and must be non-null.");
|
||||
}
|
||||
|
||||
const keyPair = await this.cryptoFunctionService.rsaGenerateKeyPair(2048);
|
||||
const publicB64 = Utils.fromBufferToB64(keyPair[0]);
|
||||
|
@ -35,7 +35,6 @@ import { SendData } from "../../../tools/send/models/data/send.data";
|
||||
import { SendResponse } from "../../../tools/send/models/response/send.response";
|
||||
import { SendApiService } from "../../../tools/send/services/send-api.service.abstraction";
|
||||
import { InternalSendService } from "../../../tools/send/services/send.service.abstraction";
|
||||
import { UserId } from "../../../types/guid";
|
||||
import { CipherService } from "../../../vault/abstractions/cipher.service";
|
||||
import { FolderApiServiceAbstraction } from "../../../vault/abstractions/folder/folder-api.service.abstraction";
|
||||
import { InternalFolderService } from "../../../vault/abstractions/folder/folder.service.abstraction";
|
||||
@ -311,7 +310,7 @@ export class SyncService implements SyncServiceAbstraction {
|
||||
}
|
||||
|
||||
private async syncProfile(response: ProfileResponse) {
|
||||
const stamp = await this.tokenService.getSecurityStamp(response.id as UserId);
|
||||
const stamp = await this.tokenService.getSecurityStamp(response.id);
|
||||
if (stamp != null && stamp !== response.securityStamp) {
|
||||
if (this.logoutCallback != null) {
|
||||
await this.logoutCallback(true);
|
||||
@ -321,15 +320,16 @@ export class SyncService implements SyncServiceAbstraction {
|
||||
}
|
||||
|
||||
await this.cryptoService.setMasterKeyEncryptedUserKey(response.key);
|
||||
await this.cryptoService.setPrivateKey(response.privateKey);
|
||||
await this.cryptoService.setProviderKeys(response.providers);
|
||||
await this.cryptoService.setOrgKeys(response.organizations, response.providerOrganizations);
|
||||
await this.avatarService.setSyncAvatarColor(response.id as UserId, response.avatarColor);
|
||||
await this.tokenService.setSecurityStamp(response.securityStamp, response.id as UserId);
|
||||
await this.accountService.setAccountEmailVerified(
|
||||
response.id as UserId,
|
||||
response.emailVerified,
|
||||
await this.cryptoService.setPrivateKey(response.privateKey, response.id);
|
||||
await this.cryptoService.setProviderKeys(response.providers, response.id);
|
||||
await this.cryptoService.setOrgKeys(
|
||||
response.organizations,
|
||||
response.providerOrganizations,
|
||||
response.id,
|
||||
);
|
||||
await this.avatarService.setSyncAvatarColor(response.id, response.avatarColor);
|
||||
await this.tokenService.setSecurityStamp(response.securityStamp, response.id);
|
||||
await this.accountService.setAccountEmailVerified(response.id, response.emailVerified);
|
||||
|
||||
await this.billingAccountProfileStateService.setHasPremium(
|
||||
response.premiumPersonally,
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="tw-flex tw-gap-2 tw-items-center">
|
||||
<div class="tw-flex tw-gap-2 tw-items-center tw-w-full">
|
||||
<ng-content select="[slot=start]"></ng-content>
|
||||
|
||||
<div class="tw-flex tw-flex-col tw-items-start tw-text-start tw-w-full [&_p]:tw-mb-0">
|
||||
<div class="tw-text-main tw-text-base">
|
||||
<div class="tw-text-main tw-text-base tw-w-full tw-truncate">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<div class="tw-text-muted tw-text-sm">
|
||||
<div class="tw-text-muted tw-text-sm tw-w-full tw-truncate">
|
||||
<ng-content select="[slot=secondary]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
: 'tw-border-b-secondary-300 [&:has(.item-main-content_button:hover,.item-main-content_a:hover)]:tw-border-b-transparent'
|
||||
"
|
||||
>
|
||||
<bit-item-action class="item-main-content tw-block tw-w-full">
|
||||
<bit-item-action class="item-main-content tw-block tw-flex-1 tw-overflow-hidden">
|
||||
<ng-content></ng-content>
|
||||
</bit-item-action>
|
||||
|
||||
|
@ -113,11 +113,19 @@ export const TextOverflow: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: /*html*/ `
|
||||
<div class="tw-text-main tw-mb-4">TODO: Fix truncation</div>
|
||||
<bit-item>
|
||||
<bit-item-content>
|
||||
Helloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
Helloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo!
|
||||
<ng-container slot="secondary">Worlddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd!</ng-container>
|
||||
</bit-item-content>
|
||||
<ng-container slot="end">
|
||||
<bit-item-action>
|
||||
<button type="button" bitIconButton="bwi-clone"></button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
<button type="button" bitIconButton="bwi-ellipsis-v"></button>
|
||||
</bit-item-action>
|
||||
</ng-container>
|
||||
</bit-item>
|
||||
`,
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user