mirror of
https://github.com/bitwarden/android.git
synced 2024-11-26 19:36:18 +03:00
BIT-782: Implement Personal Ownership policy support (#920)
This commit is contained in:
parent
f380e21600
commit
debfbc04b0
17 changed files with 427 additions and 29 deletions
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 ->
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue