mirror of
https://github.com/bitwarden/android.git
synced 2026-06-08 16:17:05 -05:00
Decouple unlock and sync (#264)
This commit is contained in:
committed by
Álison Fernandes
parent
feba8595b3
commit
e8ae15ddc3
@@ -121,33 +121,40 @@ class AuthRepositoryImpl constructor(
|
||||
}
|
||||
.fold(
|
||||
onFailure = { LoginResult.Error(errorMessage = null) },
|
||||
onSuccess = {
|
||||
when (it) {
|
||||
is CaptchaRequired -> LoginResult.CaptchaRequired(it.captchaKey)
|
||||
onSuccess = { loginResponse ->
|
||||
when (loginResponse) {
|
||||
is CaptchaRequired -> LoginResult.CaptchaRequired(loginResponse.captchaKey)
|
||||
is Success -> {
|
||||
authDiskSource.userState = it
|
||||
.toUserState(
|
||||
previousUserState = authDiskSource.userState,
|
||||
environmentUrlData = environmentRepository
|
||||
.environment
|
||||
.environmentUrlData,
|
||||
)
|
||||
.also { userState ->
|
||||
authDiskSource.storeUserKey(
|
||||
userId = userState.activeUserId,
|
||||
userKey = it.key,
|
||||
)
|
||||
authDiskSource.storePrivateKey(
|
||||
userId = userState.activeUserId,
|
||||
privateKey = it.privateKey,
|
||||
)
|
||||
}
|
||||
vaultRepository.unlockVaultAndSync(masterPassword = password)
|
||||
val userStateJson = loginResponse.toUserState(
|
||||
previousUserState = authDiskSource.userState,
|
||||
environmentUrlData = environmentRepository
|
||||
.environment
|
||||
.environmentUrlData,
|
||||
)
|
||||
vaultRepository.unlockVault(
|
||||
email = userStateJson.activeAccount.profile.email,
|
||||
kdf = userStateJson.activeAccount.profile.toSdkParams(),
|
||||
userKey = loginResponse.key,
|
||||
privateKey = loginResponse.privateKey,
|
||||
// TODO use actual organization keys BIT-1091
|
||||
organizationalKeys = emptyMap(),
|
||||
masterPassword = password,
|
||||
)
|
||||
authDiskSource.userState = userStateJson
|
||||
authDiskSource.storeUserKey(
|
||||
userId = userStateJson.activeUserId,
|
||||
userKey = loginResponse.key,
|
||||
)
|
||||
authDiskSource.storePrivateKey(
|
||||
userId = userStateJson.activeUserId,
|
||||
privateKey = loginResponse.privateKey,
|
||||
)
|
||||
vaultRepository.sync()
|
||||
LoginResult.Success
|
||||
}
|
||||
|
||||
is GetTokenResponseJson.Invalid -> {
|
||||
LoginResult.Error(errorMessage = it.errorModel.errorMessage)
|
||||
LoginResult.Error(errorMessage = loginResponse.errorModel.errorMessage)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.vault.repository
|
||||
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.FolderView
|
||||
import com.bitwarden.core.Kdf
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||
@@ -46,7 +47,20 @@ interface VaultRepository {
|
||||
fun getVaultFolderStateFlow(folderId: String): StateFlow<DataState<FolderView?>>
|
||||
|
||||
/**
|
||||
* Attempt to initialize crypto and sync the vault data.
|
||||
* Attempt to unlock the vault and sync the vault data for the currently active user.
|
||||
*/
|
||||
suspend fun unlockVaultAndSync(masterPassword: String): VaultUnlockResult
|
||||
suspend fun unlockVaultAndSyncForCurrentUser(masterPassword: String): VaultUnlockResult
|
||||
|
||||
/**
|
||||
* Attempt to unlock the vault with the specified user information.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun unlockVault(
|
||||
masterPassword: String,
|
||||
email: String,
|
||||
kdf: Kdf,
|
||||
userKey: String,
|
||||
privateKey: String,
|
||||
organizationalKeys: Map<String, String>,
|
||||
): VaultUnlockResult
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.vault.repository
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.FolderView
|
||||
import com.bitwarden.core.InitCryptoRequest
|
||||
import com.bitwarden.core.Kdf
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
import com.x8bit.bitwarden.data.auth.repository.util.toSdkParams
|
||||
import com.x8bit.bitwarden.data.auth.repository.util.toUpdatedUserStateJson
|
||||
@@ -31,7 +32,6 @@ import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -146,18 +146,62 @@ class VaultRepositoryImpl constructor(
|
||||
initialValue = DataState.Loading,
|
||||
)
|
||||
|
||||
override suspend fun unlockVaultAndSync(masterPassword: String): VaultUnlockResult {
|
||||
return flow {
|
||||
willSyncAfterUnlock = true
|
||||
emit(initializeCrypto(masterPassword = masterPassword))
|
||||
}
|
||||
.onEach {
|
||||
willSyncAfterUnlock = false
|
||||
if (it is VaultUnlockResult.Success) sync()
|
||||
@Suppress("ReturnCount")
|
||||
override suspend fun unlockVaultAndSyncForCurrentUser(
|
||||
masterPassword: String,
|
||||
): VaultUnlockResult {
|
||||
val userState = authDiskSource.userState
|
||||
?: return VaultUnlockResult.InvalidStateError
|
||||
val userKey = authDiskSource.getUserKey(userId = userState.activeUserId)
|
||||
?: return VaultUnlockResult.InvalidStateError
|
||||
val privateKey = authDiskSource.getPrivateKey(userId = userState.activeUserId)
|
||||
?: return VaultUnlockResult.InvalidStateError
|
||||
return unlockVault(
|
||||
masterPassword = masterPassword,
|
||||
email = userState.activeAccount.profile.email,
|
||||
kdf = userState.activeAccount.profile.toSdkParams(),
|
||||
userKey = userKey,
|
||||
privateKey = privateKey,
|
||||
// TODO use actual organization keys BIT-1091
|
||||
organizationalKeys = emptyMap(),
|
||||
)
|
||||
.also {
|
||||
if (it is VaultUnlockResult.Success) {
|
||||
sync()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun unlockVault(
|
||||
masterPassword: String,
|
||||
email: String,
|
||||
kdf: Kdf,
|
||||
userKey: String,
|
||||
privateKey: String,
|
||||
organizationalKeys: Map<String, String>,
|
||||
): VaultUnlockResult =
|
||||
flow {
|
||||
willSyncAfterUnlock = true
|
||||
emit(
|
||||
vaultSdkSource
|
||||
.initializeCrypto(
|
||||
request = InitCryptoRequest(
|
||||
kdfParams = kdf,
|
||||
email = email,
|
||||
password = masterPassword,
|
||||
userKey = userKey,
|
||||
privateKey = privateKey,
|
||||
organizationKeys = organizationalKeys,
|
||||
),
|
||||
)
|
||||
.fold(
|
||||
onFailure = { VaultUnlockResult.GenericError },
|
||||
onSuccess = { it.toVaultUnlockResult() },
|
||||
),
|
||||
)
|
||||
}
|
||||
.onCompletion { willSyncAfterUnlock = false }
|
||||
.first()
|
||||
}
|
||||
|
||||
private fun storeUserKeyAndPrivateKey(
|
||||
userKey: String?,
|
||||
@@ -177,32 +221,6 @@ class VaultRepositoryImpl constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ReturnCount")
|
||||
private suspend fun initializeCrypto(masterPassword: String): VaultUnlockResult {
|
||||
val userState = authDiskSource.userState
|
||||
?: return VaultUnlockResult.InvalidStateError
|
||||
val userKey = authDiskSource.getUserKey(userId = userState.activeUserId)
|
||||
?: return VaultUnlockResult.InvalidStateError
|
||||
val privateKey = authDiskSource.getPrivateKey(userId = userState.activeUserId)
|
||||
?: return VaultUnlockResult.InvalidStateError
|
||||
return vaultSdkSource
|
||||
.initializeCrypto(
|
||||
request = InitCryptoRequest(
|
||||
kdfParams = userState.activeAccount.profile.toSdkParams(),
|
||||
email = userState.activeAccount.profile.email,
|
||||
password = masterPassword,
|
||||
userKey = userKey,
|
||||
privateKey = privateKey,
|
||||
// TODO use actual organization keys BIT-1091
|
||||
organizationKeys = mapOf(),
|
||||
),
|
||||
)
|
||||
.fold(
|
||||
onFailure = { VaultUnlockResult.GenericError },
|
||||
onSuccess = { it.toVaultUnlockResult() },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun decryptSendsAndUpdateSendDataState(sendList: List<SyncResponseJson.Send>?) {
|
||||
val newState = vaultSdkSource
|
||||
.decryptSendList(
|
||||
|
||||
@@ -92,7 +92,7 @@ class VaultUnlockViewModel @Inject constructor(
|
||||
private fun handleUnlockClick() {
|
||||
mutableStateFlow.update { it.copy(dialog = VaultUnlockState.VaultUnlockDialog.Loading) }
|
||||
viewModelScope.launch {
|
||||
val vaultUnlockResult = vaultRepo.unlockVaultAndSync(
|
||||
val vaultUnlockResult = vaultRepo.unlockVaultAndSyncForCurrentUser(
|
||||
mutableStateFlow.value.passwordInput,
|
||||
)
|
||||
sendAction(VaultUnlockAction.Internal.ReceiveVaultUnlockResult(vaultUnlockResult))
|
||||
|
||||
Reference in New Issue
Block a user