From ab90f5ff9527949cd0fa78a0941b9adfd2cbfa81 Mon Sep 17 00:00:00 2001 From: Patrick Honkonen <1883101+SaintPatrck@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:43:23 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=8D=92[PM-25057]=20Refactor=20card=20rest?= =?UTF-8?q?riction=20logic=20in=20AutofillCipherProvider=20(#5791)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../provider/AutofillCipherProviderImpl.kt | 25 ++++++++++++++++++- .../processor/AutofillCipherProviderTest.kt | 19 ++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/provider/AutofillCipherProviderImpl.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/provider/AutofillCipherProviderImpl.kt index ea232e7a35..e5ee01de22 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/provider/AutofillCipherProviderImpl.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/autofill/provider/AutofillCipherProviderImpl.kt @@ -71,7 +71,9 @@ class AutofillCipherProviderImpl( // Must not require a reprompt. it.reprompt == CipherRepromptType.NONE && // Must not be restricted by organization. - it.organizationId !in organizationIdsWithCardTypeRestrictions + !it.isExcludedByOrgCardRestrictions( + organizationIdsWithCardTypeRestrictions, + ) } ?.let { nonNullCipherListView -> nonNullCipherListView.id?.let { cipherId -> @@ -154,4 +156,25 @@ class AutofillCipherProviderImpl( is GetCipherResult.Success -> result.cipherView } + + /** + * Checks if this [CipherListView] item should be excluded from autofill due to + * organization-based card type restrictions. + * + * It's considered restricted if: + * 1. There are organizations with card type restrictions AND this item is a personal vault item + * (organizationId is null). + * 2. OR this item belongs to an organization that has card type restrictions. + */ + private fun CipherListView.isExcludedByOrgCardRestrictions( + restrictingOrgIds: List, + ): Boolean { + if (restrictingOrgIds.isEmpty()) { + return false + } + // If personal vault (no orgId), restricted if any org has restrictions. + return organizationId == null || + // If part of an org, restricted if that org is in the restricting list. + organizationId in restrictingOrgIds + } } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/processor/AutofillCipherProviderTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/processor/AutofillCipherProviderTest.kt index ad5fbf8983..766be06c60 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/processor/AutofillCipherProviderTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/autofill/processor/AutofillCipherProviderTest.kt @@ -279,7 +279,13 @@ class AutofillCipherProviderTest { every { deletedDate } returns null every { type } returns CipherListViewType.Card(cardListView) every { reprompt } returns CipherRepromptType.NONE - every { organizationId } returns ORGANIZATION_ID + every { organizationId } returns ORGANIZATION_ID_WITH_CARD_TYPE_RESTRICTIONS + } + val personalVaultCardCipherView: CipherListView = mockk { + every { deletedDate } returns null + every { type } returns CipherListViewType.Card(cardListView) + every { reprompt } returns CipherRepromptType.NONE + every { organizationId } returns null } val decryptCipherListViewsResult = DecryptCipherListResult( successes = listOf( @@ -287,6 +293,7 @@ class AutofillCipherProviderTest { deletedCardCipherView, repromptCardCipherView, restrictedCardCipherView, + personalVaultCardCipherView, loginCipherListViewWithTotp, loginCipherListViewWithoutTotp, ), @@ -295,7 +302,12 @@ class AutofillCipherProviderTest { every { policyManager.getActivePolicies(PolicyTypeJson.RESTRICT_ITEM_TYPES) - } returns listOf(createMockPolicy(number = 1, organizationId = ORGANIZATION_ID)) + } returns listOf( + createMockPolicy( + number = 1, + organizationId = ORGANIZATION_ID_WITH_CARD_TYPE_RESTRICTIONS, + ), + ) coEvery { vaultRepository.getCipher(CARD_CIPHER_ID) } returns GetCipherResult.Success( @@ -314,6 +326,7 @@ class AutofillCipherProviderTest { val expected = listOf( CARD_AUTOFILL_CIPHER, ) + every { cardCipherListView.organizationId } returns ORGANIZATION_ID every { cardCipherListView.subtitle } returns CARD_SUBTITLE // Test & Verify @@ -563,6 +576,8 @@ class AutofillCipherProviderTest { private const val ACTIVE_USER_ID = "activeUserId" private const val ORGANIZATION_ID = "organizationId" +private const val ORGANIZATION_ID_WITH_CARD_TYPE_RESTRICTIONS = + "organizationIdWithCardTypeRestrictions" private const val CARD_CARDHOLDER_NAME = "John Doe" private const val CARD_CODE = "123" private const val CARD_EXP_MONTH = "January"