PM-11248: Add isUsingKeyConnector flag to UserState (#3798)

This commit is contained in:
David Perez 2024-08-21 14:24:34 -05:00 committed by GitHub
parent 3b3b9ef33b
commit 5761e9510a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 330 additions and 3 deletions

View file

@ -50,6 +50,11 @@ interface AuthDiskSource {
*/
fun getShouldUseKeyConnector(userId: String): Boolean?
/**
* Retrieves the state indicating that the user should use a key connector as a flow.
*/
fun getShouldUseKeyConnectorFlow(userId: String): Flow<Boolean?>
/**
* Stores the boolean indicating that the user should use a key connector.
*/

View file

@ -57,6 +57,8 @@ class AuthDiskSourceImpl(
AuthDiskSource {
private val inMemoryPinProtectedUserKeys = mutableMapOf<String, String?>()
private val mutableShouldUseKeyConnectorFlowMap =
mutableMapOf<String, MutableSharedFlow<Boolean?>>()
private val mutableOrganizationsFlowMap =
mutableMapOf<String, MutableSharedFlow<List<SyncResponseJson.Profile.Organization>?>>()
private val mutablePoliciesFlowMap =
@ -129,6 +131,10 @@ class AuthDiskSourceImpl(
// indefinitely unless the TDE flow explicitly removes them.
}
override fun getShouldUseKeyConnectorFlow(userId: String): Flow<Boolean?> =
getMutableShouldUseKeyConnectorFlowMap(userId = userId)
.onSubscription { emit(getShouldUseKeyConnector(userId = userId)) }
override fun getShouldUseKeyConnector(
userId: String,
): Boolean? = getBoolean(key = USES_KEY_CONNECTOR.appendIdentifier(userId))
@ -138,6 +144,7 @@ class AuthDiskSourceImpl(
key = USES_KEY_CONNECTOR.appendIdentifier(userId),
value = shouldUseKeyConnector,
)
getMutableShouldUseKeyConnectorFlowMap(userId = userId).tryEmit(shouldUseKeyConnector)
}
override fun getShouldTrustDevice(
@ -381,6 +388,13 @@ class AuthDiskSourceImpl(
putString(key = UNIQUE_APP_ID_KEY, value = it)
}
private fun getMutableShouldUseKeyConnectorFlowMap(
userId: String,
): MutableSharedFlow<Boolean?> =
mutableShouldUseKeyConnectorFlowMap.getOrPut(userId) {
bufferedMutableSharedFlow(replay = 1)
}
private fun getMutableOrganizationsFlow(
userId: String,
): MutableSharedFlow<List<SyncResponseJson.Profile.Organization>?> =

View file

@ -56,6 +56,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.SendVerificationEmailResul
import com.x8bit.bitwarden.data.auth.repository.model.SetPasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
@ -74,6 +75,8 @@ import com.x8bit.bitwarden.data.auth.repository.util.toUserState
import com.x8bit.bitwarden.data.auth.repository.util.toUserStateJsonWithPassword
import com.x8bit.bitwarden.data.auth.repository.util.userAccountTokens
import com.x8bit.bitwarden.data.auth.repository.util.userAccountTokensFlow
import com.x8bit.bitwarden.data.auth.repository.util.userKeyConnectorStateFlow
import com.x8bit.bitwarden.data.auth.repository.util.userKeyConnectorStateList
import com.x8bit.bitwarden.data.auth.repository.util.userOrganizationsList
import com.x8bit.bitwarden.data.auth.repository.util.userOrganizationsListFlow
import com.x8bit.bitwarden.data.auth.repository.util.userSwitchingChangesFlow
@ -238,6 +241,7 @@ class AuthRepositoryImpl(
authDiskSource.userStateFlow,
authDiskSource.userAccountTokensFlow,
authDiskSource.userOrganizationsListFlow,
authDiskSource.userKeyConnectorStateFlow,
vaultRepository.vaultUnlockDataStateFlow,
mutableHasPendingAccountAdditionStateFlow,
// Ignore the data in the merge, but trigger an update when they emit.
@ -249,12 +253,14 @@ class AuthRepositoryImpl(
val userStateJson = array[0] as UserStateJson?
val userAccountTokens = array[1] as List<UserAccountTokens>
val userOrganizationsList = array[2] as List<UserOrganizations>
val vaultState = array[3] as List<VaultUnlockData>
val hasPendingAccountAddition = array[4] as Boolean
val userIsUsingKeyConnectorList = array[3] as List<UserKeyConnectorState>
val vaultState = array[4] as List<VaultUnlockData>
val hasPendingAccountAddition = array[5] as Boolean
userStateJson?.toUserState(
vaultState = vaultState,
userAccountTokens = userAccountTokens,
userOrganizationsList = userOrganizationsList,
userIsUsingKeyConnectorList = userIsUsingKeyConnectorList,
hasPendingAccountAddition = hasPendingAccountAddition,
isBiometricsEnabledProvider = ::isBiometricsEnabled,
vaultUnlockTypeProvider = ::getVaultUnlockType,
@ -272,6 +278,7 @@ class AuthRepositoryImpl(
vaultState = vaultRepository.vaultUnlockDataStateFlow.value,
userAccountTokens = authDiskSource.userAccountTokens,
userOrganizationsList = authDiskSource.userOrganizationsList,
userIsUsingKeyConnectorList = authDiskSource.userKeyConnectorStateList,
hasPendingAccountAddition = mutableHasPendingAccountAdditionStateFlow.value,
isBiometricsEnabledProvider = ::isBiometricsEnabled,
vaultUnlockTypeProvider = ::getVaultUnlockType,

View file

@ -0,0 +1,9 @@
package com.x8bit.bitwarden.data.auth.repository.model
/**
* Associates [isUsingKeyConnector] with the given [userId].
*/
data class UserKeyConnectorState(
val userId: String,
val isUsingKeyConnector: Boolean?,
)

View file

@ -50,6 +50,7 @@ data class UserState(
* @property isBiometricsEnabled Indicates that the biometrics mechanism for unlocking the
* user's vault is enabled.
* @property vaultUnlockType The mechanism by which the user's vault may be unlocked.
* @property isUsingKeyConnector Indicates if the account is currently using a key connector.
*/
data class Account(
val userId: String,
@ -67,6 +68,7 @@ data class UserState(
val organizations: List<Organization>,
val isBiometricsEnabled: Boolean,
val vaultUnlockType: VaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
val isUsingKeyConnector: Boolean,
) {
/**
* Indicates that the user does or does not have a means to manually unlock the vault.

View file

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.repository.util
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserSwitchingData
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -100,6 +101,47 @@ val AuthDiskSource.userAccountTokensFlow: Flow<List<UserAccountTokens>>
}
.distinctUntilChanged()
/**
* Returns the current list of [UserKeyConnectorState].
*/
val AuthDiskSource.userKeyConnectorStateList: List<UserKeyConnectorState>
get() = this
.userState
?.accounts
.orEmpty()
.map { (userId, _) ->
UserKeyConnectorState(
userId = userId,
isUsingKeyConnector = this.getShouldUseKeyConnector(userId = userId),
)
}
/**
* Returns a [Flow] that emits distinct updates to [UserKeyConnectorState].
*/
@OptIn(ExperimentalCoroutinesApi::class)
val AuthDiskSource.userKeyConnectorStateFlow: Flow<List<UserKeyConnectorState>>
get() = this
.userStateFlow
.flatMapLatest { userStateJson ->
combine(
userStateJson
?.accounts
.orEmpty()
.map { (userId, _) ->
this
.getShouldUseKeyConnectorFlow(userId = userId)
.map {
UserKeyConnectorState(
userId = userId,
isUsingKeyConnector = it,
)
}
},
) { it.toList() }
}
.distinctUntilChanged()
/**
* Returns a [Flow] that emits every time the active user is changed.
*/

View file

@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.repository.util
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
@ -79,6 +80,7 @@ fun UserStateJson.toUserState(
vaultState: List<VaultUnlockData>,
userAccountTokens: List<UserAccountTokens>,
userOrganizationsList: List<UserOrganizations>,
userIsUsingKeyConnectorList: List<UserKeyConnectorState>,
hasPendingAccountAddition: Boolean,
isBiometricsEnabledProvider: (userId: String) -> Boolean,
vaultUnlockTypeProvider: (userId: String) -> VaultUnlockType,
@ -133,6 +135,9 @@ fun UserStateJson.toUserState(
needsMasterPassword = needsMasterPassword,
hasMasterPassword = decryptionOptions?.hasMasterPassword != false,
trustedDevice = trustedDevice,
isUsingKeyConnector = userIsUsingKeyConnectorList
.find { it.userId == userId }
?.isUsingKeyConnector == true,
)
},
hasPendingAccountAddition = hasPendingAccountAddition,

View file

@ -778,6 +778,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -139,6 +139,26 @@ class AuthDiskSourceTest {
assertFalse(authDiskSource.getShouldUseKeyConnector(userId = userId) ?: true)
}
@Test
fun `getShouldUseKeyConnectorFlow should react to changes in getShouldUseKeyConnector`() =
runTest {
val mockUserId = "mockUserId"
authDiskSource.getShouldUseKeyConnectorFlow(userId = mockUserId).test {
assertNull(authDiskSource.getShouldUseKeyConnector(userId = mockUserId))
assertNull(awaitItem())
authDiskSource.storeShouldUseKeyConnector(
userId = mockUserId,
shouldUseKeyConnector = true,
)
assertEquals(true, awaitItem())
authDiskSource.storeShouldUseKeyConnector(
userId = mockUserId,
shouldUseKeyConnector = false,
)
assertEquals(false, awaitItem())
}
}
@Test
fun `shouldTrustDevice should pull from and update SharedPreferences`() {
val userId = "userId"

View file

@ -18,6 +18,8 @@ class FakeAuthDiskSource : AuthDiskSource {
override var rememberedEmailAddress: String? = null
override var rememberedOrgIdentifier: String? = null
private val mutableShouldUseKeyConnectorFlowMap =
mutableMapOf<String, MutableSharedFlow<Boolean?>>()
private val mutableOrganizationsFlowMap =
mutableMapOf<String, MutableSharedFlow<List<SyncResponseJson.Profile.Organization>?>>()
private val mutablePoliciesFlowMap =
@ -68,17 +70,24 @@ class FakeAuthDiskSource : AuthDiskSource {
storedBiometricKeys.remove(userId)
storedOrganizationKeys.remove(userId)
mutableShouldUseKeyConnectorFlowMap.remove(userId)
mutableOrganizationsFlowMap.remove(userId)
mutablePoliciesFlowMap.remove(userId)
mutableAccountTokensFlowMap.remove(userId)
}
override fun getShouldUseKeyConnectorFlow(
userId: String,
): Flow<Boolean?> = getMutableShouldUseKeyConnectorFlow(userId = userId)
.onSubscription { emit(getShouldUseKeyConnector(userId = userId)) }
override fun getShouldUseKeyConnector(
userId: String,
): Boolean = storedShouldUseKeyConnector[userId] ?: false
): Boolean? = storedShouldUseKeyConnector[userId]
override fun storeShouldUseKeyConnector(userId: String, shouldUseKeyConnector: Boolean?) {
storedShouldUseKeyConnector[userId] = shouldUseKeyConnector
getMutableShouldUseKeyConnectorFlow(userId = userId).tryEmit(shouldUseKeyConnector)
}
override fun getShouldTrustDevice(userId: String): Boolean =
@ -354,6 +363,13 @@ class FakeAuthDiskSource : AuthDiskSource {
//region Private helper functions
private fun getMutableShouldUseKeyConnectorFlow(
userId: String,
): MutableSharedFlow<Boolean?> =
mutableShouldUseKeyConnectorFlowMap.getOrPut(userId) {
bufferedMutableSharedFlow(replay = 1)
}
private fun getMutableOrganizationsFlow(
userId: String,
): MutableSharedFlow<List<SyncResponseJson.Profile.Organization>?> =

View file

@ -72,6 +72,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.ResetPasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.SendVerificationEmailResult
import com.x8bit.bitwarden.data.auth.repository.model.SetPasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePinResult
@ -316,6 +317,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -340,6 +342,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.PIN },
@ -355,6 +358,7 @@ class AuthRepositoryTest {
vaultState = emptyVaultState,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.PIN },
@ -382,6 +386,7 @@ class AuthRepositoryTest {
vaultState = emptyVaultState,
userAccountTokens = emptyList(),
userOrganizationsList = USER_ORGANIZATIONS,
userIsUsingKeyConnectorList = USER_SHOULD_USER_KEY_CONNECTOR,
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -597,6 +602,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -606,6 +612,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -4752,6 +4759,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -4784,6 +4792,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -4814,6 +4823,7 @@ class AuthRepositoryTest {
vaultState = VAULT_UNLOCK_DATA,
userAccountTokens = emptyList(),
userOrganizationsList = emptyList(),
userIsUsingKeyConnectorList = emptyList(),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -5596,6 +5606,12 @@ class AuthRepositoryTest {
organizations = ORGANIZATIONS.toOrganizations(),
),
)
private val USER_SHOULD_USER_KEY_CONNECTOR = listOf(
UserKeyConnectorState(
userId = USER_ID_1,
isUsingKeyConnector = null,
),
)
private val VAULT_UNLOCK_DATA = listOf(
VaultUnlockData(
userId = USER_ID_1,

View file

@ -8,6 +8,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserSwitchingData
import com.x8bit.bitwarden.data.vault.datasource.network.model.OrganizationType
@ -220,6 +221,114 @@ class AuthDiskSourceExtensionsTest {
)
}
@Test
fun `userKeyConnectorStateFlow should emit whenever there are changes to key connector data`() =
runTest {
val mockAccounts = mapOf(
"userId1" to mockk<AccountJson>(),
"userId2" to mockk<AccountJson>(),
"userId3" to mockk<AccountJson>(),
)
val userStateJson = mockk<UserStateJson> {
every { accounts } returns mockAccounts
}
authDiskSource.apply {
userState = userStateJson
storeShouldUseKeyConnector(
userId = "userId1",
shouldUseKeyConnector = false,
)
}
authDiskSource.userKeyConnectorStateFlow.test {
assertEquals(
listOf(
UserKeyConnectorState(
userId = "userId1",
isUsingKeyConnector = false,
),
UserKeyConnectorState(
userId = "userId2",
isUsingKeyConnector = null,
),
UserKeyConnectorState(
userId = "userId3",
isUsingKeyConnector = null,
),
),
awaitItem(),
)
authDiskSource.storeShouldUseKeyConnector(
userId = "userId2",
shouldUseKeyConnector = true,
)
assertEquals(
listOf(
UserKeyConnectorState(
userId = "userId1",
isUsingKeyConnector = false,
),
UserKeyConnectorState(
userId = "userId2",
isUsingKeyConnector = true,
),
UserKeyConnectorState(
userId = "userId3",
isUsingKeyConnector = null,
),
),
awaitItem(),
)
}
}
@Test
fun `userKeyConnectorStateList should return data for all available users`() {
val mockAccounts = mapOf(
"userId1" to mockk<AccountJson>(),
"userId2" to mockk<AccountJson>(),
"userId3" to mockk<AccountJson>(),
)
val userStateJson = mockk<UserStateJson> {
every { accounts } returns mockAccounts
}
authDiskSource.apply {
userState = userStateJson
storeShouldUseKeyConnector(
userId = "userId1",
shouldUseKeyConnector = false,
)
storeShouldUseKeyConnector(
userId = "userId2",
shouldUseKeyConnector = true,
)
storeShouldUseKeyConnector(
userId = "userId3",
shouldUseKeyConnector = null,
)
}
assertEquals(
listOf(
UserKeyConnectorState(
userId = "userId1",
isUsingKeyConnector = false,
),
UserKeyConnectorState(
userId = "userId2",
isUsingKeyConnector = true,
),
UserKeyConnectorState(
userId = "userId3",
isUsingKeyConnector = null,
),
),
authDiskSource.userKeyConnectorStateList,
)
}
@Test
fun `userOrganizationsListFlow should emit whenever there are changes to organization data`() =
runTest {

View file

@ -11,6 +11,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserD
import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
@ -239,6 +240,7 @@ class UserStateJsonExtensionsTest {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -296,6 +298,12 @@ class UserStateJsonExtensionsTest {
),
),
),
userIsUsingKeyConnectorList = listOf(
UserKeyConnectorState(
userId = "activeUserId",
isUsingKeyConnector = false,
),
),
hasPendingAccountAddition = false,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.PIN },
@ -334,6 +342,7 @@ class UserStateJsonExtensionsTest {
needsMasterPassword = true,
trustedDevice = null,
hasMasterPassword = false,
isUsingKeyConnector = false,
),
),
hasPendingAccountAddition = true,
@ -387,6 +396,12 @@ class UserStateJsonExtensionsTest {
),
),
),
userIsUsingKeyConnectorList = listOf(
UserKeyConnectorState(
userId = "activeUserId",
isUsingKeyConnector = null,
),
),
hasPendingAccountAddition = true,
isBiometricsEnabledProvider = { true },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
@ -431,6 +446,7 @@ class UserStateJsonExtensionsTest {
hasResetPasswordPermission = false,
),
hasMasterPassword = false,
isUsingKeyConnector = true,
),
),
hasPendingAccountAddition = true,
@ -487,6 +503,12 @@ class UserStateJsonExtensionsTest {
),
),
),
userIsUsingKeyConnectorList = listOf(
UserKeyConnectorState(
userId = "activeUserId",
isUsingKeyConnector = true,
),
),
hasPendingAccountAddition = true,
isBiometricsEnabledProvider = { false },
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },

View file

@ -531,6 +531,7 @@ private fun createMockAccounts(number: Int): List<UserState.Account> {
isBiometricsEnabled = false,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
)
}

View file

@ -301,6 +301,7 @@ private val DEFAULT_USER_STATE: UserState = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -85,6 +85,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -220,6 +221,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
val userState = UserState(
activeUserId = "activeUserId",
@ -274,6 +276,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
val userState = UserState(
activeUserId = "activeUserId",
@ -332,6 +335,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
val userState = UserState(
activeUserId = "activeUserId",
@ -506,6 +510,7 @@ class LandingViewModelTest : BaseViewModelTest() {
isBiometricsEnabled = false,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
val userState = UserState(
@ -539,6 +544,7 @@ class LandingViewModelTest : BaseViewModelTest() {
isBiometricsEnabled = false,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
val userState = UserState(

View file

@ -128,6 +128,7 @@ class LoginViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -98,6 +98,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -273,6 +273,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsMasterPassword = false,
trustedDevice = TRUSTED_DEVICE,
hasMasterPassword = false,
isUsingKeyConnector = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -213,6 +213,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -250,6 +251,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -1008,6 +1010,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -74,6 +74,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -106,6 +107,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -135,6 +137,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = true,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -172,6 +175,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasResetPasswordPermission = false,
),
hasMasterPassword = false,
isUsingKeyConnector = false,
),
),
),
@ -207,6 +211,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasResetPasswordPermission = false,
),
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -242,6 +247,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasResetPasswordPermission = false,
),
hasMasterPassword = false,
isUsingKeyConnector = false,
),
),
),
@ -275,6 +281,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
hasPendingAccountAddition = true,
@ -308,6 +315,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -346,6 +354,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -384,6 +393,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -428,6 +438,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -473,6 +484,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -513,6 +525,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -552,6 +565,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -626,6 +640,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -675,6 +690,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
@ -712,6 +728,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),

View file

@ -1417,6 +1417,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -640,6 +640,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -241,6 +241,7 @@ private val DEFAULT_USER_STATE: UserState = UserState(
hasResetPasswordPermission = true,
),
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -369,6 +369,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -721,6 +721,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -2405,6 +2405,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -1100,6 +1100,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -3888,6 +3888,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
hasPendingAccountAddition = false,

View file

@ -444,6 +444,7 @@ class CipherViewExtensionsTest {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
}

View file

@ -561,6 +561,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -2578,6 +2578,7 @@ class VaultItemViewModelTest : BaseViewModelTest() {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -3784,6 +3784,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -509,6 +509,7 @@ private val DEFAULT_USER_STATE = UserState(
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -124,6 +124,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
},
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -194,6 +194,7 @@ class VaultViewModelTest : BaseViewModelTest() {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -276,6 +277,7 @@ class VaultViewModelTest : BaseViewModelTest() {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -1525,6 +1527,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
UserState.Account(
userId = "lockedUserId",
@ -1541,6 +1544,7 @@ private val DEFAULT_USER_STATE = UserState(
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)

View file

@ -83,6 +83,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
UserState.Account(
userId = "lockedUserId",
@ -106,6 +107,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
UserState.Account(
userId = "unlockedUserId",
@ -133,6 +135,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
UserState.Account(
userId = "loggedOutUserId",
@ -160,6 +163,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -202,6 +206,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
.toAccountSummary(isActive = true),
)
@ -242,6 +247,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
.toAccountSummary(isActive = false),
)
@ -286,6 +292,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
)
@ -311,6 +318,7 @@ class UserStateExtensionsTest {
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
.toVaultFilterData(isIndividualVaultDisabled = false),
)
@ -363,6 +371,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
.toVaultFilterData(
isIndividualVaultDisabled = false,
@ -416,6 +425,7 @@ class UserStateExtensionsTest {
),
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
)
.toVaultFilterData(
isIndividualVaultDisabled = true,