Remove the RemoveCardPolicy feature flag (#5770)

This commit is contained in:
David Perez 2025-08-22 11:33:08 -05:00 committed by GitHub
parent a1c6276092
commit 517829e7b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 49 additions and 255 deletions

View File

@ -30,7 +30,6 @@ fun <T : Any> FlagKey<T>.ListItemContent(
FlagKey.CredentialExchangeProtocolExport,
FlagKey.CipherKeyEncryption,
FlagKey.UserManagedPrivilegedApps,
FlagKey.RemoveCardPolicy,
-> {
@Suppress("UNCHECKED_CAST")
BooleanFlagItem(
@ -79,7 +78,6 @@ private fun <T : Any> FlagKey<T>.getDisplayLabel(): String = when (this) {
stringResource(BitwardenString.user_trusted_privileged_app_management)
}
FlagKey.RemoveCardPolicy -> stringResource(BitwardenString.remove_card_policy)
FlagKey.BitwardenAuthenticationEnabled -> {
stringResource(BitwardenString.bitwarden_authentication_enabled)
}

View File

@ -4,7 +4,6 @@ import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.bitwarden.annotation.OmitFromCoverage
import com.bitwarden.core.data.manager.model.FlagKey
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.data.repository.util.baseIconUrl
import com.bitwarden.data.repository.util.baseWebSendUrl
@ -27,7 +26,6 @@ import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilitySele
import com.x8bit.bitwarden.data.autofill.manager.AutofillSelectionManager
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
import com.x8bit.bitwarden.data.autofill.util.login
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
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
@ -69,8 +67,6 @@ import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@ -99,7 +95,6 @@ class SearchViewModel @Inject constructor(
private val organizationEventManager: OrganizationEventManager,
private val vaultRepo: VaultRepository,
private val authRepo: AuthRepository,
featureFlagManager: FeatureFlagManager,
environmentRepo: EnvironmentRepository,
settingsRepo: SettingsRepository,
snackbarRelayManager: SnackbarRelayManager,
@ -155,24 +150,10 @@ class SearchViewModel @Inject constructor(
.onEach(::sendAction)
.launchIn(viewModelScope)
featureFlagManager
.getFeatureFlagFlow(FlagKey.RemoveCardPolicy)
.flatMapLatest { isFlagEnabled ->
if (isFlagEnabled) {
policyManager
.getActivePoliciesFlow(type = PolicyTypeJson.RESTRICT_ITEM_TYPES)
.map { policies ->
policies.map { it.organizationId }
}
} else {
flowOf(emptyList<String>())
}
}
.map { organizationIds ->
SearchAction.Internal.RestrictItemTypesPolicyUpdateReceive(
restrictItemTypesPolicyOrdIds = organizationIds,
)
}
policyManager
.getActivePoliciesFlow(type = PolicyTypeJson.RESTRICT_ITEM_TYPES)
.map { policies -> policies.map { it.organizationId } }
.map { SearchAction.Internal.RestrictItemTypesPolicyUpdateReceive(it) }
.onEach(::sendAction)
.launchIn(viewModelScope)

View File

@ -4,7 +4,6 @@ import android.net.Uri
import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.bitwarden.core.data.manager.model.FlagKey
import com.bitwarden.core.data.util.toFormattedPattern
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.ui.platform.base.BaseViewModel
@ -19,7 +18,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.PasswordStrengthResult
import com.x8bit.bitwarden.data.auth.repository.model.RequestOtpResult
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifyOtpResult
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEvent
@ -55,7 +53,6 @@ class ExportVaultViewModel @Inject constructor(
private val vaultRepository: VaultRepository,
private val fileManager: FileManager,
private val clock: Clock,
private val featureFlagManager: FeatureFlagManager,
private val organizationEventManager: OrganizationEventManager,
) : BaseViewModel<ExportVaultState, ExportVaultEvent, ExportVaultAction>(
initialState = savedStateHandle[KEY_STATE]
@ -467,19 +464,14 @@ class ExportVaultViewModel @Inject constructor(
}
private fun getRestrictedItemTypes(): List<CipherType> {
val isRemoveCardPolicyFeatureEnabled =
featureFlagManager.getFeatureFlag(FlagKey.RemoveCardPolicy)
if (!isRemoveCardPolicyFeatureEnabled) {
return emptyList()
val hasActiveRestrictItemTypesPolicy = policyManager
.getActivePolicies(type = PolicyTypeJson.RESTRICT_ITEM_TYPES)
.isNotEmpty()
return if (!hasActiveRestrictItemTypesPolicy) {
emptyList()
} else {
listOf(CipherType.CARD)
}
val hasActiveRestrictItemTypesPolicy =
policyManager.getActivePolicies(type = PolicyTypeJson.RESTRICT_ITEM_TYPES).isNotEmpty()
if (!hasActiveRestrictItemTypesPolicy) {
return emptyList()
}
return listOf(CipherType.CARD)
}
}
@ -534,7 +526,7 @@ sealed class ExportVaultEvent {
data object NavigateBack : ExportVaultEvent()
/**
* Shows a toast with the given [message].
* Shows a toast with the given [data].
*/
data class ShowSnackbar(
val data: BitwardenSnackbarData,

View File

@ -110,7 +110,6 @@ import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@ -212,15 +211,7 @@ class VaultItemListingViewModel @Inject constructor(
policyManager
.getActivePoliciesFlow(type = PolicyTypeJson.RESTRICT_ITEM_TYPES)
.combine(
featureFlagManager.getFeatureFlagFlow(FlagKey.RemoveCardPolicy),
) { policies, enabledFlag ->
if (enabledFlag) {
policies.map { it.organizationId }
} else {
emptyList()
}
}
.map { policies -> policies.map { it.organizationId } }
.map { VaultItemListingsAction.Internal.RestrictItemTypesPolicyUpdateReceive(it) }
.onEach(::sendAction)
.launchIn(viewModelScope)

View File

@ -3,7 +3,6 @@ package com.x8bit.bitwarden.ui.vault.feature.vault
import android.os.Parcelable
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.viewModelScope
import com.bitwarden.core.data.manager.model.FlagKey
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.core.util.persistentListOfNotNull
import com.bitwarden.data.repository.util.baseIconUrl
@ -28,7 +27,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.platform.datasource.disk.model.FlightRecorderDataSet
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
@ -67,7 +65,6 @@ import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
@ -99,7 +96,6 @@ class VaultViewModel @Inject constructor(
private val specialCircumstanceManager: SpecialCircumstanceManager,
private val networkConnectionManager: NetworkConnectionManager,
snackbarRelayManager: SnackbarRelayManager,
featureFlagManager: FeatureFlagManager,
) : BaseViewModel<VaultState, VaultEvent, VaultAction>(
initialState = run {
val userState = requireNotNull(authRepository.userStateFlow.value)
@ -194,15 +190,7 @@ class VaultViewModel @Inject constructor(
policyManager
.getActivePoliciesFlow(type = PolicyTypeJson.RESTRICT_ITEM_TYPES)
.combine(
featureFlagManager.getFeatureFlagFlow(FlagKey.RemoveCardPolicy),
) { policies, enabledFlag ->
if (enabledFlag && policies.isNotEmpty()) {
policies.map { it.organizationId }
} else {
null
}
}
.map { policies -> policies.map { it.organizationId } }
.map { VaultAction.Internal.PolicyUpdateReceive(it) }
.onEach(::sendAction)
.launchIn(viewModelScope)
@ -265,7 +253,7 @@ class VaultViewModel @Inject constructor(
val excludedOptions = persistentListOfNotNull(
CreateVaultItemType.SSH_KEY,
CreateVaultItemType.CARD.takeUnless {
state.restrictItemTypesPolicyOrgIds.isNullOrEmpty()
state.restrictItemTypesPolicyOrgIds.isEmpty()
},
)
@ -1045,7 +1033,7 @@ data class VaultState(
private val isPullToRefreshSettingEnabled: Boolean,
val baseIconUrl: String,
val isIconLoadingDisabled: Boolean,
val restrictItemTypesPolicyOrgIds: List<String>?,
val restrictItemTypesPolicyOrgIds: List<String>,
) : Parcelable {
/**
@ -1738,7 +1726,7 @@ sealed class VaultAction {
* Indicates that a policy update has been received.
*/
data class PolicyUpdateReceive(
val restrictItemTypesPolicyOrdIds: List<String>?,
val restrictItemTypesPolicyOrdIds: List<String>,
) : Internal()
/**
@ -1763,7 +1751,7 @@ private fun MutableStateFlow<VaultState>.updateToErrorStateOrDialog(
errorTitle: Text,
errorMessage: Text,
isRefreshing: Boolean,
restrictItemTypesPolicyOrgIds: List<String>?,
restrictItemTypesPolicyOrgIds: List<String>,
) {
this.update {
if (vaultData != null) {

View File

@ -42,13 +42,13 @@ fun VaultData.toViewState(
isIconLoadingDisabled: Boolean,
baseIconUrl: String,
vaultFilterType: VaultFilterType,
restrictItemTypesPolicyOrgIds: List<String>?,
restrictItemTypesPolicyOrgIds: List<String>,
): VaultState.ViewState {
val filteredCipherViewListWithDeletedItems =
decryptCipherListResult
.successes
.applyRestrictItemTypesPolicy(restrictItemTypesPolicyOrgIds ?: emptyList())
.applyRestrictItemTypesPolicy(restrictItemTypesPolicyOrgIds)
.toFilteredList(vaultFilterType)
val filteredCipherViewList = filteredCipherViewListWithDeletedItems
@ -154,7 +154,7 @@ fun VaultData.toViewState(
trashItemsCount = filteredCipherViewListWithDeletedItems.count {
it.deletedDate != null
},
showCardGroup = cardCount != 0 || restrictItemTypesPolicyOrgIds == null,
showCardGroup = cardCount != 0 || restrictItemTypesPolicyOrgIds.isEmpty(),
)
}
}

View File

@ -147,14 +147,12 @@ private val DEFAULT_MAP_VALUE: ImmutableMap<FlagKey<Any>, Any> = persistentMapOf
FlagKey.CredentialExchangeProtocolImport to true,
FlagKey.CredentialExchangeProtocolExport to true,
FlagKey.UserManagedPrivilegedApps to true,
FlagKey.RemoveCardPolicy to true,
)
private val UPDATED_MAP_VALUE: ImmutableMap<FlagKey<Any>, Any> = persistentMapOf(
FlagKey.CredentialExchangeProtocolImport to false,
FlagKey.CredentialExchangeProtocolExport to false,
FlagKey.UserManagedPrivilegedApps to false,
FlagKey.RemoveCardPolicy to false,
)
private val DEFAULT_STATE = DebugMenuState(

View File

@ -4,7 +4,6 @@ import android.net.Uri
import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test
import app.cash.turbine.turbineScope
import com.bitwarden.core.data.manager.model.FlagKey
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.data.datasource.disk.base.FakeDispatcherManager
@ -31,7 +30,6 @@ import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilitySele
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.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManagerImpl
@ -158,13 +156,6 @@ class SearchViewModelTest : BaseViewModelTest() {
} returns mutableSnackbarDataFlow
}
private val mutableRemoveCardPolicyFeatureFlow = MutableStateFlow(false)
private val featureFlagManager: FeatureFlagManager = mockk {
every {
getFeatureFlagFlow(FlagKey.RemoveCardPolicy)
} returns mutableRemoveCardPolicyFeatureFlow
}
@BeforeEach
fun setup() {
mockkStatic(
@ -1676,10 +1667,8 @@ class SearchViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly if RemoveCardPolicy flag is enable`() =
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly`() =
runTest {
mutableRemoveCardPolicyFeatureFlow.value = true
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE.copy(restrictItemTypesPolicyOrgIds = persistentListOf()),
@ -1705,33 +1694,6 @@ class SearchViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly if RemoveCardPolicy flag is disabled`() =
runTest {
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE,
viewModel.stateFlow.value,
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
isEnabled = true,
data = null,
),
),
)
assertEquals(
DEFAULT_STATE.copy(restrictItemTypesPolicyOrgIds = persistentListOf()),
viewModel.stateFlow.value,
)
}
@Test
fun `DecryptCipherErrorReceive should display error dialog`() = runTest {
val viewModel = createViewModel()
@ -1799,7 +1761,6 @@ class SearchViewModelTest : BaseViewModelTest() {
autofillSelectionManager = autofillSelectionManager,
organizationEventManager = organizationEventManager,
snackbarRelayManager = snackbarRelayManager,
featureFlagManager = featureFlagManager,
)
/**

View File

@ -3,7 +3,6 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.exportvault
import android.net.Uri
import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test
import com.bitwarden.core.data.manager.model.FlagKey
import com.bitwarden.data.repository.model.Environment
import com.bitwarden.exporters.ExportFormat
import com.bitwarden.network.model.PolicyTypeJson
@ -20,7 +19,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.RequestOtpResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifyOtpResult
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.event.OrganizationEventManager
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
@ -81,13 +79,6 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
} returns ExportVaultDataResult.Success("data")
}
private val fileManager: FileManager = mockk()
private val featureFlagManager: FeatureFlagManager = mockk {
every {
getFeatureFlag(FlagKey.RemoveCardPolicy)
} returns false
}
private val organizationEventManager = mockk<OrganizationEventManager> {
every { trackEvent(event = any()) } just runs
}
@ -143,7 +134,7 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `ConfirmExportVaultClicked correct password should call exportVaultDataToString with restricted item types when policy and feature flags enabled`() {
fun `ConfirmExportVaultClicked correct password should call exportVaultDataToString with restricted item types when policy`() {
val password = "password"
coEvery {
authRepository.validatePassword(
@ -153,9 +144,6 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.RESTRICT_ITEM_TYPES)
} returns listOf(createMockPolicy())
every {
featureFlagManager.getFeatureFlag(FlagKey.RemoveCardPolicy)
} returns true
val viewModel = createViewModel()
viewModel.trySendAction(ExportVaultAction.PasswordInputChanged(password))
@ -172,16 +160,13 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `ConfirmExportVaultClicked correct password should call exportVaultDataToString without restricted item types when policy is disabled and feature flag is enabled`() {
fun `ConfirmExportVaultClicked correct password should call exportVaultDataToString without restricted item types when policy is disabled`() {
val password = "password"
coEvery {
authRepository.validatePassword(
password = password,
)
} returns ValidatePasswordResult.Success(isValid = true)
every {
featureFlagManager.getFeatureFlag(FlagKey.RemoveCardPolicy)
} returns true
val viewModel = createViewModel()
viewModel.trySendAction(ExportVaultAction.PasswordInputChanged(password))
@ -845,7 +830,6 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
fileManager = fileManager,
vaultRepository = vaultRepository,
clock = clock,
featureFlagManager = featureFlagManager,
organizationEventManager = organizationEventManager,
)
}

View File

@ -250,14 +250,8 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
coEvery { addTrustedPrivilegedApp(any(), any()) } just runs
}
private val mutableRemoveCardPolicyFeatureFlow = MutableStateFlow(false)
private val featureFlagManager: FeatureFlagManager = mockk {
every {
getFeatureFlagFlow(FlagKey.RemoveCardPolicy)
} returns mutableRemoveCardPolicyFeatureFlow
every {
getFeatureFlag(FlagKey.UserManagedPrivilegedApps)
} returns true
every { getFeatureFlag(FlagKey.UserManagedPrivilegedApps) } returns true
}
private val initialState = createVaultItemListingState()
@ -376,10 +370,8 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly if RemoveCardPolicy flag is enable`() =
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly`() =
runTest {
mutableRemoveCardPolicyFeatureFlow.value = true
val viewModel = createVaultItemListingViewModel()
assertEquals(
initialState.copy(restrictItemTypesPolicyOrgIds = persistentListOf()),
@ -405,33 +397,6 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly if RemoveCardPolicy flag is disabled`() =
runTest {
val viewModel = createVaultItemListingViewModel()
assertEquals(
initialState,
viewModel.stateFlow.value,
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
isEnabled = true,
data = null,
),
),
)
assertEquals(
initialState.copy(restrictItemTypesPolicyOrgIds = persistentListOf()),
viewModel.stateFlow.value,
)
}
@Test
fun `on LockAccountClick should call lockVault for the given account`() {
val accountUserId = "userId"
@ -1392,7 +1357,6 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
@Test
fun `AddVaultItemClick inside a folder should hide card item selection dialog state when RESTRICT_ITEM_TYPES policy is enabled`() =
runTest {
mutableRemoveCardPolicyFeatureFlow.value = true
val viewModel = createVaultItemListingViewModel(
savedStateHandle = createSavedStateHandleWithVaultItemListingType(
vaultItemListingType = VaultItemListingType.Folder(folderId = "id"),
@ -1431,7 +1395,6 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
@Test
fun `AddVaultItemClick inside a collection should hide card item selection dialog state when RESTRICT_ITEM_TYPES policy is enabled`() =
runTest {
mutableRemoveCardPolicyFeatureFlow.value = true
val viewModel = createVaultItemListingViewModel(
savedStateHandle = createSavedStateHandleWithVaultItemListingType(
vaultItemListingType = VaultItemListingType.Collection(collectionId = "id"),
@ -5014,8 +4977,8 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
title = BitwardenString.an_error_has_occurred.asText(),
message =
BitwardenString
.credential_operation_failed_because_user_verification_was_cancelled
.asText(),
.credential_operation_failed_because_user_verification_was_cancelled
.asText(),
),
viewModel.stateFlow.value.dialogState,
)

View File

@ -2071,7 +2071,7 @@ private val DEFAULT_STATE: VaultState = VaultState(
isRefreshing = false,
showImportActionCard = false,
flightRecorderSnackBar = null,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
private val DEFAULT_CONTENT_VIEW_STATE: VaultState.ViewState.Content = VaultState.ViewState.Content(

View File

@ -1,7 +1,6 @@
package com.x8bit.bitwarden.ui.vault.feature.vault
import app.cash.turbine.test
import com.bitwarden.core.data.manager.model.FlagKey
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.data.repository.model.Environment
@ -25,7 +24,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.platform.datasource.disk.model.FlightRecorderDataSet
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
@ -171,13 +169,6 @@ class VaultViewModelTest : BaseViewModelTest() {
every { trackEvent(event = any()) } just runs
}
private val mutableRemoveCardPolicyFeatureFlow = MutableStateFlow(false)
private val mutableSshKeyVaultItemsEnabledFlow = MutableStateFlow(false)
private val featureFlagManager: FeatureFlagManager = mockk {
every {
getFeatureFlagFlow(FlagKey.RemoveCardPolicy)
} returns mutableRemoveCardPolicyFeatureFlow
}
private val reviewPromptManager: ReviewPromptManager = mockk()
private val specialCircumstanceManager: SpecialCircumstanceManager = mockk {
@ -219,7 +210,6 @@ class VaultViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `UserState updates with a non-null value when switching accounts should do nothing`() {
val viewModel = createViewModel()
@ -414,10 +404,8 @@ class VaultViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly if RemoveCardPolicy flag is enable`() =
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly`() =
runTest {
mutableRemoveCardPolicyFeatureFlow.value = true
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE,
@ -441,33 +429,6 @@ class VaultViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `RESTRICT_ITEM_TYPES policy changes should update restrictItemTypesPolicyOrgIds accordingly if RemoveCardPolicy flag is disabled`() =
runTest {
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE,
viewModel.stateFlow.value,
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
isEnabled = true,
data = null,
),
),
)
assertEquals(
DEFAULT_STATE.copy(restrictItemTypesPolicyOrgIds = null),
viewModel.stateFlow.value,
)
}
@Test
fun `Flight Recorder changes should update flightRecorderSnackbar accordingly`() = runTest {
mockkStatic(FlightRecorderDataSet::toSnackbarData)
@ -724,7 +685,7 @@ class VaultViewModelTest : BaseViewModelTest() {
isIconLoadingDisabled = viewModel.stateFlow.value.isIconLoadingDisabled,
baseIconUrl = viewModel.stateFlow.value.baseIconUrl,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
),
)
.copy(
@ -749,7 +710,7 @@ class VaultViewModelTest : BaseViewModelTest() {
isIconLoadingDisabled = viewModel.stateFlow.value.isIconLoadingDisabled,
baseIconUrl = viewModel.stateFlow.value.baseIconUrl,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
),
),
viewModel.stateFlow.value,
@ -759,7 +720,6 @@ class VaultViewModelTest : BaseViewModelTest() {
@Test
fun `vaultDataStateFlow Loaded with items should update state to Content`() = runTest {
mutableSshKeyVaultItemsEnabledFlow.value = true
mutableVaultDataStateFlow.tryEmit(
value = DataState.Loaded(
data = VaultData(
@ -1212,7 +1172,6 @@ class VaultViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `vaultDataStateFlow NoNetwork with items should update state to Content`() =
runTest {
@ -1313,7 +1272,6 @@ class VaultViewModelTest : BaseViewModelTest() {
@Test
fun `vaultDataStateFlow Loaded should include SSH key vault items`() =
runTest {
mutableSshKeyVaultItemsEnabledFlow.value = true
mutableVaultDataStateFlow.tryEmit(
value = DataState.Loaded(
data = VaultData(
@ -2593,7 +2551,6 @@ class VaultViewModelTest : BaseViewModelTest() {
@Test
fun `SelectAddItemType action should set dialog state to SelectVaultAddItemType accordingly when RESTRICT_ITEM_TYPES is enabled`() =
runTest {
mutableRemoveCardPolicyFeatureFlow.value = true
val viewModel = createViewModel()
mutableActivePoliciesFlow.emit(
listOf(
@ -2672,7 +2629,6 @@ class VaultViewModelTest : BaseViewModelTest() {
settingsRepository = settingsRepository,
vaultRepository = vaultRepository,
organizationEventManager = organizationEventManager,
featureFlagManager = featureFlagManager,
firstTimeActionManager = firstTimeActionManager,
snackbarRelayManager = snackbarRelayManager,
reviewPromptManager = reviewPromptManager,
@ -2787,5 +2743,5 @@ private fun createMockVaultState(
showImportActionCard = true,
isRefreshing = false,
flightRecorderSnackBar = null,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)

View File

@ -72,7 +72,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -144,7 +144,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.MyVault,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -204,7 +204,7 @@ class VaultDataExtensionsTest {
organizationName = "Mock Organization 1",
),
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -262,7 +262,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -289,7 +289,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -317,7 +317,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -359,7 +359,7 @@ class VaultDataExtensionsTest {
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -403,7 +403,7 @@ class VaultDataExtensionsTest {
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -447,7 +447,7 @@ class VaultDataExtensionsTest {
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -675,7 +675,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -719,7 +719,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -766,7 +766,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -820,7 +820,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -891,7 +891,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -1087,7 +1087,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(
@ -1146,7 +1146,7 @@ class VaultDataExtensionsTest {
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
vaultFilterType = VaultFilterType.AllVaults,
hasMasterPassword = true,
restrictItemTypesPolicyOrgIds = null,
restrictItemTypesPolicyOrgIds = emptyList(),
)
assertEquals(

View File

@ -26,7 +26,6 @@ fun <T : Any> FlagKey<T>.ListItemContent(
FlagKey.CipherKeyEncryption,
FlagKey.CredentialExchangeProtocolExport,
FlagKey.CredentialExchangeProtocolImport,
FlagKey.RemoveCardPolicy,
FlagKey.UserManagedPrivilegedApps,
-> BooleanFlagItem(
label = flagKey.getDisplayLabel(),
@ -72,7 +71,6 @@ private fun <T : Any> FlagKey<T>.getDisplayLabel(): String = when (this) {
stringResource(BitwardenString.user_trusted_privileged_app_management)
}
FlagKey.RemoveCardPolicy -> stringResource(BitwardenString.remove_card_policy)
FlagKey.BitwardenAuthenticationEnabled -> {
stringResource(BitwardenString.bitwarden_authentication_enabled)
}

View File

@ -33,7 +33,6 @@ sealed class FlagKey<out T : Any> {
CredentialExchangeProtocolImport,
CredentialExchangeProtocolExport,
UserManagedPrivilegedApps,
RemoveCardPolicy,
)
}
}
@ -72,15 +71,6 @@ sealed class FlagKey<out T : Any> {
override val defaultValue: Boolean = false
}
/**
* Data object holding the feature flag key to enable the removal of card item types.
* This flag will hide card types from organizations with policy enable and individual vaults
*/
data object RemoveCardPolicy : FlagKey<Boolean>() {
override val keyName: String = "pm-16442-remove-card-item-type-policy"
override val defaultValue: Boolean = false
}
/**
* Indicates the state of Bitwarden authentication.
*/

View File

@ -24,10 +24,6 @@ class FlagKeyTest {
FlagKey.UserManagedPrivilegedApps.keyName,
"pm-18970-user-managed-privileged-apps",
)
assertEquals(
FlagKey.RemoveCardPolicy.keyName,
"pm-16442-remove-card-item-type-policy",
)
assertEquals(
FlagKey.BitwardenAuthenticationEnabled.keyName,
"bitwarden-authentication-enabled",
@ -42,7 +38,6 @@ class FlagKeyTest {
FlagKey.CredentialExchangeProtocolExport,
FlagKey.CipherKeyEncryption,
FlagKey.UserManagedPrivilegedApps,
FlagKey.RemoveCardPolicy,
FlagKey.BitwardenAuthenticationEnabled,
).all {
!it.defaultValue

View File

@ -22,7 +22,6 @@
<string name="generate_error_report">Generate error report</string>
<string name="error_reports">Error reports</string>
<string name="user_trusted_privileged_app_management">User-trusted privileged app management</string>
<string name="remove_card_policy">Remove Card Policy</string>
<string name="bitwarden_authentication_enabled">Bitwarden authentication enabled</string>
<string name="import_format_label_bitwarden_json">Bitwarden (.json)</string>
<string name="import_format_label_2fas_json">2FAS (no password)</string>