mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
BITAU-108 Add unlockWithAuthenticatorSyncKey to VaultRepository (#3909)
This commit is contained in:
parent
84f92f1b13
commit
cdf8b49d61
3 changed files with 116 additions and 0 deletions
|
@ -167,6 +167,18 @@ interface VaultRepository : CipherManager, VaultLockManager {
|
||||||
*/
|
*/
|
||||||
fun emitTotpCodeResult(totpCodeResult: TotpCodeResult)
|
fun emitTotpCodeResult(totpCodeResult: TotpCodeResult)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to unlock the vault using a user unlock key.
|
||||||
|
*
|
||||||
|
* @param userId ID of the user's vault to unlock.
|
||||||
|
* @param decryptedUserKey A decrypted unlock key for the user (ex: their authenticator
|
||||||
|
* sync unlock key)
|
||||||
|
*/
|
||||||
|
suspend fun unlockVaultWithDecryptedUserKey(
|
||||||
|
userId: String,
|
||||||
|
decryptedUserKey: String,
|
||||||
|
): VaultUnlockResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to unlock the vault using the stored biometric key for the currently active user.
|
* Attempt to unlock the vault using the stored biometric key for the currently active user.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -553,6 +553,16 @@ class VaultRepositoryImpl(
|
||||||
mutableTotpCodeResultFlow.tryEmit(totpCodeResult)
|
mutableTotpCodeResultFlow.tryEmit(totpCodeResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun unlockVaultWithDecryptedUserKey(
|
||||||
|
userId: String,
|
||||||
|
decryptedUserKey: String,
|
||||||
|
): VaultUnlockResult = unlockVaultForUser(
|
||||||
|
userId = userId,
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
|
||||||
|
decryptedUserKey = decryptedUserKey,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
override suspend fun unlockVaultWithBiometrics(): VaultUnlockResult {
|
override suspend fun unlockVaultWithBiometrics(): VaultUnlockResult {
|
||||||
val userId = activeUserId ?: return VaultUnlockResult.InvalidStateError
|
val userId = activeUserId ?: return VaultUnlockResult.InvalidStateError
|
||||||
val biometricsKey = authDiskSource
|
val biometricsKey = authDiskSource
|
||||||
|
|
|
@ -1243,6 +1243,100 @@ class VaultRepositoryTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
fun `unlockVaultWithDecryptedUserKey with VaultLockManager Success should return Success`() =
|
||||||
|
runTest {
|
||||||
|
val userId = MOCK_USER_STATE.activeUserId
|
||||||
|
val authenticatorSyncUnlockKey = "asdf1234"
|
||||||
|
val privateKey = "mockPrivateKey-1"
|
||||||
|
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||||
|
coEvery {
|
||||||
|
vaultLockManager.unlockVault(
|
||||||
|
userId = userId,
|
||||||
|
kdf = MOCK_PROFILE.toSdkParams(),
|
||||||
|
email = "email",
|
||||||
|
privateKey = privateKey,
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
|
||||||
|
decryptedUserKey = authenticatorSyncUnlockKey,
|
||||||
|
),
|
||||||
|
organizationKeys = null,
|
||||||
|
)
|
||||||
|
} returns VaultUnlockResult.Success
|
||||||
|
fakeAuthDiskSource.apply {
|
||||||
|
storeAuthenticatorSyncUnlockKey(
|
||||||
|
userId = userId,
|
||||||
|
authenticatorSyncUnlockKey = authenticatorSyncUnlockKey,
|
||||||
|
)
|
||||||
|
storePrivateKey(userId = userId, privateKey = privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = vaultRepository.unlockVaultWithDecryptedUserKey(
|
||||||
|
userId = userId,
|
||||||
|
decryptedUserKey = authenticatorSyncUnlockKey,
|
||||||
|
)
|
||||||
|
assertEquals(VaultUnlockResult.Success, result)
|
||||||
|
coVerify {
|
||||||
|
vaultLockManager.unlockVault(
|
||||||
|
userId = userId,
|
||||||
|
kdf = MOCK_PROFILE.toSdkParams(),
|
||||||
|
email = "email",
|
||||||
|
privateKey = "mockPrivateKey-1",
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
|
||||||
|
decryptedUserKey = authenticatorSyncUnlockKey,
|
||||||
|
),
|
||||||
|
organizationKeys = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
fun `unlockVaultWithDecryptedUserKey with VaultLockManager InvalidStateError should return InvalidStateError`() =
|
||||||
|
runTest {
|
||||||
|
val userId = MOCK_USER_STATE.activeUserId
|
||||||
|
val authenticatorSyncUnlockKey = "asdf1234"
|
||||||
|
val privateKey = "mockPrivateKey-1"
|
||||||
|
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||||
|
coEvery {
|
||||||
|
vaultLockManager.unlockVault(
|
||||||
|
userId = userId,
|
||||||
|
kdf = MOCK_PROFILE.toSdkParams(),
|
||||||
|
email = "email",
|
||||||
|
privateKey = privateKey,
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
|
||||||
|
decryptedUserKey = authenticatorSyncUnlockKey,
|
||||||
|
),
|
||||||
|
organizationKeys = null,
|
||||||
|
)
|
||||||
|
} returns VaultUnlockResult.InvalidStateError
|
||||||
|
fakeAuthDiskSource.apply {
|
||||||
|
storeAuthenticatorSyncUnlockKey(
|
||||||
|
userId = userId,
|
||||||
|
authenticatorSyncUnlockKey = authenticatorSyncUnlockKey,
|
||||||
|
)
|
||||||
|
storePrivateKey(userId = userId, privateKey = privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = vaultRepository.unlockVaultWithDecryptedUserKey(
|
||||||
|
userId = userId,
|
||||||
|
decryptedUserKey = authenticatorSyncUnlockKey,
|
||||||
|
)
|
||||||
|
assertEquals(VaultUnlockResult.InvalidStateError, result)
|
||||||
|
coVerify {
|
||||||
|
vaultLockManager.unlockVault(
|
||||||
|
userId = userId,
|
||||||
|
kdf = MOCK_PROFILE.toSdkParams(),
|
||||||
|
email = "email",
|
||||||
|
privateKey = "mockPrivateKey-1",
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
|
||||||
|
decryptedUserKey = authenticatorSyncUnlockKey,
|
||||||
|
),
|
||||||
|
organizationKeys = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `unlockVaultWithMasterPassword with missing user state should return InvalidStateError`() =
|
fun `unlockVaultWithMasterPassword with missing user state should return InvalidStateError`() =
|
||||||
runTest {
|
runTest {
|
||||||
|
|
Loading…
Reference in a new issue