Add needsMasterPassword field to userState (#1105)

This commit is contained in:
David Perez 2024-03-07 09:37:18 -06:00 committed by Álison Fernandes
parent f854f70613
commit 274aa620b1
20 changed files with 66 additions and 8 deletions

View file

@ -41,6 +41,8 @@ data class UserState(
* authentication to view their vault.
* @property isVaultUnlocked Whether or not the user's vault is currently unlocked.
* @property needsPasswordReset If the user needs to reset their password.
* @property needsMasterPassword Indicates whether the user needs to create a password (e.g.
* they logged in using SSO and don't yet have one).
* @property organizations List of [Organization]s the user is associated with, if any.
* @property isBiometricsEnabled Indicates that the biometrics mechanism for unlocking the
* user's vault is enabled.
@ -56,6 +58,7 @@ data class UserState(
val isLoggedIn: Boolean,
val isVaultUnlocked: Boolean,
val needsPasswordReset: Boolean,
val needsMasterPassword: Boolean,
val organizations: List<Organization>,
val isBiometricsEnabled: Boolean,
val vaultUnlockType: VaultUnlockType = VaultUnlockType.MASTER_PASSWORD,

View file

@ -58,21 +58,22 @@ fun UserStateJson.toUserState(
.accounts
.values
.map { accountJson ->
val userId = accountJson.profile.userId
val profile = accountJson.profile
val userId = profile.userId
val vaultUnlocked = vaultState.statusFor(userId) == VaultUnlockData.Status.UNLOCKED
val needsPasswordReset = accountJson.profile.forcePasswordResetReason != null
val needsPasswordReset = profile.forcePasswordResetReason != null
val needsMasterPassword = profile.userDecryptionOptions?.hasMasterPassword == false
UserState.Account(
userId = accountJson.profile.userId,
name = accountJson.profile.name,
email = accountJson.profile.email,
avatarColorHex = accountJson.profile.avatarColorHex
?: accountJson.profile.userId.toHexColorRepresentation(),
userId = userId,
name = profile.name,
email = profile.email,
avatarColorHex = profile.avatarColorHex ?: userId.toHexColorRepresentation(),
environment = accountJson
.settings
.environmentUrlData
.toEnvironmentUrlsOrDefault(),
isPremium = accountJson.profile.hasPremium == true,
isPremium = profile.hasPremium == true,
isLoggedIn = isLoggedInProvider(userId),
isVaultUnlocked = vaultUnlocked && !needsPasswordReset,
needsPasswordReset = needsPasswordReset,
@ -82,6 +83,7 @@ fun UserStateJson.toUserState(
.orEmpty(),
isBiometricsEnabled = isBiometricsEnabledProvider(userId),
vaultUnlockType = vaultUnlockTypeProvider(userId),
needsMasterPassword = needsMasterPassword,
)
},
hasPendingAccountAddition = hasPendingAccountAddition,

View file

@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KdfTypeJson
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.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -117,6 +118,7 @@ class UserStateJsonExtensionsTest {
),
isBiometricsEnabled = false,
vaultUnlockType = VaultUnlockType.PIN,
needsMasterPassword = false,
),
),
),
@ -131,6 +133,11 @@ class UserStateJsonExtensionsTest {
every { avatarColorHex } returns "activeAvatarColorHex"
every { hasPremium } returns null
every { forcePasswordResetReason } returns null
every { userDecryptionOptions } returns UserDecryptionOptionsJson(
hasMasterPassword = true,
trustedDeviceUserDecryptionOptions = null,
keyConnectorUserDecryptionOptions = null,
)
},
tokens = AccountTokensJson(
accessToken = "accessToken",
@ -193,6 +200,7 @@ class UserStateJsonExtensionsTest {
),
isBiometricsEnabled = true,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
needsMasterPassword = true,
),
),
hasPendingAccountAddition = true,
@ -208,6 +216,11 @@ class UserStateJsonExtensionsTest {
every { avatarColorHex } returns null
every { hasPremium } returns true
every { forcePasswordResetReason } returns null
every { userDecryptionOptions } returns UserDecryptionOptionsJson(
hasMasterPassword = false,
trustedDeviceUserDecryptionOptions = null,
keyConnectorUserDecryptionOptions = null,
)
},
tokens = AccountTokensJson(
accessToken = null,

View file

@ -74,6 +74,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)
@ -206,6 +207,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
)
val userState = UserState(
activeUserId = "activeUserId",
@ -257,6 +259,7 @@ class LandingViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
)
val userState = UserState(
activeUserId = "activeUserId",

View file

@ -130,6 +130,7 @@ class LoginViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -118,6 +118,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)
@ -152,6 +153,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = true,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)
@ -728,6 +730,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -50,6 +50,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),
@ -76,6 +77,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = true,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),
@ -103,6 +105,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
hasPendingAccountAddition = true,
@ -130,6 +133,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),
@ -165,6 +169,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),
@ -200,6 +205,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),
@ -241,6 +247,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),
@ -273,6 +280,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
),

View file

@ -1365,6 +1365,7 @@ private val DEFAULT_USER_STATE = UserState(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -297,6 +297,7 @@ private val DEFAULT_USER_STATE = UserState(
isVaultUnlocked = true,
needsPasswordReset = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -2175,6 +2175,7 @@ private val DEFAULT_USER_STATE = UserState(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -1097,6 +1097,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -2454,6 +2454,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
),
isBiometricsEnabled = true,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
needsMasterPassword = false,
),
),
hasPendingAccountAddition = false,

View file

@ -418,6 +418,7 @@ class CipherViewExtensionsTest {
),
isBiometricsEnabled = true,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
needsMasterPassword = false,
)
}

View file

@ -556,6 +556,7 @@ private val DEFAULT_USER_STATE = UserState(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -1916,6 +1916,7 @@ class VaultItemViewModelTest : BaseViewModelTest() {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -1436,6 +1436,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
)
private val DEFAULT_USER_STATE = UserState(

View file

@ -476,6 +476,7 @@ private val DEFAULT_USER_STATE = UserState(
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "mockOrganizationId-1",

View file

@ -96,6 +96,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = if (hasOrganizations) {
listOf(
Organization(

View file

@ -176,6 +176,7 @@ class VaultViewModelTest : BaseViewModelTest() {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organiationId",
@ -253,6 +254,7 @@ class VaultViewModelTest : BaseViewModelTest() {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -1470,6 +1472,7 @@ private val DEFAULT_USER_STATE = UserState(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
UserState.Account(
userId = "lockedUserId",
@ -1483,6 +1486,7 @@ private val DEFAULT_USER_STATE = UserState(
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
),
),
)

View file

@ -71,6 +71,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -89,6 +90,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = false,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -111,6 +113,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -133,6 +136,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = false,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -170,6 +174,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -205,6 +210,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = false,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -244,6 +250,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId",
@ -272,6 +279,7 @@ class UserStateExtensionsTest {
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
)
.toVaultFilterData(isIndividualVaultDisabled = false),
)
@ -307,6 +315,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId-B",
@ -353,6 +362,7 @@ class UserStateExtensionsTest {
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
needsMasterPassword = false,
organizations = listOf(
Organization(
id = "organizationId-B",