Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions BitwardenShared/Core/Platform/Models/Enum/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,13 @@ extension FeatureFlag: @retroactive CaseIterable {
/// Flag to enable/disable forced KDF updates.
static let forceUpdateKdfSettings = FeatureFlag(rawValue: "pm-18021-force-update-kdf-settings")

/// A feature flag to enable the removal of card item types.
static let removeCardPolicy = FeatureFlag(
rawValue: "pm-16442-remove-card-item-type-policy",
)

public static var allCases: [FeatureFlag] {
[
.cxpExportMobile,
.cxpImportMobile,
.cipherKeyEncryption,
.enableCipherKeyEncryption,
.forceUpdateKdfSettings,
.removeCardPolicy,
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,10 @@ struct DefaultVaultListDataPreparator: VaultListDataPreparator {

// MARK: Private

/// Returns the restricted organization IDs for the `.restrictItemTypes` policy if enabled
/// and adds them to the builder.
/// Returns the restricted organization IDs for the `.restrictItemTypes` policy and adds them
/// to the builder.
/// - Returns: The restricted organization IDs.
func prepareRestrictedOrganizationIds(builder: VaultListPreparedDataBuilder) async -> [String] {
guard await configService.getFeatureFlag(.removeCardPolicy) else {
return []
}
let restrictedOrganizationIds = await policyService.getOrganizationIdsForRestricItemTypesPolicy()
builder.prepareRestrictItemsPolicyOrganizations(restrictedOrganizationIds: restrictedOrganizationIds)
return restrictedOrganizationIds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"addItemForGroup",
])
XCTAssertNotNil(result)
Expand Down Expand Up @@ -147,6 +148,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"addFido2Item",
])
XCTAssertNotNil(result)
Expand All @@ -156,7 +158,6 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
/// cipher as it doesn't pass restrict item type policy.
@MainActor
func test_prepareAutofillCombinedSingleData_doesNotPassRestrictItemPolicy() async throws {
configService.featureFlagsBool[.removeCardPolicy] = true
ciphersClientWrapperService.decryptAndProcessCiphersInBatchOnCipherParameterToPass = .fixture(
id: "1",
organizationId: "1",
Expand Down Expand Up @@ -201,7 +202,9 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
filter: VaultListFilter(uri: "https://example.com"),
)

XCTAssertTrue(mockCallOrderHelper.callOrder.isEmpty)
XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
])
XCTAssertNotNil(result)
}

Expand All @@ -228,6 +231,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
"incrementTOTPCount",
Expand All @@ -254,6 +258,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
"addCipherDecryptionFailure",
Expand Down Expand Up @@ -282,6 +287,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
])
Expand All @@ -297,7 +303,6 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
organizationId: "1",
type: .card(.fixture()),
)
configService.featureFlagsBool[.removeCardPolicy] = true
policyService.policyAppliesToUserPolicies = [.fixture(organizationId: "1")]

let result = try await subject.prepareData(
Expand All @@ -316,48 +321,14 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
}

/// `prepareData(from:collections:folders:filter:)` returns the prepared data without filtering out cipher even
/// with restricted item types policy but with `.removeCardPolicy` off.
@MainActor
func test_prepareData_preparedDataNoFilteringOutCipherWithRestrictedItemsPolicyButCardFlagOff() async throws {
ciphersClientWrapperService.decryptAndProcessCiphersInBatchOnCipherParameterToPass = .fixture(
organizationId: "1",
type: .card(.fixture()),
)

configService.featureFlagsBool[.removeCardPolicy] = false
policyService.policyAppliesToUserPolicies = [.fixture(organizationId: "1")]

let result = try await subject.prepareData(
from: [.fixture(organizationId: "1", type: .card)],
collections: [.fixture(id: "1"), .fixture(id: "2")],
folders: [.fixture(id: "1"), .fixture(id: "2"), .fixture(id: "3")],
filter: VaultListFilter(addTOTPGroup: true),
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareFolders",
"prepareCollections",
"incrementTOTPCount",
"addCipherDecryptionFailure",
"addFolderItem",
"addFavoriteItem",
"addNoFolderItem",
"incrementCipherTypeCount",
"incrementCollectionCount",
])
XCTAssertNotNil(result)
}

/// `prepareData(from:collections:folders:filter:)` returns the prepared data without filtering out cipher even
/// with `.removeCardPolicy` flag on, restricted item types policy without matching organization.
/// with restricted item types policy without matching organization.
@MainActor
func test_prepareData_preparedDataNoFilteringOutCipherWithRestrictedItemsPolicyNonMatchingOrgs() async throws {
ciphersClientWrapperService.decryptAndProcessCiphersInBatchOnCipherParameterToPass = .fixture(
organizationId: "1",
type: .card(.fixture()),
)

configService.featureFlagsBool[.removeCardPolicy] = true
policyService.policyAppliesToUserPolicies = [.fixture(organizationId: "2")]

let result = try await subject.prepareData(
Expand Down Expand Up @@ -399,6 +370,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
"incrementCipherDeletedCount",
Expand Down Expand Up @@ -434,6 +406,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
])
Expand All @@ -449,7 +422,6 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
organizationId: "1",
type: .card(.fixture()),
)
configService.featureFlagsBool[.removeCardPolicy] = true
policyService.policyAppliesToUserPolicies = [.fixture(organizationId: "1")]

let result = try await subject.prepareGroupData(
Expand Down Expand Up @@ -480,6 +452,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi

// should not call incrementCollectionCount and addItemForGroup
XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
])
Expand All @@ -501,6 +474,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
"addFolderItem",
Expand All @@ -524,6 +498,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
"incrementCollectionCount",
Expand All @@ -547,31 +522,15 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
}

/// `prepareGroupData(from:collections:folders:filter:)` returns the prepared data
/// when not filtering by folder nor collection with restricted items policy but `.removeCardPolicy` flag off.
@MainActor
func test_prepareGroupData_cardRestrictedItemsTypeCardFlagOff() async throws {
ciphersClientWrapperService.decryptAndProcessCiphersInBatchOnCipherParameterToPass = .fixture(
id: "1",
organizationId: "1",
type: .card(.fixture()),
)
configService.featureFlagsBool[.removeCardPolicy] = false
policyService.policyAppliesToUserPolicies = [.fixture(organizationId: "1")]

try await prepareGroupDataGenericTest(group: .card)
}

/// `prepareGroupData(from:collections:folders:filter:)` returns the prepared data
/// when not filtering by folder nor collection with `.removeCardPolicy` flag on and restricted items policy
/// when not filtering by folder nor collection with restricted items policy
/// non-matching organization IDs.
@MainActor
func test_prepareGroupData_cardWithCardFlagOffAndNonMatchingRestrictedItemsTypeOrgs() async throws {
func test_prepareGroupData_cardNonMatchingRestrictedItemsTypeOrgs() async throws {
ciphersClientWrapperService.decryptAndProcessCiphersInBatchOnCipherParameterToPass = .fixture(
id: "1",
organizationId: "1",
type: .card(.fixture()),
)
configService.featureFlagsBool[.removeCardPolicy] = true
policyService.policyAppliesToUserPolicies = [.fixture(organizationId: "2")]

let result = try await subject.prepareGroupData(
Expand Down Expand Up @@ -627,17 +586,17 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"addItemWithMatchResultCipher",
])
XCTAssertNotNil(result)
XCTAssertEqual(cipherMatchingHelper.doesCipherMatchReceivedCipher?.id, "1")
}

/// `prepareAutofillPasswordsData(from:filter:)` returns the prepared data filtering out cipher as it doesn't pass
/// restrict item type policy..
/// restrict item type policy.
@MainActor
func test_prepareAutofillPasswordsData_doesNotPassRestrictItemPolicy() async throws {
configService.featureFlagsBool[.removeCardPolicy] = true
ciphersClientWrapperService.decryptAndProcessCiphersInBatchOnCipherParameterToPass = .fixture(
id: "1",
organizationId: "1",
Expand Down Expand Up @@ -685,6 +644,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
])
XCTAssertNotNil(result)
XCTAssertNil(cipherMatchingHelper.doesCipherMatchReceivedCipher)
Expand All @@ -703,6 +663,7 @@ class VaultListDataPreparatorTests: BitwardenTestCase { // swiftlint:disable:thi
)

XCTAssertEqual(mockCallOrderHelper.callOrder, [
"prepareRestrictItemsPolicyOrganizations",
"prepareFolders",
"prepareCollections",
"addItemForGroup",
Expand Down
16 changes: 3 additions & 13 deletions BitwardenShared/Core/Vault/Repositories/VaultRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ class DefaultVaultRepository { // swiftlint:disable:this type_body_length
let isMatchingCipher: (CipherListView) -> Bool = isActive
? { $0.deletedDate == nil }
: { $0.deletedDate != nil }
let restrictItemTypesOrgIds = await getRestrictItemTypesOrgIds()
let restrictItemTypesOrgIds = await policyService.getOrganizationIdsForRestricItemTypesPolicy()

return try await cipherService.ciphersPublisher().asyncTryMap { ciphers -> [CipherListView] in
// Convert the Ciphers to CipherViews and filter appropriately.
Expand Down Expand Up @@ -814,7 +814,7 @@ class DefaultVaultRepository { // swiftlint:disable:this type_body_length
collections: [Collection],
folders: [Folder] = [],
) async throws -> [VaultListSection] {
let restrictItemTypesOrgIds = await getRestrictItemTypesOrgIds()
let restrictItemTypesOrgIds = await policyService.getOrganizationIdsForRestricItemTypesPolicy()
let ciphers = try await clientService.vault().ciphers().decryptListWithFailures(ciphers: ciphers)
.successes
.filter { cipher in
Expand Down Expand Up @@ -873,15 +873,6 @@ class DefaultVaultRepository { // swiftlint:disable:this type_body_length
return !restrictItemTypesOrgIds.contains(orgId)
}

/// If `FeatureFlag.removeCardPolicy` feature flag is enabled, gets the organization IDs that have the
/// `PolicyType.restrictItemTypes` policy active.
///
/// - Returns: A list of organization IDs that have the restrictItemTypes policy enabled.
private func getRestrictItemTypesOrgIds() async -> [String] {
guard await configService.getFeatureFlag(.removeCardPolicy) else { return [] }
return await policyService.getOrganizationIdsForRestricItemTypesPolicy()
}

/// Returns a list of the sections in the vault list from a sync response.
///
/// - Parameters:
Expand All @@ -897,7 +888,7 @@ class DefaultVaultRepository { // swiftlint:disable:this type_body_length
folders: [Folder],
filter: VaultListFilter,
) async throws -> [VaultListSection] {
let restrictItemTypesOrgIds = await getRestrictItemTypesOrgIds()
let restrictItemTypesOrgIds = await policyService.getOrganizationIdsForRestricItemTypesPolicy()
let ciphers = try await clientService.vault().ciphers().decryptListWithFailures(ciphers: ciphers)
.successes
.filter { cipher in
Expand Down Expand Up @@ -1154,7 +1145,6 @@ extension DefaultVaultRepository: VaultRepository {

func getItemTypesUserCanCreate() async -> [CipherType] {
let itemTypes: [CipherType] = CipherType.canCreateCases.reversed()
guard await configService.getFeatureFlag(.removeCardPolicy) else { return itemTypes }
let restrictItemTypesOrgIds = await policyService.getOrganizationIdsForRestricItemTypesPolicy()
if !restrictItemTypesOrgIds.isEmpty {
return itemTypes.filter { $0 != .card }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -861,11 +861,10 @@ class VaultRepositoryTests: BitwardenTestCase { // swiftlint:disable:this type_b
}

/// `getItemTypesUserCanCreate()` gets the user's available item types for item creation
/// when feature flag is true and true are policies enabled.
/// when policies are enabled.
@MainActor
func test_getItemTypesUserCanCreate() async throws {
stateService.activeAccount = .fixture()
configService.featureFlagsBool[.removeCardPolicy] = true
policyService.policyAppliesToUserPolicies = [
.fixture(
enabled: true,
Expand All @@ -883,30 +882,10 @@ class VaultRepositoryTests: BitwardenTestCase { // swiftlint:disable:this type_b
}

/// `getItemTypesUserCanCreate()` gets the user's available item types for item creation
/// when feature flag is false.
@MainActor
func test_getItemTypesUserCanCreate_flag_false() async throws {
stateService.activeAccount = .fixture()
configService.featureFlagsBool[.removeCardPolicy] = false
policyService.policyAppliesToUserPolicies = [
.fixture(
enabled: true,
id: "restrict_item_type",
organizationId: "org1",
type: .restrictItemTypes,
),
]

let result = await subject.getItemTypesUserCanCreate()
XCTAssertEqual(result, [.secureNote, .identity, .card, .login])
}

/// `getItemTypesUserCanCreate()` gets the user's available item types for item creation
/// when feature flag is true and no policies apply to the user.
/// when no policies apply to the user.
@MainActor
func test_getItemTypesUserCanCreate_no_policies() async throws {
stateService.activeAccount = .fixture()
configService.featureFlagsBool[.removeCardPolicy] = true
policyService.policyAppliesToUserPolicies = []

let result = await subject.getItemTypesUserCanCreate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,7 @@ class DefultExportVaultService: ExportVaultService {
}

func fetchAllCiphersToExport() async throws -> [Cipher] {
var restrictedTypes: [CipherType] = []
if await configService.getFeatureFlag(.removeCardPolicy) {
restrictedTypes = await policyService.getRestrictedItemCipherTypes()
}
let restrictedTypes = await policyService.getRestrictedItemCipherTypes()

return try await cipherService.fetchAllCiphers().filter { cipher in
cipher.deletedDate == nil
Expand Down
Loading