Add vaultstore generic instance for sharing main app and autofill component (#846)

This commit is contained in:
Leendert de Borst
2025-05-26 11:41:01 +02:00
parent b99025c48a
commit 29c52c844f
3 changed files with 70 additions and 9 deletions

View File

@@ -22,9 +22,9 @@ class NativeVaultManager(reactContext: ReactApplicationContext) :
const val NAME = "NativeVaultManager"
}
private val vaultStore = VaultStore(
AndroidStorageProvider(reactContext),
private val vaultStore = VaultStore.getInstance(
AndroidKeystoreProvider(reactContext) { getFragmentActivity() },
AndroidStorageProvider(reactContext)
)
init {

View File

@@ -44,6 +44,11 @@ class VaultStore(
fun onError(e: Exception)
}
interface CredentialOperationCallback {
fun onSuccess(result: List<Credential>)
fun onError(e: Exception)
}
fun storeEncryptionKey(base64EncryptionKey: String) {
this.encryptionKey = Base64.decode(base64EncryptionKey, Base64.NO_WRAP)
@@ -388,6 +393,35 @@ class VaultStore(
storageProvider.clearStorage()
}
/**
* Attempts to get all credentials using only the cached encryption key.
* Returns false if the key isn't in memory, which signals the caller to authenticate.
*/
fun tryGetAllCredentials(callback: CredentialOperationCallback): Boolean {
// Check if the encryption key is already in memory
if (encryptionKey == null) {
Log.d(TAG, "Encryption key not in memory, authentication required")
return false
}
try {
Log.d(TAG, "Unlocking vault and retrieving all credentials")
// Unlock vault if it's locked
if (!isVaultUnlocked()) {
unlockVault()
}
// Return all credentials
callback.onSuccess(getAllCredentials())
return true
} catch (e: Exception) {
Log.e(TAG, "Error retrieving credentials", e)
callback.onError(e)
return false
}
}
private fun decryptData(encryptedData: String): String {
var decryptedResult: String? = null
var error: Exception? = null
@@ -680,14 +714,26 @@ class VaultStore(
return null
}
return try {
val formats = listOf(
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US).apply {
timeZone = TimeZone.getTimeZone("UTC")
}.parse(dateString)
} catch (e: Exception) {
Log.e(TAG, "Error parsing date: $dateString", e)
null
},
SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US).apply {
timeZone = TimeZone.getTimeZone("UTC")
}
)
for (format in formats) {
try {
return format.parse(dateString)
} catch (e: Exception) {
// Continue to next format if this one fails
continue
}
}
Log.e(TAG, "Error parsing date: $dateString")
return null
}
fun onAppBackgrounded() {
@@ -722,5 +768,20 @@ class VaultStore(
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.time
@Volatile
private var instance: VaultStore? = null
@JvmStatic
fun getInstance(keystoreProvider: KeystoreProvider, storageProvider: StorageProvider): VaultStore {
return instance ?: synchronized(this) {
instance ?: VaultStore(storageProvider, keystoreProvider).also { instance = it }
}
}
@JvmStatic
fun getExistingInstance(): VaultStore? {
return instance
}
}
}

View File

@@ -118,10 +118,10 @@ export default function AndroidAutofillScreen() : React.ReactNode {
</TouchableOpacity>
</View>
<ThemedText style={styles.instructionStep}>
2. Navigate to &quot;Passwords, passkeys & accounts&quot; in the settings menu
2. Navigate to the &quot;Passwords and autofill&quot; section in the settings menu. Depending on your device, this option may be under &quot;General management&quot; or &quot;System Settings&quot;.
</ThemedText>
<ThemedText style={styles.instructionStep}>
3. Change the &quot;prefered service&quot; to &quot;AliasVault&quot;
3. Change the &quot;autofill preferred service&quot; to &quot;AliasVault&quot;
</ThemedText>
<ThemedText style={styles.warningText}>
Note: You&apos;ll need to authenticate with your device security method when using autofill.