BIT-782: Implement Personal Ownership policy support (#920)

This commit is contained in:
Caleb Derosier 2024-01-31 20:54:08 -07:00 committed by Álison Fernandes
parent f380e21600
commit debfbc04b0
17 changed files with 427 additions and 29 deletions

View file

@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.autofill.manager.AutofillSelectionManager
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
import com.x8bit.bitwarden.data.platform.manager.util.toAutofillSelectionDataOrNull
@ -17,6 +18,7 @@ import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.repository.util.baseIconUrl
import com.x8bit.bitwarden.data.platform.repository.util.baseWebSendUrl
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.DeleteSendResult
import com.x8bit.bitwarden.data.vault.repository.model.GenerateTotpResult
@ -61,6 +63,7 @@ class SearchViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val clock: Clock,
private val clipboardManager: BitwardenClipboardManager,
private val policyManager: PolicyManager,
private val autofillSelectionManager: AutofillSelectionManager,
private val vaultRepo: VaultRepository,
private val authRepo: AuthRepository,
@ -84,7 +87,11 @@ class SearchViewModel @Inject constructor(
dialogState = null,
vaultFilterData = when (searchType) {
is SearchType.Sends -> null
is SearchType.Vault -> userState.activeAccount.toVaultFilterData()
is SearchType.Vault -> userState.activeAccount.toVaultFilterData(
isIndividualVaultDisabled = policyManager
.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
.any(),
)
},
baseWebSendUrl = environmentRepo.environment.environmentUrlData.baseWebSendUrl,
baseIconUrl = environmentRepo.environment.environmentUrlData.baseIconUrl,

View file

@ -17,6 +17,7 @@ import androidx.compose.ui.unit.dp
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.BitwardenListHeaderText
import com.x8bit.bitwarden.ui.platform.components.BitwardenMultiSelectButton
import com.x8bit.bitwarden.ui.platform.components.BitwardenPolicyWarningText
import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCardTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
@ -58,6 +59,17 @@ fun VaultAddEditContent(
modifier = modifier
.semantics { testTagsAsResourceId = true },
) {
item {
if (state.isIndividualVaultDisabled && isAddItemMode) {
BitwardenPolicyWarningText(
text = stringResource(R.string.personal_ownership_policy_in_effect),
modifier = Modifier
.padding(horizontal = 16.dp)
.fillMaxWidth(),
)
}
}
item {
BitwardenListHeaderText(
label = stringResource(id = R.string.item_information),

View file

@ -8,6 +8,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
import com.x8bit.bitwarden.data.platform.manager.util.toAutofillSaveItemOrNull
@ -17,6 +18,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.repository.util.takeUntilLoaded
import com.x8bit.bitwarden.data.tools.generator.repository.GeneratorRepository
import com.x8bit.bitwarden.data.tools.generator.repository.model.GeneratorResult
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.CreateCipherResult
import com.x8bit.bitwarden.data.vault.repository.model.DeleteCipherResult
@ -74,6 +76,7 @@ class VaultAddEditViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val authRepository: AuthRepository,
private val clipboardManager: BitwardenClipboardManager,
private val policyManager: PolicyManager,
private val vaultRepository: VaultRepository,
private val generatorRepository: GeneratorRepository,
private val settingsRepository: SettingsRepository,
@ -84,6 +87,9 @@ class VaultAddEditViewModel @Inject constructor(
initialState = savedStateHandle[KEY_STATE]
?: run {
val vaultAddEditType = VaultAddEditArgs(savedStateHandle).vaultAddEditType
val isIndividualVaultDisabled = policyManager
.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
.any()
// Check for autofill data to pre-populate
val autofillSaveItem = specialCircumstanceManager
@ -104,11 +110,12 @@ class VaultAddEditViewModel @Inject constructor(
}
val defaultAddTypeContent = autofillSelectionData
?.toDefaultAddTypeContent()
?.toDefaultAddTypeContent(isIndividualVaultDisabled)
?: autofillSaveItem
?.toDefaultAddTypeContent()
?.toDefaultAddTypeContent(isIndividualVaultDisabled)
?: VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
)
@ -1140,8 +1147,11 @@ class VaultAddEditViewModel @Inject constructor(
private fun VaultAddEditState.determineContentState(
vaultData: VaultData,
userData: UserState?,
): VaultAddEditState =
copy(
): VaultAddEditState {
val isIndividualVaultDisabled = policyManager
.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
.any()
return copy(
viewState = vaultData.cipherViewList
.find { it.id == vaultAddEditType.vaultItemId }
.validateCipherOrReturnErrorState(
@ -1152,6 +1162,7 @@ class VaultAddEditViewModel @Inject constructor(
// or use the current state for Add
(cipherView?.toViewState(
isClone = isCloneMode,
isIndividualVaultDisabled = isIndividualVaultDisabled,
resourceManager = resourceManager,
) ?: viewState)
.appendFolderAndOwnerData(
@ -1159,10 +1170,12 @@ class VaultAddEditViewModel @Inject constructor(
collectionViewList = vaultData.collectionViewList
.filter { !it.readOnly },
activeAccount = currentAccount,
isIndividualVaultDisabled = isIndividualVaultDisabled,
resourceManager = resourceManager,
)
},
)
}
private fun handleVaultTotpCodeReceive(action: VaultAddEditAction.Internal.TotpCodeReceive) {
when (action.totpResult) {
@ -1473,6 +1486,7 @@ data class VaultAddEditState(
data class Content(
val common: Common,
val type: ItemType,
val isIndividualVaultDisabled: Boolean,
val previousItemTypes: Map<ItemTypeOption, ItemType> = emptyMap(),
) : ViewState() {
@ -1512,6 +1526,7 @@ data class VaultAddEditState(
*/
val selectedOwner: Owner?
get() = availableOwners.find { it.id == selectedOwnerId }
?: availableOwners.firstOrNull()
/**
* Helper to provide the currently selected folder.

View file

@ -11,11 +11,14 @@ import java.util.UUID
* Returns pre-filled content that may be used for an "add" type
* [VaultAddEditState.ViewState.Content].
*/
fun AutofillSaveItem.toDefaultAddTypeContent(): VaultAddEditState.ViewState.Content =
fun AutofillSaveItem.toDefaultAddTypeContent(
isIndividualVaultDisabled: Boolean,
): VaultAddEditState.ViewState.Content =
when (this) {
is AutofillSaveItem.Card -> {
VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = VaultAddEditState.ViewState.Content.ItemType.Card(
number = this.number.orEmpty(),
expirationMonth = VaultCardExpirationMonth
@ -35,6 +38,7 @@ fun AutofillSaveItem.toDefaultAddTypeContent(): VaultAddEditState.ViewState.Cont
common = VaultAddEditState.ViewState.Content.Common(
name = simpleUri.orEmpty(),
),
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = VaultAddEditState.ViewState.Content.ItemType.Login(
username = this.username.orEmpty(),
password = this.password.orEmpty(),

View file

@ -10,7 +10,9 @@ import java.util.UUID
* Returns pre-filled content that may be used for an "add" type
* [VaultAddEditState.ViewState.Content].
*/
fun AutofillSelectionData.toDefaultAddTypeContent(): VaultAddEditState.ViewState.Content {
fun AutofillSelectionData.toDefaultAddTypeContent(
isIndividualVaultDisabled: Boolean,
): VaultAddEditState.ViewState.Content {
val uri = this.uri
val simpleUri = uri?.toHostOrPathOrNull()
val defaultAddType = when (this.type) {
@ -34,6 +36,7 @@ fun AutofillSelectionData.toDefaultAddTypeContent(): VaultAddEditState.ViewState
common = VaultAddEditState.ViewState.Content.Common(
name = simpleUri.orEmpty(),
),
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = defaultAddType,
)
}

View file

@ -30,6 +30,7 @@ import java.util.UUID
*/
fun CipherView.toViewState(
isClone: Boolean,
isIndividualVaultDisabled: Boolean,
resourceManager: ResourceManager,
): VaultAddEditState.ViewState =
VaultAddEditState.ViewState.Content(
@ -86,6 +87,7 @@ fun CipherView.toViewState(
availableOwners = emptyList(),
customFieldData = this.fields.orEmpty().map { it.toCustomField() },
),
isIndividualVaultDisabled = isIndividualVaultDisabled,
)
/**
@ -95,6 +97,7 @@ fun VaultAddEditState.ViewState.appendFolderAndOwnerData(
folderViewList: List<FolderView>,
collectionViewList: List<CollectionView>,
activeAccount: UserState.Account,
isIndividualVaultDisabled: Boolean,
resourceManager: ResourceManager,
): VaultAddEditState.ViewState {
return (this as? VaultAddEditState.ViewState.Content)?.let { currentContentState ->
@ -111,6 +114,7 @@ fun VaultAddEditState.ViewState.appendFolderAndOwnerData(
),
availableOwners = activeAccount.toAvailableOwners(
collectionViewList = collectionViewList,
isIndividualVaultDisabled = isIndividualVaultDisabled,
),
),
)
@ -161,10 +165,17 @@ private fun UserState.Account.toSelectedOwnerId(cipherView: CipherView?): String
private fun UserState.Account.toAvailableOwners(
collectionViewList: List<CollectionView>,
isIndividualVaultDisabled: Boolean,
): List<VaultAddEditState.Owner> =
listOf(VaultAddEditState.Owner(name = email, id = null, collections = emptyList()))
.plus(
organizations.map {
listOfNotNull(
VaultAddEditState.Owner(
name = email,
id = null,
collections = emptyList(),
)
.takeUnless { isIndividualVaultDisabled },
*organizations
.map {
VaultAddEditState.Owner(
name = it.name.orEmpty(),
id = it.id,
@ -181,8 +192,9 @@ private fun UserState.Account.toAvailableOwners(
)
},
)
},
)
}
.toTypedArray(),
)
private fun FieldView.toCustomField() =
when (this.type) {

View file

@ -7,10 +7,12 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.repository.util.baseIconUrl
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.GenerateTotpResult
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
@ -52,6 +54,7 @@ class VaultViewModel @Inject constructor(
private val authRepository: AuthRepository,
private val clipboardManager: BitwardenClipboardManager,
private val clock: Clock,
private val policyManager: PolicyManager,
private val settingsRepository: SettingsRepository,
private val vaultRepository: VaultRepository,
) : BaseViewModel<VaultState, VaultEvent, VaultAction>(
@ -59,7 +62,11 @@ class VaultViewModel @Inject constructor(
val userState = requireNotNull(authRepository.userStateFlow.value)
val accountSummaries = userState.toAccountSummaries()
val activeAccountSummary = userState.toActiveAccountSummary()
val vaultFilterData = userState.activeAccount.toVaultFilterData()
val vaultFilterData = userState.activeAccount.toVaultFilterData(
isIndividualVaultDisabled = policyManager
.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
.any(),
)
val appBarTitle = vaultFilterData.toAppBarTitle()
VaultState(
appBarTitle = appBarTitle,
@ -414,7 +421,11 @@ class VaultViewModel @Inject constructor(
// navigating.
if (state.isSwitchingAccounts) return
val vaultFilterData = userState.activeAccount.toVaultFilterData()
val vaultFilterData = userState.activeAccount.toVaultFilterData(
isIndividualVaultDisabled = policyManager
.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
.any(),
)
val appBarTitle = vaultFilterData.toAppBarTitle()
mutableStateFlow.update {
val accountSummaries = userState.toAccountSummaries()

View file

@ -47,16 +47,18 @@ fun UserState.Account.toAccountSummary(
* Converts the given [UserState.Account] to a [VaultFilterData] (if applicable). Filter data is
* only relevant when the given account is associated with one or more organizations.
*/
fun UserState.Account.toVaultFilterData(): VaultFilterData? =
fun UserState.Account.toVaultFilterData(
isIndividualVaultDisabled: Boolean,
): VaultFilterData? =
this
.organizations
.takeIf { it.isNotEmpty() }
?.let { organizations ->
VaultFilterData(
selectedVaultFilterType = VaultFilterType.AllVaults,
vaultFilterTypes = listOf(
vaultFilterTypes = listOfNotNull(
VaultFilterType.AllVaults,
VaultFilterType.MyVault,
VaultFilterType.MyVault.takeUnless { isIndividualVaultDisabled },
*organizations
.sortedBy { it.name }
.map { organization ->

View file

@ -13,6 +13,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.autofill.manager.AutofillSelectionManager
import com.x8bit.bitwarden.data.autofill.manager.AutofillSelectionManagerImpl
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManagerImpl
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
@ -21,6 +22,8 @@ import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.repository.model.Environment
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
@ -77,6 +80,11 @@ class SearchViewModelTest : BaseViewModelTest() {
private val clipboardManager: BitwardenClipboardManager = mockk {
every { setText(any<String>()) } just runs
}
private val policyManager: PolicyManager = mockk<PolicyManager> {
every {
getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns emptyList()
}
private val mutableVaultDataStateFlow =
MutableStateFlow<DataState<VaultData>>(DataState.Loading)
private val vaultRepository: VaultRepository = mockk {
@ -124,6 +132,26 @@ class SearchViewModelTest : BaseViewModelTest() {
assertEquals(state, viewModel.stateFlow.value)
}
@Test
fun `initial state should be correct when user has PERSONAL_OWNERSHIP policy`() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
organizationId = "Test Org",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,
isEnabled = true,
data = null,
),
)
val viewModel = createViewModel()
assertEquals(DEFAULT_STATE, viewModel.stateFlow.value)
verify {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
}
}
@Test
fun `BackClick should emit NavigateBack`() = runTest {
val viewModel = createViewModel()
@ -1232,6 +1260,7 @@ class SearchViewModelTest : BaseViewModelTest() {
environmentRepo = environmentRepository,
settingsRepo = settingsRepository,
clipboardManager = clipboardManager,
policyManager = policyManager,
specialCircumstanceManager = specialCircumstanceManager,
autofillSelectionManager = autofillSelectionManager,
)

View file

@ -305,6 +305,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
isIndividualVaultDisabled = false,
),
)
}
@ -333,6 +334,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
isIndividualVaultDisabled = false,
),
)
}
@ -371,6 +373,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Card(),
isIndividualVaultDisabled = false,
),
)
}
@ -403,6 +406,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
type = VaultAddEditState.ViewState.Content.ItemType.Login(
password = "p@ssw0rd",
),
isIndividualVaultDisabled = false,
),
)
}
@ -440,6 +444,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
password = "p@ssw0rd",
canViewPassword = false,
),
isIndividualVaultDisabled = false,
),
)
}
@ -2490,6 +2495,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
originalCipher = createMockCipherView(1),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = false,
),
)
}
@ -2530,6 +2536,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = false,
),
)
}
@ -2558,6 +2565,48 @@ class VaultAddEditScreenTest : BaseComposeTest() {
.assertIsDisplayed()
}
@Test
fun `should display policy warning when personal vault is disabled for add item type`() {
mutableStateFlow.update {
it.copy(
vaultAddEditType = VaultAddEditType.AddItem,
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(
originalCipher = createMockCipherView(1),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = true,
),
)
}
composeTestRule
.onNodeWithTextAfterScroll(
text = "An organization policy is affecting your ownership options.",
)
.assertIsDisplayed()
}
@Test
fun `should not display policy warning when personal vault is disabled for edit item type`() {
mutableStateFlow.update {
it.copy(
vaultAddEditType = VaultAddEditType.EditItem("mockId-1"),
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(
originalCipher = createMockCipherView(1),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = true,
),
)
}
composeTestRule
.onNodeWithText(text = "An organization policy is affecting your ownership options.")
.assertDoesNotExist()
}
@Test
fun `Delete dialog ok click should send ConfirmDeleteClick`() {
mutableStateFlow.update {
@ -2568,6 +2617,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
originalCipher = createMockCipherView(1),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = false,
),
)
}
@ -2615,6 +2665,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
originalCipher = createMockCipherView(1),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = false,
),
)
}
@ -2763,6 +2814,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
isIndividualVaultDisabled = false,
),
dialog = VaultAddEditState.DialogState.Generic(message = "test".asText()),
vaultAddEditType = VaultAddEditType.AddItem,
@ -2773,6 +2825,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
isIndividualVaultDisabled = false,
),
dialog = null,
)
@ -2782,6 +2835,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Identity(),
isIndividualVaultDisabled = false,
),
dialog = null,
)
@ -2791,6 +2845,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.Card(),
isIndividualVaultDisabled = false,
),
dialog = null,
)
@ -2810,6 +2865,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
),
),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = false,
),
dialog = null,
vaultAddEditType = VaultAddEditType.AddItem,
@ -2820,6 +2876,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
viewState = VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
isIndividualVaultDisabled = false,
),
dialog = null,
)

View file

@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManagerImpl
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
@ -26,6 +27,8 @@ import com.x8bit.bitwarden.data.platform.repository.model.Environment
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
import com.x8bit.bitwarden.data.tools.generator.repository.GeneratorRepository
import com.x8bit.bitwarden.data.tools.generator.repository.util.FakeGeneratorRepository
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.CreateCipherResult
@ -95,6 +98,11 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
every { getString(R.string.folder_none) } returns "No Folder"
}
private val clipboardManager: BitwardenClipboardManager = mockk()
private val policyManager: PolicyManager = mockk {
every {
getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns emptyList()
}
private val vaultRepository: VaultRepository = mockk {
every { vaultDataStateFlow } returns mutableVaultDataFlow
every { totpCodeFlow } returns totpTestCodeFlow
@ -134,6 +142,9 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
awaitItem(),
)
}
verify {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
}
}
@Test
@ -155,6 +166,57 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
}
}
@Test
fun `initial add state should be correct with individual vault disabled`() = runTest {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
organizationId = "Test Org",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,
isEnabled = true,
data = null,
),
)
val vaultAddEditType = VaultAddEditType.AddItem
mutableVaultDataFlow.value = DataState.Loaded(
data = createVaultData(),
)
val viewModel = createAddVaultItemViewModel(
savedStateHandle = createSavedStateHandleWithState(
state = null,
vaultAddEditType = vaultAddEditType,
),
)
assertEquals(
VaultAddEditState(
vaultAddEditType = vaultAddEditType,
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(
availableOwners = listOf(
VaultAddEditState.Owner(
id = "organizationId",
name = "organizationName",
collections = emptyList(),
),
),
),
isIndividualVaultDisabled = true,
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
),
dialog = null,
),
viewModel.stateFlow.value,
)
verify(exactly = 1) {
vaultRepository.vaultDataStateFlow
}
verify {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
}
}
@Test
fun `initial add state should be correct when autofill selection`() = runTest {
val autofillSelectionData = AutofillSelectionData(
@ -165,7 +227,9 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
autofillSelectionData = autofillSelectionData,
shouldFinishWhenComplete = true,
)
val autofillContentState = autofillSelectionData.toDefaultAddTypeContent()
val autofillContentState = autofillSelectionData.toDefaultAddTypeContent(
isIndividualVaultDisabled = false,
)
val vaultAddEditType = VaultAddEditType.AddItem
val initState = createVaultAddItemState(
vaultAddEditType = vaultAddEditType,
@ -197,7 +261,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.AutofillSave(
autofillSaveItem = autofillSaveItem,
)
val autofillContentState = autofillSaveItem.toDefaultAddTypeContent()
val autofillContentState = autofillSaveItem.toDefaultAddTypeContent(false)
val vaultAddEditType = VaultAddEditType.AddItem
val initState = createVaultAddItemState(
vaultAddEditType = vaultAddEditType,
@ -685,6 +749,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
every {
cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
} returns stateWithName.viewState
@ -713,6 +778,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
coVerify(exactly = 1) {
cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
vaultRepository.updateCipher(DEFAULT_EDIT_ITEM_ID, any())
@ -744,6 +810,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
every {
cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
} returns stateWithName.viewState
@ -801,7 +868,11 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val errorMessage = "You do not have permission to edit this."
every {
cipherView.toViewState(isClone = false, resourceManager = resourceManager)
cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
} returns stateWithName.viewState
coEvery {
vaultRepository.updateCipher(DEFAULT_EDIT_ITEM_ID, any())
@ -907,6 +978,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
previousItemTypes = mapOf(
VaultAddEditState.ItemTypeOption.LOGIN
@ -936,6 +1008,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Card(),
previousItemTypes = mapOf(
VaultAddEditState.ItemTypeOption.LOGIN
@ -965,6 +1038,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Identity(),
previousItemTypes = mapOf(
VaultAddEditState.ItemTypeOption.LOGIN
@ -994,6 +1068,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
previousItemTypes = mapOf(
VaultAddEditState.ItemTypeOption.LOGIN
@ -1074,6 +1149,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val loginState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(
password = password,
),
@ -1209,6 +1285,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(
totpCode = null,
),
@ -1233,6 +1310,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(
totpCode = "TestKey",
),
@ -1274,6 +1352,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(
uri = listOf(UriItem("testID", "Test", null)),
),
@ -1306,6 +1385,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
val expectedState = loginInitialState.copy(
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState(),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(
uri = listOf(),
),
@ -1772,6 +1852,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
vaultRepository = vaultRepository,
generatorRepository = generatorRepository,
specialCircumstanceManager = specialCircumstanceManager,
policyManager = policyManager,
resourceManager = resourceManager,
authRepository = authRepository,
settingsRepository = settingsRepository,
@ -1789,6 +1870,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
common = createCommonContentViewState(
name = "newName",
),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
),
)
@ -1811,6 +1893,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState()
.copy(selectedFolderId = "mockId-1"),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
),
)
@ -1829,6 +1912,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
common = createCommonContentViewState(
favorite = true,
),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
),
)
@ -1850,6 +1934,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
common = createCommonContentViewState(
masterPasswordReprompt = true,
),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
),
)
@ -1869,6 +1954,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
common = createCommonContentViewState(
notes = "newNotes",
),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
),
)
@ -1892,6 +1978,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
viewState = VaultAddEditState.ViewState.Content(
common = createCommonContentViewState()
.copy(selectedOwnerId = "mockId-1"),
isIndividualVaultDisabled = false,
type = createLoginTypeContentViewState(),
),
)
@ -2217,6 +2304,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
private fun createVaultAddItemState(
vaultAddEditType: VaultAddEditType = VaultAddEditType.AddItem,
commonContentViewState: VaultAddEditState.ViewState.Content.Common = createCommonContentViewState(),
isIndividualVaultDisabled: Boolean = false,
typeContentViewState: VaultAddEditState.ViewState.Content.ItemType = createLoginTypeContentViewState(),
dialogState: VaultAddEditState.DialogState? = null,
): VaultAddEditState =
@ -2224,6 +2312,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
vaultAddEditType = vaultAddEditType,
viewState = VaultAddEditState.ViewState.Content(
common = commonContentViewState,
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = typeContentViewState,
),
dialog = dialogState,
@ -2313,6 +2402,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
vaultRepository = vaultRepo,
generatorRepository = generatorRepo,
specialCircumstanceManager = specialCircumstanceManager,
policyManager = policyManager,
resourceManager = bitwardenResourceManager,
authRepository = authRepository,
settingsRepository = settingsRepository,

View file

@ -28,6 +28,7 @@ class AutofillSaveItemExtensionsTest {
assertEquals(
VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Card(
number = "number",
expirationMonth = VaultCardExpirationMonth.JANUARY,
@ -41,7 +42,7 @@ class AutofillSaveItemExtensionsTest {
expirationYear = "2024",
securityCode = "securityCode",
)
.toDefaultAddTypeContent(),
.toDefaultAddTypeContent(isIndividualVaultDisabled = false),
)
}
@ -53,6 +54,7 @@ class AutofillSaveItemExtensionsTest {
common = VaultAddEditState.ViewState.Content.Common(
name = "www.test.com",
),
isIndividualVaultDisabled = true,
type = VaultAddEditState.ViewState.Content.ItemType.Login(
username = "username",
password = "password",
@ -70,7 +72,7 @@ class AutofillSaveItemExtensionsTest {
password = "password",
uri = "https://www.test.com",
)
.toDefaultAddTypeContent(),
.toDefaultAddTypeContent(isIndividualVaultDisabled = true),
)
}
}

View file

@ -27,13 +27,14 @@ class AutofillSelectionDataExtensionsTest {
assertEquals(
VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Card(),
),
AutofillSelectionData(
type = AutofillSelectionData.Type.CARD,
uri = null,
)
.toDefaultAddTypeContent(),
.toDefaultAddTypeContent(isIndividualVaultDisabled = false),
)
}
@ -45,6 +46,7 @@ class AutofillSelectionDataExtensionsTest {
common = VaultAddEditState.ViewState.Content.Common(
name = "www.test.com",
),
isIndividualVaultDisabled = true,
type = VaultAddEditState.ViewState.Content.ItemType.Login(
uriList = listOf(
UriItem(
@ -59,7 +61,7 @@ class AutofillSelectionDataExtensionsTest {
type = AutofillSelectionData.Type.LOGIN,
uri = "https://www.test.com",
)
.toDefaultAddTypeContent(),
.toDefaultAddTypeContent(isIndividualVaultDisabled = true),
)
}
}

View file

@ -52,6 +52,7 @@ class CipherViewExtensionsTest {
val result = cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
@ -76,6 +77,7 @@ class CipherViewExtensionsTest {
availableFolders = emptyList(),
availableOwners = emptyList(),
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Card(
cardHolderName = "Bit Warden",
number = "4012888888881881",
@ -94,6 +96,7 @@ class CipherViewExtensionsTest {
val result = cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = true,
resourceManager = resourceManager,
)
@ -118,6 +121,7 @@ class CipherViewExtensionsTest {
availableFolders = emptyList(),
availableOwners = emptyList(),
),
isIndividualVaultDisabled = true,
type = VaultAddEditState.ViewState.Content.ItemType.Identity(
firstName = "John",
middleName = "Richard",
@ -141,6 +145,7 @@ class CipherViewExtensionsTest {
val result = cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
@ -165,6 +170,7 @@ class CipherViewExtensionsTest {
),
),
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Login(
username = "username",
password = "password",
@ -183,6 +189,7 @@ class CipherViewExtensionsTest {
val result = cipherView.toViewState(
isClone = false,
isIndividualVaultDisabled = true,
resourceManager = resourceManager,
)
@ -202,6 +209,7 @@ class CipherViewExtensionsTest {
availableFolders = emptyList(),
availableOwners = emptyList(),
),
isIndividualVaultDisabled = true,
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
),
result,
@ -214,6 +222,7 @@ class CipherViewExtensionsTest {
val result = cipherView.toViewState(
isClone = true,
isIndividualVaultDisabled = false,
resourceManager = resourceManager,
)
@ -233,6 +242,7 @@ class CipherViewExtensionsTest {
availableFolders = emptyList(),
availableOwners = emptyList(),
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
),
result,

View file

@ -6,11 +6,14 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.repository.model.Environment
import com.x8bit.bitwarden.data.platform.repository.util.baseIconUrl
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
@ -52,6 +55,11 @@ class VaultViewModelTest : BaseViewModelTest() {
private val clipboardManager: BitwardenClipboardManager = mockk {
every { setText(any<String>()) } just runs
}
private val policyManager: PolicyManager = mockk {
every {
getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns emptyList()
}
private val mutablePullToRefreshEnabledFlow = MutableStateFlow(false)
private val mutableIsIconLoadingDisabledFlow = MutableStateFlow(false)
@ -93,7 +101,10 @@ class VaultViewModelTest : BaseViewModelTest() {
fun `initial state should be correct and should trigger a syncIfNecessary call`() {
val viewModel = createViewModel()
assertEquals(DEFAULT_STATE, viewModel.stateFlow.value)
verify { vaultRepository.syncIfNecessary() }
verify {
vaultRepository.syncIfNecessary()
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
}
}
@Test
@ -143,7 +154,7 @@ class VaultViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `UserState updates with a non-null value when not switching accounts should update the account information in the state`() {
fun `UserState updates with a non-null value when not switching accounts should update the account information in the state when personal ownership enabled`() {
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE,
@ -207,6 +218,82 @@ class VaultViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `UserState updates with a non-null value when not switching accounts should update the account information in the state when personal ownership disabled`() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,
isEnabled = true,
data = null,
),
)
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE,
viewModel.stateFlow.value,
)
mutableUserStateFlow.value =
DEFAULT_USER_STATE.copy(
accounts = listOf(
UserState.Account(
userId = "activeUserId",
name = "Other User",
email = "active@bitwarden.com",
avatarColorHex = "#00aaaa",
environment = Environment.Us,
isPremium = true,
isLoggedIn = true,
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = listOf(
Organization(
id = "organizationId",
name = "Test Organization",
),
),
),
),
)
assertEquals(
DEFAULT_STATE.copy(
appBarTitle = R.string.vaults.asText(),
avatarColorString = "#00aaaa",
initials = "OU",
accountSummaries = listOf(
AccountSummary(
userId = "activeUserId",
name = "Other User",
email = "active@bitwarden.com",
avatarColorHex = "#00aaaa",
environmentLabel = "bitwarden.com",
isActive = true,
isLoggedIn = true,
isVaultUnlocked = true,
),
),
vaultFilterData = VaultFilterData(
selectedVaultFilterType = VaultFilterType.AllVaults,
vaultFilterTypes = listOf(
VaultFilterType.AllVaults,
VaultFilterType.OrganizationVault(
organizationId = "organizationId",
organizationName = "Test Organization",
),
),
),
),
viewModel.stateFlow.value,
)
}
@Test
fun `on LockAccountClick should call lockVault for the given account`() {
val accountUserId = "userId"
@ -1245,6 +1332,7 @@ class VaultViewModelTest : BaseViewModelTest() {
VaultViewModel(
authRepository = authRepository,
clipboardManager = clipboardManager,
policyManager = policyManager,
clock = clock,
settingsRepository = settingsRepository,
vaultRepository = vaultRepository,

View file

@ -273,13 +273,13 @@ class UserStateExtensionsTest {
isBiometricsEnabled = false,
organizations = emptyList(),
)
.toVaultFilterData(),
.toVaultFilterData(isIndividualVaultDisabled = false),
)
}
@Suppress("MaxLineLength")
@Test
fun `toVaultFilterData for an account with organizations should return data with the available types in the correct order`() {
fun `toVaultFilterData for an account with organizations and individual vault enabled should return data with the available types in the correct order`() {
assertEquals(
VaultFilterData(
selectedVaultFilterType = VaultFilterType.AllVaults,
@ -318,7 +318,55 @@ class UserStateExtensionsTest {
),
),
)
.toVaultFilterData(),
.toVaultFilterData(
isIndividualVaultDisabled = false,
),
)
}
@Suppress("MaxLineLength")
@Test
fun `toVaultFilterData for an account with organizations and individual vault disabled should return data with the available types in the correct order`() {
assertEquals(
VaultFilterData(
selectedVaultFilterType = VaultFilterType.AllVaults,
vaultFilterTypes = listOf(
VaultFilterType.AllVaults,
VaultFilterType.OrganizationVault(
organizationId = "organizationId-A",
organizationName = "Organization A",
),
VaultFilterType.OrganizationVault(
organizationId = "organizationId-B",
organizationName = "Organization B",
),
),
),
UserState.Account(
userId = "activeUserId",
name = "name",
email = "email",
avatarColorHex = "avatarColorHex",
environment = Environment.Us,
isPremium = true,
isLoggedIn = true,
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = listOf(
Organization(
id = "organizationId-B",
name = "Organization B",
),
Organization(
id = "organizationId-A",
name = "Organization A",
),
),
)
.toVaultFilterData(
isIndividualVaultDisabled = true,
),
)
}
}

View file

@ -47,6 +47,7 @@ class VaultAddItemStateExtensionsTest {
notes = "mockNotes-1",
selectedOwnerId = "mockOwnerId-1",
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Login(
username = "mockUsername-1",
password = "mockPassword-1",
@ -124,6 +125,7 @@ class VaultAddItemStateExtensionsTest {
notes = "mockNotes-1",
selectedOwnerId = "mockOwnerId-1",
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Login(
username = "mockUsername-1",
password = "mockPassword-1",
@ -212,6 +214,7 @@ class VaultAddItemStateExtensionsTest {
VaultAddEditState.Custom.HiddenField("testId", "TestHidden", "TestHidden"),
),
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
)
@ -281,6 +284,7 @@ class VaultAddItemStateExtensionsTest {
selectedOwnerId = "mockOwnerId-1",
customFieldData = emptyList(),
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.SecureNotes,
)
@ -314,6 +318,7 @@ class VaultAddItemStateExtensionsTest {
notes = "mockNotes-1",
selectedOwnerId = "mockOwnerId-1",
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Identity(
selectedTitle = VaultIdentityTitle.MR,
firstName = "mockFirstName",
@ -411,6 +416,7 @@ class VaultAddItemStateExtensionsTest {
notes = "mockNotes-1",
selectedOwnerId = "mockOwnerId-1",
),
isIndividualVaultDisabled = false,
type = VaultAddEditState.ViewState.Content.ItemType.Identity(
selectedTitle = VaultIdentityTitle.MR,
firstName = "mockFirstName",