mirror of
https://github.com/bitwarden/android.git
synced 2026-06-06 14:28:45 -05:00
Refactor vault unlock state to enum (#853)
This commit is contained in:
committed by
Álison Fernandes
parent
d8ee29a0a4
commit
a317174db7
@@ -144,7 +144,7 @@ class AuthRepositoryImpl(
|
||||
override val userStateFlow: StateFlow<UserState?> = combine(
|
||||
authDiskSource.userStateFlow,
|
||||
authDiskSource.userOrganizationsListFlow,
|
||||
vaultRepository.vaultStateFlow,
|
||||
vaultRepository.vaultUnlockDataStateFlow,
|
||||
mutableHasPendingAccountAdditionStateFlow,
|
||||
mutableHasPendingAccountDeletionStateFlow,
|
||||
) {
|
||||
@@ -174,7 +174,7 @@ class AuthRepositoryImpl(
|
||||
initialValue = authDiskSource
|
||||
.userState
|
||||
?.toUserState(
|
||||
vaultState = vaultRepository.vaultStateFlow.value,
|
||||
vaultState = vaultRepository.vaultUnlockDataStateFlow.value,
|
||||
userOrganizationsList = authDiskSource.userOrganizationsList,
|
||||
hasPendingAccountAddition = mutableHasPendingAccountAdditionStateFlow.value,
|
||||
isBiometricsEnabledProvider = ::isBiometricsEnabled,
|
||||
|
||||
@@ -6,7 +6,8 @@ import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.toEnvironmentUrlsOrDefault
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultState
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.statusFor
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.toHexColorRepresentation
|
||||
|
||||
/**
|
||||
@@ -44,7 +45,7 @@ fun UserStateJson.toUpdatedUserStateJson(
|
||||
* Converts the given [UserStateJson] to a [UserState] using the given [vaultState].
|
||||
*/
|
||||
fun UserStateJson.toUserState(
|
||||
vaultState: VaultState,
|
||||
vaultState: List<VaultUnlockData>,
|
||||
userOrganizationsList: List<UserOrganizations>,
|
||||
hasPendingAccountAddition: Boolean,
|
||||
isBiometricsEnabledProvider: (userId: String) -> Boolean,
|
||||
@@ -69,7 +70,8 @@ fun UserStateJson.toUserState(
|
||||
.toEnvironmentUrlsOrDefault(),
|
||||
isPremium = accountJson.profile.hasPremium == true,
|
||||
isLoggedIn = accountJson.isLoggedIn,
|
||||
isVaultUnlocked = userId in vaultState.unlockedVaultUserIds,
|
||||
isVaultUnlocked = vaultState.statusFor(userId) ==
|
||||
VaultUnlockData.Status.UNLOCKED,
|
||||
organizations = userOrganizationsList
|
||||
.find { it.userId == userId }
|
||||
?.organizations
|
||||
|
||||
@@ -7,10 +7,12 @@ import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
|
||||
import com.x8bit.bitwarden.data.platform.manager.ciphermatching.CipherMatchingManager
|
||||
import com.x8bit.bitwarden.data.platform.util.subtitle
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.statusFor
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
||||
/**
|
||||
* The default [AutofillCipherProvider] implementation. This service is used for getting currrent
|
||||
* The default [AutofillCipherProvider] implementation. This service is used for getting current
|
||||
* [AutofillCipher]s.
|
||||
*/
|
||||
class AutofillCipherProviderImpl(
|
||||
@@ -25,7 +27,9 @@ class AutofillCipherProviderImpl(
|
||||
|
||||
// Wait for any unlocking actions to finish. This can be relevant on startup for Never lock
|
||||
// accounts.
|
||||
vaultRepository.vaultStateFlow.first { userId !in it.unlockingVaultUserIds }
|
||||
vaultRepository.vaultUnlockDataStateFlow.first {
|
||||
it.statusFor(userId) != VaultUnlockData.Status.UNLOCKING
|
||||
}
|
||||
|
||||
return !vaultRepository.isVaultUnlocked(userId = userId)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.x8bit.bitwarden.data.vault.manager
|
||||
|
||||
import com.bitwarden.core.InitUserCryptoMethod
|
||||
import com.bitwarden.crypto.Kdf
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultState
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
@@ -11,9 +11,9 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
*/
|
||||
interface VaultLockManager {
|
||||
/**
|
||||
* Flow that represents the current vault state.
|
||||
* Flow that represents the current vault lock state for each user.
|
||||
*/
|
||||
val vaultStateFlow: StateFlow<VaultState>
|
||||
val vaultUnlockDataStateFlow: StateFlow<List<VaultUnlockData>>
|
||||
|
||||
/**
|
||||
* Whether or not the vault is currently locked for the given [userId].
|
||||
|
||||
@@ -20,9 +20,11 @@ import com.x8bit.bitwarden.data.platform.util.asSuccess
|
||||
import com.x8bit.bitwarden.data.platform.util.flatMap
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultState
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.statusFor
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toVaultUnlockResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.update
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -68,16 +70,11 @@ class VaultLockManagerImpl(
|
||||
private val activeUserId: String? get() = authDiskSource.userState?.activeUserId
|
||||
private val userIds: Set<String> get() = authDiskSource.userState?.accounts?.keys.orEmpty()
|
||||
|
||||
private val mutableVaultStateStateFlow =
|
||||
MutableStateFlow(
|
||||
VaultState(
|
||||
unlockedVaultUserIds = emptySet(),
|
||||
unlockingVaultUserIds = emptySet(),
|
||||
),
|
||||
)
|
||||
private val mutableVaultUnlockDataStateFlow =
|
||||
MutableStateFlow<List<VaultUnlockData>>(emptyList())
|
||||
|
||||
override val vaultStateFlow: StateFlow<VaultState>
|
||||
get() = mutableVaultStateStateFlow.asStateFlow()
|
||||
override val vaultUnlockDataStateFlow: StateFlow<List<VaultUnlockData>>
|
||||
get() = mutableVaultUnlockDataStateFlow.asStateFlow()
|
||||
|
||||
init {
|
||||
observeAppForegroundChanges()
|
||||
@@ -86,10 +83,10 @@ class VaultLockManagerImpl(
|
||||
}
|
||||
|
||||
override fun isVaultUnlocked(userId: String): Boolean =
|
||||
userId in mutableVaultStateStateFlow.value.unlockedVaultUserIds
|
||||
mutableVaultUnlockDataStateFlow.value.statusFor(userId) == VaultUnlockData.Status.UNLOCKED
|
||||
|
||||
override fun isVaultUnlocking(userId: String): Boolean =
|
||||
userId in mutableVaultStateStateFlow.value.unlockingVaultUserIds
|
||||
mutableVaultUnlockDataStateFlow.value.statusFor(userId) == VaultUnlockData.Status.UNLOCKING
|
||||
|
||||
override fun lockVault(userId: String) {
|
||||
setVaultToLocked(userId = userId)
|
||||
@@ -205,10 +202,8 @@ class VaultLockManagerImpl(
|
||||
}
|
||||
|
||||
private fun setVaultToUnlocked(userId: String) {
|
||||
mutableVaultStateStateFlow.update {
|
||||
it.copy(
|
||||
unlockedVaultUserIds = it.unlockedVaultUserIds + userId,
|
||||
)
|
||||
mutableVaultUnlockDataStateFlow.update {
|
||||
it.update(userId, VaultUnlockData.Status.UNLOCKED)
|
||||
}
|
||||
// If we are unlocking an account with a timeout of Never, we should make sure to store the
|
||||
// auto-unlock key.
|
||||
@@ -217,10 +212,8 @@ class VaultLockManagerImpl(
|
||||
|
||||
private fun setVaultToLocked(userId: String) {
|
||||
vaultSdkSource.clearCrypto(userId = userId)
|
||||
mutableVaultStateStateFlow.update {
|
||||
it.copy(
|
||||
unlockedVaultUserIds = it.unlockedVaultUserIds - userId,
|
||||
)
|
||||
mutableVaultUnlockDataStateFlow.update {
|
||||
it.update(userId, null)
|
||||
}
|
||||
authDiskSource.storeUserAutoUnlockKey(
|
||||
userId = userId,
|
||||
@@ -229,18 +222,16 @@ class VaultLockManagerImpl(
|
||||
}
|
||||
|
||||
private fun setVaultToUnlocking(userId: String) {
|
||||
mutableVaultStateStateFlow.update {
|
||||
it.copy(
|
||||
unlockingVaultUserIds = it.unlockingVaultUserIds + userId,
|
||||
)
|
||||
mutableVaultUnlockDataStateFlow.update {
|
||||
it.update(userId, VaultUnlockData.Status.UNLOCKING)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setVaultToNotUnlocking(userId: String) {
|
||||
mutableVaultStateStateFlow.update {
|
||||
it.copy(
|
||||
unlockingVaultUserIds = it.unlockingVaultUserIds - userId,
|
||||
)
|
||||
val status = mutableVaultUnlockDataStateFlow.value.statusFor(userId)
|
||||
if (status != VaultUnlockData.Status.UNLOCKING) return
|
||||
mutableVaultUnlockDataStateFlow.update {
|
||||
it.update(userId, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository.model
|
||||
|
||||
/**
|
||||
* General description of the vault across multiple users.
|
||||
*
|
||||
* @property unlockedVaultUserIds The user IDs for all users that currently have unlocked vaults.
|
||||
* @property unlockedVaultUserIds The user IDs for all users that are actively unlocking their
|
||||
* vaults.
|
||||
*/
|
||||
data class VaultState(
|
||||
val unlockedVaultUserIds: Set<String>,
|
||||
val unlockingVaultUserIds: Set<String>,
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository.model
|
||||
|
||||
/**
|
||||
* The vault state for a given user ID.
|
||||
*
|
||||
* @property userId The user ID.
|
||||
* @property status The lock status of the user's vault.
|
||||
*/
|
||||
data class VaultUnlockData(
|
||||
val userId: String,
|
||||
val status: Status,
|
||||
) {
|
||||
/**
|
||||
* The lock status of a user's vault.
|
||||
*/
|
||||
enum class Status {
|
||||
PENDING,
|
||||
UNLOCKED,
|
||||
UNLOCKING,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository.util
|
||||
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
||||
|
||||
/**
|
||||
* Get the vault unlock status for a [userId] from a list of [VaultUnlockData].
|
||||
*/
|
||||
fun List<VaultUnlockData>.statusFor(userId: String): VaultUnlockData.Status? =
|
||||
firstOrNull { it.userId == userId }?.status
|
||||
|
||||
/**
|
||||
* Update the vault unlock status for a [userId] in a list of [VaultUnlockData].
|
||||
*/
|
||||
fun List<VaultUnlockData>.update(
|
||||
userId: String,
|
||||
status: VaultUnlockData.Status?,
|
||||
): List<VaultUnlockData> {
|
||||
val updatedList = filter {
|
||||
it.userId != userId
|
||||
}
|
||||
return if (status == null) {
|
||||
updatedList
|
||||
} else {
|
||||
updatedList
|
||||
.plus(
|
||||
VaultUnlockData(
|
||||
userId = userId,
|
||||
status = status,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user