feat: Add backup as setting #2135

This commit is contained in:
J-Jamet
2025-09-11 00:00:22 +02:00
parent 36e3b85400
commit ccd5da0962
6 changed files with 49 additions and 14 deletions

View File

@@ -68,6 +68,7 @@ import com.kunzisoft.keepass.model.AppOrigin
import com.kunzisoft.keepass.model.Passkey import com.kunzisoft.keepass.model.Passkey
import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.IOException import java.io.IOException
@@ -81,6 +82,9 @@ class PasskeyLauncherActivity : DatabaseModeActivity() {
private var mCreationParameters: PublicKeyCredentialCreationParameters? = null private var mCreationParameters: PublicKeyCredentialCreationParameters? = null
private var mPasskey: Passkey? = null private var mPasskey: Passkey? = null
private val mBackupEligibility = PreferencesUtil.isPasskeyBackupEligibilityEnable(this)
private val mBackupState = PreferencesUtil.isPasskeyBackupStateEnable(this)
private var mPasskeySelectionActivityResultLauncher: ActivityResultLauncher<Intent>? = private var mPasskeySelectionActivityResultLauncher: ActivityResultLauncher<Intent>? =
this.buildActivityResultLauncher( this.buildActivityResultLauncher(
lockDatabase = true, lockDatabase = true,
@@ -108,7 +112,9 @@ class PasskeyLauncherActivity : DatabaseModeActivity() {
usageParameters = usageParameters, usageParameters = usageParameters,
appOrigin = appOrigin appOrigin = appOrigin
), ),
passkey = passkey passkey = passkey,
backupEligibility = mBackupEligibility,
backupState = mBackupState
) )
) )
) )
@@ -141,7 +147,9 @@ class PasskeyLauncherActivity : DatabaseModeActivity() {
PendingIntentHandler.setCreateCredentialResponse( PendingIntentHandler.setCreateCredentialResponse(
intent = responseIntent, intent = responseIntent,
response = buildCreatePublicKeyCredentialResponse( response = buildCreatePublicKeyCredentialResponse(
publicKeyCredentialCreationParameters = it publicKeyCredentialCreationParameters = it,
backupEligibility = mBackupEligibility,
backupState = mBackupState
) )
) )
} }
@@ -272,7 +280,9 @@ class PasskeyLauncherActivity : DatabaseModeActivity() {
usageParameters = usageParameters, usageParameters = usageParameters,
appOrigin = appOrigin appOrigin = appOrigin
), ),
passkey = passkey passkey = passkey,
backupEligibility = mBackupEligibility,
backupState = mBackupState
) )
) )
) )

View File

@@ -472,7 +472,9 @@ object PasskeyHelper {
* by calling this method the user is always recognized as present and verified * by calling this method the user is always recognized as present and verified
*/ */
fun buildCreatePublicKeyCredentialResponse( fun buildCreatePublicKeyCredentialResponse(
publicKeyCredentialCreationParameters: PublicKeyCredentialCreationParameters publicKeyCredentialCreationParameters: PublicKeyCredentialCreationParameters,
backupEligibility: Boolean,
backupState: Boolean
): CreatePublicKeyCredentialResponse { ): CreatePublicKeyCredentialResponse {
val keyPair = publicKeyCredentialCreationParameters.signatureKey.first val keyPair = publicKeyCredentialCreationParameters.signatureKey.first
@@ -489,8 +491,8 @@ object PasskeyHelper {
) ?: mapOf<Int, Any>()), ) ?: mapOf<Int, Any>()),
userPresent = true, userPresent = true,
userVerified = true, userVerified = true,
backupEligibility = BACKUP_ELIGIBILITY, backupEligibility = backupEligibility,
backupState = false, // TODO Setting to add a backup manually #2135 backupState = backupState,
publicKeyTypeId = keyTypeId, publicKeyTypeId = keyTypeId,
publicKeyCbor = Signature.convertPublicKey(keyPair.public, keyTypeId)!!, publicKeyCbor = Signature.convertPublicKey(keyPair.public, keyTypeId)!!,
clientDataResponse = publicKeyCredentialCreationParameters.clientDataResponse clientDataResponse = publicKeyCredentialCreationParameters.clientDataResponse
@@ -559,7 +561,9 @@ object PasskeyHelper {
fun buildPasskeyPublicKeyCredential( fun buildPasskeyPublicKeyCredential(
requestOptions: PublicKeyCredentialRequestOptions, requestOptions: PublicKeyCredentialRequestOptions,
clientDataResponse: ClientDataResponse, clientDataResponse: ClientDataResponse,
passkey: Passkey passkey: Passkey,
backupEligibility: Boolean,
backupState: Boolean
): PublicKeyCredential { ): PublicKeyCredential {
val getCredentialResponse = FidoPublicKeyCredential( val getCredentialResponse = FidoPublicKeyCredential(
id = passkey.credentialId, id = passkey.credentialId,
@@ -567,8 +571,8 @@ object PasskeyHelper {
requestOptions = requestOptions, requestOptions = requestOptions,
userPresent = true, userPresent = true,
userVerified = true, userVerified = true,
backupEligibility = BACKUP_ELIGIBILITY, backupEligibility = backupEligibility,
backupState = false, // TODO Setting to add a backup manually #2135 backupState = backupState,
userHandle = passkey.userHandle, userHandle = passkey.userHandle,
privateKey = passkey.privateKeyPem, privateKey = passkey.privateKeyPem,
clientDataResponse = clientDataResponse clientDataResponse = clientDataResponse
@@ -599,6 +603,4 @@ object PasskeyHelper {
) )
} }
} }
private const val BACKUP_ELIGIBILITY = true
} }

View File

@@ -686,6 +686,18 @@ object PreferencesUtil {
context.resources.getBoolean(R.bool.keyboard_previous_lock_default)) context.resources.getBoolean(R.bool.keyboard_previous_lock_default))
} }
fun isPasskeyBackupEligibilityEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.passkeys_backup_eligibility_key),
context.resources.getBoolean(R.bool.passkeys_backup_eligibility_default))
}
fun isPasskeyBackupStateEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.passkeys_backup_state_key),
context.resources.getBoolean(R.bool.passkeys_backup_state_default))
}
fun isAutofillCloseDatabaseEnable(context: Context): Boolean { fun isAutofillCloseDatabaseEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.autofill_close_database_key), return prefs.getBoolean(context.getString(R.string.autofill_close_database_key),

View File

@@ -135,6 +135,10 @@
<string name="passkeys_explanation_key" translatable="false">passkeys_explanation_key</string> <string name="passkeys_explanation_key" translatable="false">passkeys_explanation_key</string>
<string name="settings_passkeys_key" translatable="false">settings_passkeys_key</string> <string name="settings_passkeys_key" translatable="false">settings_passkeys_key</string>
<string name="passkeys_privileged_apps_key" translatable="false">passkeys_privileged_apps_key</string> <string name="passkeys_privileged_apps_key" translatable="false">passkeys_privileged_apps_key</string>
<string name="passkeys_backup_eligibility_key" translatable="false">passkeys_backup_eligibility_key</string>
<bool name="passkeys_backup_eligibility_default" translatable="false">true</bool>
<string name="passkeys_backup_state_key" translatable="false">passkeys_backup_state_key</string>
<bool name="passkeys_backup_state_default" translatable="false">false</bool>
<string name="keyboard_notification_entry_key" translatable="false">keyboard_notification_entry_key</string> <string name="keyboard_notification_entry_key" translatable="false">keyboard_notification_entry_key</string>
<bool name="keyboard_notification_entry_default" translatable="false">true</bool> <bool name="keyboard_notification_entry_default" translatable="false">true</bool>
<string name="keyboard_notification_entry_clear_close_key" translatable="false">keyboard_notification_entry_clear_close_key</string> <string name="keyboard_notification_entry_clear_close_key" translatable="false">keyboard_notification_entry_clear_close_key</string>

View File

@@ -427,6 +427,10 @@
<string name="passkeys_privileged_apps_explanation">WARNING : A privileged app acts as a gateway to retrieve the origin of an authentication. Ensure its legitimacy to avoid security issues.</string> <string name="passkeys_privileged_apps_explanation">WARNING : A privileged app acts as a gateway to retrieve the origin of an authentication. Ensure its legitimacy to avoid security issues.</string>
<string name="passkeys_privileged_apps_ask_title">App not recognized</string> <string name="passkeys_privileged_apps_ask_title">App not recognized</string>
<string name="passkeys_privileged_apps_ask_message">%1$s attempts to perform a Passkey action.\n\nWould you like to add it to the list of privileged apps?</string> <string name="passkeys_privileged_apps_ask_message">%1$s attempts to perform a Passkey action.\n\nWould you like to add it to the list of privileged apps?</string>
<string name="passkeys_backup_eligibility_title">Backup Eligibility</string>
<string name="passkeys_backup_eligibility_summary">Determine at creation time whether the public key credential source is allowed to be backed up</string>
<string name="passkeys_backup_state_title">Backup State</string>
<string name="passkeys_backup_state_summary">Indicate that credentials are backed up and protected against the loss of a single device</string>
<string name="autofill">Autofill</string> <string name="autofill">Autofill</string>
<string name="credential_provider_service_subtitle">Passkeys, Autofill credential provider</string> <string name="credential_provider_service_subtitle">Passkeys, Autofill credential provider</string>
<string name="autofill_sign_in_prompt">Sign in with KeePassDX</string> <string name="autofill_sign_in_prompt">Sign in with KeePassDX</string>

View File

@@ -24,14 +24,17 @@
android:key="@string/passkeys_privileged_apps_key" android:key="@string/passkeys_privileged_apps_key"
android:title="@string/passkeys_privileged_apps_title" android:title="@string/passkeys_privileged_apps_title"
android:summary="@string/passkeys_privileged_apps_summary"/> android:summary="@string/passkeys_privileged_apps_summary"/>
<!-- <SwitchPreferenceCompat
// TODO Backup state #2135 android:key="@string/passkeys_backup_eligibility_key"
android:title="@string/passkeys_backup_eligibility_title"
android:summary="@string/passkeys_backup_eligibility_summary"
android:defaultValue="@bool/passkeys_backup_eligibility_default"/>
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="@string/passkeys_backup_state_key" android:key="@string/passkeys_backup_state_key"
android:dependency="@string/passkeys_backup_eligibility_key"
android:title="@string/passkeys_backup_state_title" android:title="@string/passkeys_backup_state_title"
android:summary="@string/passkeys_backup_state_summary" android:summary="@string/passkeys_backup_state_summary"
android:defaultValue="@bool/passkeys_backup_state_default"/> android:defaultValue="@bool/passkeys_backup_state_default"/>
-->
</PreferenceCategory> </PreferenceCategory>
<!-- <!--
// TODO Passkeys default group #2123 // TODO Passkeys default group #2123