diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt index 0d91faa5f60..49d4855481c 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt @@ -1060,7 +1060,7 @@ class AuthRepositoryImpl( ?: return RemovePasswordResult.Error(error = MissingPropertyException("User Key")) val keyConnectorUrl = organizations .find { - it.shouldUseKeyConnector && + it.isKeyConnectorEnabled && it.role != OrganizationType.OWNER && it.role != OrganizationType.ADMIN } diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt index 9103d3b1168..c616f46cda1 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt @@ -9,7 +9,7 @@ import com.bitwarden.network.model.OrganizationType * @property name The name of the organization (if applicable). * @property shouldManageResetPassword Indicates that this user has the permission to manage their * own password. - * @property shouldUseKeyConnector Indicates that the organization uses a key connector. + * @property isKeyConnectorEnabled Indicates that the organization uses a key connector. * @property role The user's role in the organization. * @property keyConnectorUrl The key connector domain (if applicable). * @property userIsClaimedByOrganization Indicates that the user is claimed by the organization. @@ -20,7 +20,7 @@ data class Organization( val id: String, val name: String, val shouldManageResetPassword: Boolean, - val shouldUseKeyConnector: Boolean, + val isKeyConnectorEnabled: Boolean, val role: OrganizationType, val keyConnectorUrl: String?, val userIsClaimedByOrganization: Boolean, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt index e9521a158a4..3f7f8485ad3 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt @@ -1,12 +1,24 @@ package com.x8bit.bitwarden.data.auth.repository.util import com.bitwarden.core.data.util.decodeFromStringOrNull +import com.bitwarden.network.model.MemberDecryptionType +import com.bitwarden.network.model.OrganizationStatusType +import com.bitwarden.network.model.OrganizationType +import com.bitwarden.network.model.ProductTierType +import com.bitwarden.network.model.ProviderType import com.bitwarden.network.model.SyncResponseJson +import com.bitwarden.organizations.OrganizationUserStatusType +import com.bitwarden.organizations.OrganizationUserType +import com.bitwarden.organizations.Permissions +import com.bitwarden.organizations.ProfileOrganization import com.bitwarden.policies.PolicyType import com.bitwarden.policies.PolicyView import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation import kotlinx.serialization.json.Json +import com.bitwarden.organizations.MemberDecryptionType as SdkMemberDecryptionType +import com.bitwarden.organizations.ProductTierType as SdkProductTierType +import com.bitwarden.organizations.ProviderType as SdkProviderType private val JSON = Json { ignoreUnknownKeys = true @@ -22,7 +34,7 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization? = Organization( id = this.id, name = it, - shouldUseKeyConnector = this.shouldUseKeyConnector, + isKeyConnectorEnabled = this.isKeyConnectorEnabled, role = this.type, shouldManageResetPassword = this.permissions.shouldManageResetPassword, keyConnectorUrl = this.keyConnectorUrl, @@ -39,6 +51,86 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization? = fun List.toOrganizations(): List = this.mapNotNull { it.toOrganization() } +/** + * Maps the given list of [SyncResponseJson.Profile.Organization] to a list of + * [ProfileOrganization]s. + */ +@Suppress("MaxLineLength") +fun List.toSdkProfileOrganizations(): List = + this.mapNotNull { it.toSdkProfileOrganization() } + +/** + * Maps the given [SyncResponseJson.Profile.Organization] to a [ProfileOrganization] or `null` if + * the [SyncResponseJson.Profile.Organization.name] is not present. + */ +@Suppress("LongMethod") +private fun SyncResponseJson.Profile.Organization.toSdkProfileOrganization(): ProfileOrganization? = + this.name?.let { + ProfileOrganization( + id = this.id, + name = it, + status = this.status.toSdkOrganizationUserStatusType(), + type = this.type.toSdkOrganizationUserType(), + enabled = this.isEnabled, + usePolicies = this.shouldUsePolicies, + useGroups = this.shouldUseGroups, + useDirectory = this.shouldUseDirectory, + useEvents = this.shouldUseEvents, + useTotp = this.shouldUseTotp, + use2fa = this.use2fa, + useApi = this.shouldUseApi, + useSso = this.useSso, + useOrganizationDomains = this.useOrganizationDomains, + useKeyConnector = this.shouldUseKeyConnector, + useScim = this.useScim, + useCustomPermissions = this.useCustomPermissions, + useResetPassword = this.useResetPassword, + useSecretsManager = this.useSecretsManager, + usePasswordManager = this.usePasswordManager, + useActivateAutofillPolicy = this.useActivateAutofillPolicy, + useAutomaticUserConfirmation = this.useAutomaticUserConfirmation, + selfHost = this.isSelfHost, + usersGetPremium = this.shouldUsersGetPremium, + seats = this.seats, + maxCollections = this.maxCollections, + maxStorageGb = this.maxStorageGb, + ssoBound = this.ssoBound, + identifier = this.identifier, + permissions = this.permissions.toSdkPermissions(), + resetPasswordEnrolled = this.resetPasswordEnrolled, + userId = this.userId, + organizationUserId = this.organizationUserId, + hasPublicAndPrivateKeys = this.hasPublicAndPrivateKeys, + providerId = this.providerId, + providerName = this.providerName, + providerType = this.providerType?.toSdkProviderType(), + isProviderUser = this.isProviderUser, + isMember = this.isMember, + familySponsorshipFriendlyName = this.familySponsorshipFriendlyName, + familySponsorshipAvailable = this.familySponsorshipAvailable, + productTierType = this.productTierType.toSdkProductTierType(), + keyConnectorEnabled = this.isKeyConnectorEnabled, + keyConnectorUrl = this.keyConnectorUrl, + familySponsorshipLastSyncDate = this.familySponsorshipLastSyncDate, + familySponsorshipValidUntil = this.familySponsorshipValidUntil, + familySponsorshipToDelete = this.familySponsorshipToDelete, + accessSecretsManager = this.accessSecretsManager, + limitCollectionCreation = this.limitCollectionCreation, + limitCollectionDeletion = this.limitCollectionDeletion, + limitItemDeletion = this.limitItemDeletion, + allowAdminAccessToAllCollectionItems = this.allowAdminAccessToAllCollectionItems, + userIsManagedByOrganization = this.userIsClaimedByOrganization, + useAccessIntelligence = this.useAccessIntelligence, + useAdminSponsoredFamilies = this.useAdminSponsoredFamilies, + useDisableSmAdsForUsers = this.useDisableSmAdsForUsers, + isAdminInitiated = this.isAdminInitiated, + ssoEnabled = this.ssoEnabled, + ssoMemberDecryptionType = this.ssoMemberDecryptionType?.toSdkMemberDecryptionType(), + usePhishingBlocker = this.usePhishingBlocker, + useMyItems = this.useMyItems, + ) + } + /** * Convert the JSON data of the [PolicyView] object into [PolicyInformation] data. */ @@ -64,3 +156,60 @@ val PolicyView.policyInformation: PolicyInformation? else -> null } } + +private fun SyncResponseJson.Profile.Permissions.toSdkPermissions(): Permissions = + Permissions( + accessEventLogs = this.accessEventLogs, + accessImportExport = this.accessImportExport, + accessReports = this.accessReports, + createNewCollections = this.createNewCollections, + editAnyCollection = this.editAnyCollection, + deleteAnyCollection = this.deleteAnyCollection, + manageGroups = this.manageGroups, + manageSso = this.manageSso, + managePolicies = this.shouldManagePolicies, + manageUsers = this.manageUsers, + manageResetPassword = this.shouldManageResetPassword, + manageScim = this.manageScim, + ) + +private fun OrganizationStatusType.toSdkOrganizationUserStatusType(): OrganizationUserStatusType = + when (this) { + OrganizationStatusType.REVOKED -> OrganizationUserStatusType.REVOKED + OrganizationStatusType.INVITED -> OrganizationUserStatusType.INVITED + OrganizationStatusType.ACCEPTED -> OrganizationUserStatusType.ACCEPTED + OrganizationStatusType.CONFIRMED -> OrganizationUserStatusType.CONFIRMED + } + +private fun OrganizationType.toSdkOrganizationUserType(): OrganizationUserType = + when (this) { + OrganizationType.OWNER -> OrganizationUserType.OWNER + OrganizationType.ADMIN -> OrganizationUserType.ADMIN + OrganizationType.USER -> OrganizationUserType.USER + OrganizationType.CUSTOM -> OrganizationUserType.CUSTOM + } + +private fun ProviderType.toSdkProviderType(): SdkProviderType = + when (this) { + ProviderType.MSP -> SdkProviderType.MSP + ProviderType.RESELLER -> SdkProviderType.RESELLER + ProviderType.BUSINESS_UNIT -> SdkProviderType.BUSINESS_UNIT + } + +private fun ProductTierType.toSdkProductTierType(): SdkProductTierType = + when (this) { + ProductTierType.FREE -> SdkProductTierType.FREE + ProductTierType.FAMILIES -> SdkProductTierType.FAMILIES + ProductTierType.TEAMS -> SdkProductTierType.TEAMS + ProductTierType.ENTERPRISE -> SdkProductTierType.ENTERPRISE + ProductTierType.TEAMS_STARTER -> SdkProductTierType.TEAMS_STARTER + } + +private fun MemberDecryptionType.toSdkMemberDecryptionType(): SdkMemberDecryptionType = + when (this) { + MemberDecryptionType.MASTER_PASSWORD -> SdkMemberDecryptionType.MASTER_PASSWORD + MemberDecryptionType.KEY_CONNECTOR -> SdkMemberDecryptionType.KEY_CONNECTOR + MemberDecryptionType.TRUSTED_DEVICE_ENCRYPTION -> { + SdkMemberDecryptionType.TRUSTED_DEVICE_ENCRYPTION + } + } diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModel.kt index 4cbdfff7a8d..1a994736ec5 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModel.kt @@ -32,7 +32,7 @@ class RemovePasswordViewModel @Inject constructor( val org = authRepository.userStateFlow.value ?.activeAccount ?.organizations - ?.firstOrNull { it.shouldUseKeyConnector } + ?.firstOrNull { it.isKeyConnectorEnabled } RemovePasswordState( input = "", diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModel.kt index 7ec6617c59d..e340c0e2ec1 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModel.kt @@ -268,7 +268,7 @@ class RootNavViewModel @Inject constructor( ?.let(::parseJwtTokenDataOrNull) ?.isExternal == true val usesKeyConnectorAndNotAdmin = this.activeAccount.organizations.any { - it.shouldUseKeyConnector && + it.isKeyConnectorEnabled && it.role != OrganizationType.OWNER && it.role != OrganizationType.ADMIN } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt index d0b7dd2f488..332db8c2ac0 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt @@ -5383,7 +5383,7 @@ class AuthRepositoryTest { val organizations = listOf( createMockOrganizationNetwork( number = 1, - shouldUseKeyConnector = true, + isKeyConnectorEnabled = true, type = OrganizationType.USER, keyConnectorUrl = null, ), @@ -5408,7 +5408,7 @@ class AuthRepositoryTest { val organizations = listOf( createMockOrganizationNetwork( number = 1, - shouldUseKeyConnector = true, + isKeyConnectorEnabled = true, type = OrganizationType.USER, keyConnectorUrl = url, ), @@ -5441,7 +5441,7 @@ class AuthRepositoryTest { val organizations = listOf( createMockOrganizationNetwork( number = 1, - shouldUseKeyConnector = true, + isKeyConnectorEnabled = true, type = OrganizationType.USER, keyConnectorUrl = url, ), @@ -5477,7 +5477,7 @@ class AuthRepositoryTest { val organizations = listOf( createMockOrganizationNetwork( number = 1, - shouldUseKeyConnector = true, + isKeyConnectorEnabled = true, type = OrganizationType.USER, keyConnectorUrl = url, ), @@ -5512,7 +5512,7 @@ class AuthRepositoryTest { val organizations = listOf( createMockOrganizationNetwork( number = 1, - shouldUseKeyConnector = true, + isKeyConnectorEnabled = true, type = OrganizationType.USER, keyConnectorUrl = url, ), diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/OrganizationUtil.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/OrganizationUtil.kt index 6c72c80d163..0f869b83760 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/OrganizationUtil.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/OrganizationUtil.kt @@ -22,7 +22,7 @@ fun createMockOrganization( id = id, name = name, shouldManageResetPassword = shouldManageResetPassword, - shouldUseKeyConnector = shouldUseKeyConnector, + isKeyConnectorEnabled = shouldUseKeyConnector, role = role, keyConnectorUrl = keyConnectorUrl, userIsClaimedByOrganization = userIsClaimedByOrganization, diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/ProfileOrganizationUtil.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/ProfileOrganizationUtil.kt new file mode 100644 index 00000000000..73c77d6aeb0 --- /dev/null +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/ProfileOrganizationUtil.kt @@ -0,0 +1,176 @@ +@file:Suppress("LongParameterList") + +package com.x8bit.bitwarden.data.auth.repository.model + +import com.bitwarden.organizations.MemberDecryptionType +import com.bitwarden.organizations.OrganizationUserStatusType +import com.bitwarden.organizations.OrganizationUserType +import com.bitwarden.organizations.Permissions +import com.bitwarden.organizations.ProductTierType +import com.bitwarden.organizations.ProfileOrganization +import com.bitwarden.organizations.ProviderType +import java.time.Instant + +/** + * Creates a mock [ProfileOrganization] with the given [number]. + */ +@Suppress("LongMethod") +fun createMockSdkProfileOrganization( + number: Int, + usePolicies: Boolean = false, + keyConnectorEnabled: Boolean = false, + keyConnectorUrl: String? = "mockKeyConnectorUrl-$number", + type: OrganizationUserType = OrganizationUserType.ADMIN, + seats: UInt? = 1u, + enabled: Boolean = false, + providerType: ProviderType? = ProviderType.RESELLER, + maxCollections: UInt? = 1u, + selfHost: Boolean = false, + permissions: Permissions = createMockSdkPermissions(), + providerId: String? = "mockProviderId-$number", + id: String = "mockId-$number", + useGroups: Boolean = false, + useDirectory: Boolean = false, + providerName: String? = "mockProviderName-$number", + usersGetPremium: Boolean = false, + maxStorageGb: UInt? = 1u, + identifier: String? = "mockIdentifier-$number", + use2fa: Boolean = false, + familySponsorshipToDelete: Boolean? = false, + userId: String? = "mockUserId-$number", + shouldUseEvents: Boolean = false, + familySponsorshipFriendlyName: String? = "mockFamilySponsorshipFriendlyName-$number", + useTotp: Boolean = false, + familySponsorshipLastSyncDate: Instant? = Instant.parse("2023-10-27T12:00:00Z"), + name: String = "mockName-$number", + useApi: Boolean = false, + familySponsorshipValidUntil: Instant? = Instant.parse("2023-10-27T12:00:00Z"), + status: OrganizationUserStatusType = OrganizationUserStatusType.CONFIRMED, + userIsClaimedByOrganization: Boolean = false, + limitItemDeletion: Boolean = false, + useSso: Boolean = false, + useOrganizationDomains: Boolean = false, + shouldUseKeyConnector: Boolean = false, + useScim: Boolean = false, + useCustomPermissions: Boolean = false, + useResetPassword: Boolean = false, + useSecretsManager: Boolean = false, + usePasswordManager: Boolean = false, + useActivateAutofillPolicy: Boolean = false, + useAutomaticUserConfirmation: Boolean = false, + ssoBound: Boolean = false, + resetPasswordEnrolled: Boolean = false, + organizationUserId: String? = "mockOrganizationUserId-$number", + hasPublicAndPrivateKeys: Boolean = false, + isProviderUser: Boolean = false, + isMember: Boolean = false, + familySponsorshipAvailable: Boolean = false, + productTierType: ProductTierType = ProductTierType.FREE, + accessSecretsManager: Boolean = false, + limitCollectionCreation: Boolean = false, + limitCollectionDeletion: Boolean = false, + allowAdminAccessToAllCollectionItems: Boolean = false, + useAccessIntelligence: Boolean = false, + useAdminSponsoredFamilies: Boolean = false, + useDisableSmAdsForUsers: Boolean = false, + isAdminInitiated: Boolean = false, + ssoEnabled: Boolean = false, + ssoMemberDecryptionType: MemberDecryptionType? = null, + usePhishingBlocker: Boolean = false, + useMyItems: Boolean = false, +): ProfileOrganization = + ProfileOrganization( + id = id, + name = name, + status = status, + type = type, + enabled = enabled, + usePolicies = usePolicies, + useGroups = useGroups, + useDirectory = useDirectory, + useEvents = shouldUseEvents, + useTotp = useTotp, + use2fa = use2fa, + useApi = useApi, + useSso = useSso, + useOrganizationDomains = useOrganizationDomains, + useKeyConnector = shouldUseKeyConnector, + useScim = useScim, + useCustomPermissions = useCustomPermissions, + useResetPassword = useResetPassword, + useSecretsManager = useSecretsManager, + usePasswordManager = usePasswordManager, + useActivateAutofillPolicy = useActivateAutofillPolicy, + useAutomaticUserConfirmation = useAutomaticUserConfirmation, + selfHost = selfHost, + usersGetPremium = usersGetPremium, + seats = seats, + maxCollections = maxCollections, + maxStorageGb = maxStorageGb, + ssoBound = ssoBound, + identifier = identifier, + permissions = permissions, + resetPasswordEnrolled = resetPasswordEnrolled, + userId = userId, + organizationUserId = organizationUserId, + hasPublicAndPrivateKeys = hasPublicAndPrivateKeys, + providerId = providerId, + providerName = providerName, + providerType = providerType, + isProviderUser = isProviderUser, + isMember = isMember, + familySponsorshipFriendlyName = familySponsorshipFriendlyName, + familySponsorshipAvailable = familySponsorshipAvailable, + productTierType = productTierType, + keyConnectorEnabled = keyConnectorEnabled, + keyConnectorUrl = keyConnectorUrl, + familySponsorshipLastSyncDate = familySponsorshipLastSyncDate, + familySponsorshipValidUntil = familySponsorshipValidUntil, + familySponsorshipToDelete = familySponsorshipToDelete, + accessSecretsManager = accessSecretsManager, + limitCollectionCreation = limitCollectionCreation, + limitCollectionDeletion = limitCollectionDeletion, + limitItemDeletion = limitItemDeletion, + allowAdminAccessToAllCollectionItems = allowAdminAccessToAllCollectionItems, + userIsManagedByOrganization = userIsClaimedByOrganization, + useAccessIntelligence = useAccessIntelligence, + useAdminSponsoredFamilies = useAdminSponsoredFamilies, + useDisableSmAdsForUsers = useDisableSmAdsForUsers, + isAdminInitiated = isAdminInitiated, + ssoEnabled = ssoEnabled, + ssoMemberDecryptionType = ssoMemberDecryptionType, + usePhishingBlocker = usePhishingBlocker, + useMyItems = useMyItems, + ) + +/** + * Create a mock [Permissions]. + */ +fun createMockSdkPermissions( + shouldManageResetPassword: Boolean = false, + shouldManagePolicies: Boolean = false, + accessEventLogs: Boolean = false, + accessImportExport: Boolean = false, + accessReports: Boolean = false, + createNewCollections: Boolean = false, + editAnyCollection: Boolean = false, + deleteAnyCollection: Boolean = false, + manageGroups: Boolean = false, + manageSso: Boolean = false, + manageUsers: Boolean = false, + manageScim: Boolean = false, +): Permissions = + Permissions( + manageResetPassword = shouldManageResetPassword, + managePolicies = shouldManagePolicies, + accessEventLogs = accessEventLogs, + accessImportExport = accessImportExport, + accessReports = accessReports, + createNewCollections = createNewCollections, + editAnyCollection = editAnyCollection, + deleteAnyCollection = deleteAnyCollection, + manageGroups = manageGroups, + manageSso = manageSso, + manageUsers = manageUsers, + manageScim = manageScim, + ) diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt index 3a686faca9f..0f8b12bfba9 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensionsTest.kt @@ -1,11 +1,14 @@ package com.x8bit.bitwarden.data.auth.repository.util import com.bitwarden.network.model.OrganizationType +import com.bitwarden.network.model.SyncResponseJson import com.bitwarden.network.model.createMockOrganizationNetwork import com.bitwarden.network.model.createMockPermissions +import com.bitwarden.organizations.ProfileOrganization import com.bitwarden.policies.PolicyType import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation import com.x8bit.bitwarden.data.auth.repository.model.createMockOrganization +import com.x8bit.bitwarden.data.auth.repository.model.createMockSdkProfileOrganization import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockPolicyView import kotlinx.serialization.json.Json import org.junit.jupiter.api.Assertions.assertEquals @@ -36,7 +39,7 @@ class SyncResponseJsonExtensionsTest { ), ), listOf( - createMockOrganizationNetwork(number = 1, shouldUseKeyConnector = true), + createMockOrganizationNetwork(number = 1, isKeyConnectorEnabled = true), createMockOrganizationNetwork( number = 2, type = OrganizationType.USER, @@ -47,6 +50,62 @@ class SyncResponseJsonExtensionsTest { ) } + @Test + fun `toSdkProfileOrganizations should correctly map a single organization`() { + assertEquals( + listOf(createMockSdkProfileOrganization(number = 1)), + listOf(createMockOrganizationNetwork(number = 1)).toSdkProfileOrganizations(), + ) + } + + @Test + fun `toSdkProfileOrganizations should correctly map multiple organizations`() { + assertEquals( + listOf( + createMockSdkProfileOrganization(number = 1), + createMockSdkProfileOrganization(number = 2), + ), + listOf( + createMockOrganizationNetwork(number = 1), + createMockOrganizationNetwork(number = 2), + ) + .toSdkProfileOrganizations(), + ) + } + + @Test + fun `toSdkProfileOrganizations should filter out organizations with null names`() { + assertEquals( + listOf(createMockSdkProfileOrganization(number = 1)), + listOf( + createMockOrganizationNetwork(number = 1), + createMockOrganizationNetwork(number = 2, name = null), + ) + .toSdkProfileOrganizations(), + ) + } + + @Suppress("MaxLineLength") + @Test + fun `toSdkProfileOrganizations should return empty list when all organizations have null names`() { + assertEquals( + emptyList(), + listOf( + createMockOrganizationNetwork(number = 1, name = null), + createMockOrganizationNetwork(number = 2, name = null), + ) + .toSdkProfileOrganizations(), + ) + } + + @Test + fun `toSdkProfileOrganizations should return empty list for empty input`() { + assertEquals( + emptyList(), + emptyList().toSdkProfileOrganizations(), + ) + } + @Test fun `policyInformation converts the MasterPassword Json data to policy information`() { val policyInformation = PolicyInformation.MasterPassword( diff --git a/network/src/main/kotlin/com/bitwarden/network/model/MemberDecryptionType.kt b/network/src/main/kotlin/com/bitwarden/network/model/MemberDecryptionType.kt new file mode 100644 index 00000000000..2c5986941df --- /dev/null +++ b/network/src/main/kotlin/com/bitwarden/network/model/MemberDecryptionType.kt @@ -0,0 +1,36 @@ +package com.bitwarden.network.model + +import androidx.annotation.Keep +import com.bitwarden.core.data.serializer.BaseEnumeratedIntSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * The type of encryption used for an SSO user organization. + */ +@Serializable(with = MemberDecryptionTypeSerializer::class) +enum class MemberDecryptionType { + /** + * Decryption using the user's master password. + */ + @SerialName("0") + MASTER_PASSWORD, + + /** + * Decryption via Key Connector. + */ + @SerialName("1") + KEY_CONNECTOR, + + /** + * Decryption via Trusted Device Encryption. + */ + @SerialName("2") + TRUSTED_DEVICE_ENCRYPTION, +} + +@Keep +private class MemberDecryptionTypeSerializer : BaseEnumeratedIntSerializer( + className = "MemberDecryptionType", + values = MemberDecryptionType.entries.toTypedArray(), +) diff --git a/network/src/main/kotlin/com/bitwarden/network/model/ProductTierType.kt b/network/src/main/kotlin/com/bitwarden/network/model/ProductTierType.kt new file mode 100644 index 00000000000..d57ba6c4e18 --- /dev/null +++ b/network/src/main/kotlin/com/bitwarden/network/model/ProductTierType.kt @@ -0,0 +1,48 @@ +package com.bitwarden.network.model + +import androidx.annotation.Keep +import com.bitwarden.core.data.serializer.BaseEnumeratedIntSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * The subscription tier of an organization. + */ +@Serializable(with = ProductTierTypeSerializer::class) +enum class ProductTierType { + /** + * Free tier with limited features. + */ + @SerialName("0") + FREE, + + /** + * Families plan for personal use. + */ + @SerialName("1") + FAMILIES, + + /** + * Teams plan for small organizations. + */ + @SerialName("2") + TEAMS, + + /** + * Enterprise plan with full features. + */ + @SerialName("3") + ENTERPRISE, + + /** + * Starter tier for small teams. + */ + @SerialName("4") + TEAMS_STARTER, +} + +@Keep +private class ProductTierTypeSerializer : BaseEnumeratedIntSerializer( + className = "ProductTierType", + values = ProductTierType.entries.toTypedArray(), +) diff --git a/network/src/main/kotlin/com/bitwarden/network/model/ProviderType.kt b/network/src/main/kotlin/com/bitwarden/network/model/ProviderType.kt new file mode 100644 index 00000000000..2df67fa5355 --- /dev/null +++ b/network/src/main/kotlin/com/bitwarden/network/model/ProviderType.kt @@ -0,0 +1,38 @@ +package com.bitwarden.network.model + +import androidx.annotation.Keep +import com.bitwarden.core.data.serializer.BaseEnumeratedIntSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * The type of provider. + */ +@Serializable(with = ProviderTypeSerializer::class) +enum class ProviderType { + /** + * Managed Service Provider - sells and manages its clients' Bitwarden organizations. + */ + @SerialName("0") + MSP, + + /** + * Reseller partner - sells Bitwarden to its clients but does not have any administrative + * access. + */ + @SerialName("1") + RESELLER, + + /** + * Business unit provider - used to manage multiple organizations which form part of a single + * large enterprise. + */ + @SerialName("2") + BUSINESS_UNIT, +} + +@Keep +private class ProviderTypeSerializer : BaseEnumeratedIntSerializer( + className = "ProviderType", + values = ProviderType.entries.toTypedArray(), +) diff --git a/network/src/main/kotlin/com/bitwarden/network/model/SyncResponseJson.kt b/network/src/main/kotlin/com/bitwarden/network/model/SyncResponseJson.kt index 949c1afb0a7..5cad606c4af 100644 --- a/network/src/main/kotlin/com/bitwarden/network/model/SyncResponseJson.kt +++ b/network/src/main/kotlin/com/bitwarden/network/model/SyncResponseJson.kt @@ -252,41 +252,108 @@ data class SyncResponseJson( val organizations: List? get() = newOrganizations ?: legacyOrganizations /** - * Represents an organization in the vault response. + * Represents an organization profile for the current user, containing the organization's + * feature flags, membership details, and configuration settings. * - * @property shouldUsePolicies If the organization should use policies. - * @property keyConnectorUrl The key connector URL of the organization (nullable). - * @property type The type of organization. - * @property seats The number of seats in the organization (nullable). - * @property isEnabled If the organization is enabled. - * @property providerType They type of provider for the organization (nullable). - * @property maxCollections The max collections of the organization (nullable). - * @property isSelfHost If the organization is self hosted. - * @property permissions The permissions of the organization. - * @property providerId The provider ID of the organization (nullable). - * @property id The ID of the organization. - * @property shouldUseGroups If the organization should use groups. - * @property shouldUseDirectory If the organization should use a directory. + * @property shouldUsePolicies Whether the organization has access to policies features. + * @property isKeyConnectorEnabled Whether Key Connector is enabled for this organization. + * @property keyConnectorUrl The URL of the Key Connector service, if enabled. + * @property type The user's role in the organization. + * @property seats The number of licensed seats for the organization. + * @property isEnabled Whether the organization is currently enabled. + * @property providerType The type of provider managing this organization, if any. + * @property isProviderUser Whether the current user accesses this organization through a + * provider. + * @property maxCollections The maximum number of collections the organization can create. + * @property isSelfHost Whether the organization can create a license file for a self-hosted + * instance. + * @property permissions The current user's custom permissions, relevant when + * [OrganizationType.CUSTOM] is the user's type. + * @property providerId The ID of the provider managing this organization, if any. + * @property id Unique identifier for the organization. + * @property shouldUseGroups Whether the organization has access to groups features. + * @property shouldUseDirectory Whether the organization has access to directory sync + * features. * @property key The key of the organization (nullable). - * @property providerName The provider name of the organization (nullable). - * @property shouldUsersGetPremium If users of the organization get Premium. - * @property maxStorageGb The max storage in Gb of the organization (nullable). - * @property identifier The identifier of the organization (nullable). - * @property use2fa If the organization uses 2FA. - * @property familySponsorshipToDelete If the organization has a - * family sponsorship to delete (nullable). - * @property userId The user id (nullable). - * @property shouldUseEvents If the organization should use events. - * @property familySponsorshipFriendlyName If the family sponsorship is a friendly name. - * @property shouldUseTotp If he organization should use TOTP. - * @property familySponsorshipLastSyncDate The last date the family sponsorship - * was synced (nullable). - * @property name The name of the organization (nullable). - * @property shouldUseApi If the organization should use API. - * @property familySponsorshipValidUntil The family sponsorship valid until - * of the organization (nullable). - * @property status The status of the organization. - * @property limitItemDeletion If the organization limits item deletion. + * @property providerName The name of the provider managing this organization, if any. + * @property shouldUsersGetPremium Whether organization members receive premium features. + * @property maxStorageGb The maximum encrypted storage in gigabytes, if limited. + * @property identifier The organization's SSO identifier. + * @property use2fa Whether the organization has access to two-factor authentication + * features. + * @property familySponsorshipToDelete Whether the families sponsorship is scheduled for + * deletion. + * @property userId The current user's personal user ID. + * @property shouldUseEvents Whether the organization has access to event logging features. + * @property familySponsorshipFriendlyName The friendly name of a pending families + * sponsorship, if any. + * @property shouldUseTotp Whether the organization can enforce TOTP for members. + * @property familySponsorshipLastSyncDate The date the families sponsorship was last + * synced, if applicable. + * @property name Display name of the organization. + * @property shouldUseApi Whether the organization has access to the Bitwarden Public API. + * @property familySponsorshipValidUntil The date the families sponsorship expires, if + * applicable. + * @property status The user's membership status in the organization. + * @property userIsClaimedByOrganization Whether the current user has been claimed by this + * organization. + * @property limitItemDeletion Whether item deletion is restricted to members with the + * Manage collection permission. When false, members with Edit permission can also delete + * items within their collections. + * @property useSso Whether the organization has access to SSO features. + * @property useOrganizationDomains Whether the organization can manage verified domains. + * @property useScim Whether the organization has access to SCIM provisioning. + * @property useCustomPermissions Whether the organization can use the + * [OrganizationType.CUSTOM] role. + * @property useResetPassword Whether the organization has access to the account recovery + * (admin password reset) feature. + * @property useSecretsManager Whether the organization has access to Secrets Manager. + * @property usePasswordManager Whether the organization has access to Password Manager. + * @property useActivateAutofillPolicy Whether the organization can use the activate + * autofill policy. + * @property useAutomaticUserConfirmation Whether the organization can automatically + * confirm new members without manual admin approval. + * @property ssoBound Whether the current user's account is bound to this organization + * via SSO. + * @property resetPasswordEnrolled Whether the current user is enrolled in account recovery + * for this organization. + * @property organizationUserId The current user's organization membership ID. + * @property hasPublicAndPrivateKeys Whether the organization has both a public and private + * key configured. + * @property isMember Whether the current user is a direct member of this organization (as + * opposed to provider-only access). + * @property familySponsorshipAvailable Whether the organization can sponsor a families + * plan for the current user. + * @property productTierType The subscription tier of the organization. + * @property shouldUseKeyConnector Whether the organization uses Key Connector for + * decryption. + * @property accessSecretsManager Whether the current user has access to Secrets Manager + * for this organization. + * @property limitCollectionCreation Whether collection creation is restricted to owners + * and admins only. When false, any member can create collections and automatically + * receives manage permissions over collections they create. + * @property limitCollectionDeletion Whether collection deletion is restricted to owners and + * admins only. When true, regular users cannot delete collections that they manage. + * @property allowAdminAccessToAllCollectionItems Whether owners and admins have implicit + * manage permissions over all collections. When true, owners and admins can alter items, + * groups, and permissions across all collections without requiring explicit collection + * assignments. When false, admins can only access collections where they have been + * explicitly assigned. + * @property useAccessIntelligence Whether the organization has access to Access + * Intelligence features. + * @property useAdminSponsoredFamilies Whether the organization can sponsor families plans + * for members (Families For Enterprises). + * @property useDisableSmAdsForUsers Whether Secrets Manager ads are disabled for users. + * @property isAdminInitiated Whether the organization's Families For Enterprises + * sponsorship was initiated by an admin. + * @property ssoEnabled Whether SSO login is currently enabled for this organization. + * @property ssoMemberDecryptionType The decryption type used for SSO members, if SSO is + * enabled. + * @property usePhishingBlocker Whether the organization has access to phishing blocker + * features. + * @property useMyItems Whether the organization has access to the My Items collection + * feature. This allows users to store personal items in the organization vault if the + * Centralize Organization Ownership policy is enabled. */ @Serializable data class Organization( @@ -294,7 +361,7 @@ data class SyncResponseJson( val shouldUsePolicies: Boolean, @SerialName("keyConnectorEnabled") - val shouldUseKeyConnector: Boolean, + val isKeyConnectorEnabled: Boolean, @SerialName("keyConnectorUrl") val keyConnectorUrl: String?, @@ -303,19 +370,19 @@ data class SyncResponseJson( val type: OrganizationType, @SerialName("seats") - val seats: Int?, + val seats: UInt?, @SerialName("enabled") val isEnabled: Boolean, @SerialName("providerType") - val providerType: Int?, + val providerType: ProviderType?, @SerialName("isProviderUser") val isProviderUser: Boolean = false, @SerialName("maxCollections") - val maxCollections: Int?, + val maxCollections: UInt?, @SerialName("selfHost") val isSelfHost: Boolean, @@ -345,7 +412,7 @@ data class SyncResponseJson( val shouldUsersGetPremium: Boolean, @SerialName("maxStorageGb") - val maxStorageGb: Int?, + val maxStorageGb: UInt?, @SerialName("identifier") val identifier: String?, @@ -390,6 +457,93 @@ data class SyncResponseJson( @SerialName("limitItemDeletion") val limitItemDeletion: Boolean = false, + + @SerialName("useSso") + val useSso: Boolean = false, + + @SerialName("useOrganizationDomains") + val useOrganizationDomains: Boolean = false, + + @SerialName("useScim") + val useScim: Boolean = false, + + @SerialName("useCustomPermissions") + val useCustomPermissions: Boolean = false, + + @SerialName("useResetPassword") + val useResetPassword: Boolean = false, + + @SerialName("useSecretsManager") + val useSecretsManager: Boolean = false, + + @SerialName("usePasswordManager") + val usePasswordManager: Boolean = false, + + @SerialName("useActivateAutofillPolicy") + val useActivateAutofillPolicy: Boolean = false, + + @SerialName("useAutomaticUserConfirmation") + val useAutomaticUserConfirmation: Boolean = false, + + @SerialName("ssoBound") + val ssoBound: Boolean = false, + + @SerialName("resetPasswordEnrolled") + val resetPasswordEnrolled: Boolean = false, + + @SerialName("organizationUserId") + val organizationUserId: String?, + + @SerialName("hasPublicAndPrivateKeys") + val hasPublicAndPrivateKeys: Boolean = false, + + @SerialName("isMember") + val isMember: Boolean = false, + + @SerialName("familySponsorshipAvailable") + val familySponsorshipAvailable: Boolean = false, + + @SerialName("productTierType") + val productTierType: ProductTierType = ProductTierType.FREE, + + @SerialName("useKeyConnector") + val shouldUseKeyConnector: Boolean = false, + + @SerialName("accessSecretsManager") + val accessSecretsManager: Boolean = false, + + @SerialName("limitCollectionCreation") + val limitCollectionCreation: Boolean = false, + + @SerialName("limitCollectionDeletion") + val limitCollectionDeletion: Boolean = false, + + @SerialName("allowAdminAccessToAllCollectionItems") + val allowAdminAccessToAllCollectionItems: Boolean = false, + + @SerialName("useAccessIntelligence") + val useAccessIntelligence: Boolean = false, + + @SerialName("useAdminSponsoredFamilies") + val useAdminSponsoredFamilies: Boolean = false, + + @SerialName("useDisableSmAdsForUsers") + val useDisableSmAdsForUsers: Boolean = false, + + @SerialName("isAdminInitiated") + val isAdminInitiated: Boolean = false, + + @SerialName("ssoEnabled") + val ssoEnabled: Boolean = false, + + @SerialName("ssoMemberDecryptionType") + val ssoMemberDecryptionType: MemberDecryptionType?, + + @SerialName("usePhishingBlocker") + val usePhishingBlocker: Boolean = false, + + @SerialName("useMyItems") + val useMyItems: Boolean = false, ) /** @@ -436,10 +590,24 @@ data class SyncResponseJson( ) /** - * Represents permissions in the vault response. + * Custom permission set for a user with the [OrganizationType.CUSTOM] role. * - * @property shouldManageResetPassword If reset password should be managed. - * @property shouldManagePolicies If policies should be managed. + * @property shouldManageResetPassword Can manage the account recovery (password reset) + * feature. + * @property shouldManagePolicies Can manage organization policies. + * @property accessEventLogs Can view the organization's event logs. + * @property accessImportExport Can import and export organization vault data. + * @property accessReports Can access organization reports. + * @property createNewCollections Can create new collections. + * @property editAnyCollection Can edit any collection, including those they are not + * assigned to. + * @property deleteAnyCollection Can delete any collection, including those they are not + * assigned to. + * @property manageGroups Can manage groups within the organization. + * @property manageSso Can manage SSO configuration. + * @property manageUsers Can manage organization members. + * @property manageScim Can manage SCIM (System for Cross-domain Identity Management) + * configuration. */ @Serializable data class Permissions( @@ -448,6 +616,36 @@ data class SyncResponseJson( @SerialName("managePolicies") val shouldManagePolicies: Boolean, + + @SerialName("accessEventLogs") + val accessEventLogs: Boolean = false, + + @SerialName("accessImportExport") + val accessImportExport: Boolean = false, + + @SerialName("accessReports") + val accessReports: Boolean = false, + + @SerialName("createNewCollections") + val createNewCollections: Boolean = false, + + @SerialName("editAnyCollection") + val editAnyCollection: Boolean = false, + + @SerialName("deleteAnyCollection") + val deleteAnyCollection: Boolean = false, + + @SerialName("manageGroups") + val manageGroups: Boolean = false, + + @SerialName("manageSso") + val manageSso: Boolean = false, + + @SerialName("manageUsers") + val manageUsers: Boolean = false, + + @SerialName("manageScim") + val manageScim: Boolean = false, ) } diff --git a/network/src/test/kotlin/com/bitwarden/network/service/SyncServiceTest.kt b/network/src/test/kotlin/com/bitwarden/network/service/SyncServiceTest.kt index e824201abe9..d88b6f6671f 100644 --- a/network/src/test/kotlin/com/bitwarden/network/service/SyncServiceTest.kt +++ b/network/src/test/kotlin/com/bitwarden/network/service/SyncServiceTest.kt @@ -97,7 +97,8 @@ private const val SYNC_SUCCESS_JSON = """ "editAnyCollection": false, "accessEventLogs": false, "createNewCollections": false, - "editAssignedCollections": false + "editAssignedCollections": false, + "manageScim": false }, "providerId": "mockProviderId-1", "id": "mockId-1", @@ -119,7 +120,38 @@ private const val SYNC_SUCCESS_JSON = """ "useApi": false, "familySponsorshipValidUntil": "2023-10-27T12:00:00.00Z", "status": 2, - "userIsClaimedByOrganization": false + "userIsClaimedByOrganization": false, + "useSso": false, + "useOrganizationDomains": false, + "useKeyConnector": false, + "useScim": false, + "useCustomPermissions": false, + "useResetPassword": false, + "useSecretsManager": false, + "usePasswordManager": false, + "useActivateAutofillPolicy": false, + "useAutomaticUserConfirmation": false, + "ssoBound": false, + "resetPasswordEnrolled": false, + "organizationUserId": "mockOrganizationUserId-1", + "hasPublicAndPrivateKeys": false, + "isProviderUser": false, + "isMember": false, + "familySponsorshipAvailable": false, + "productTierType": 0, + "accessSecretsManager": false, + "limitCollectionCreation": false, + "limitCollectionDeletion": false, + "limitItemDeletion": false, + "allowAdminAccessToAllCollectionItems": false, + "useAccessIntelligence": false, + "useAdminSponsoredFamilies": false, + "useDisableSmAdsForUsers": false, + "isAdminInitiated": false, + "ssoEnabled": false, + "ssoMemberDecryptionType": null, + "usePhishingBlocker": false, + "useMyItems": false } ], "organizationsNew": [ @@ -146,7 +178,8 @@ private const val SYNC_SUCCESS_JSON = """ "editAnyCollection": false, "accessEventLogs": false, "createNewCollections": false, - "editAssignedCollections": false + "editAssignedCollections": false, + "manageScim": false }, "providerId": "mockProviderId-1", "id": "mockId-1", @@ -168,7 +201,38 @@ private const val SYNC_SUCCESS_JSON = """ "useApi": false, "familySponsorshipValidUntil": "2023-10-27T12:00:00.00Z", "status": 2, - "userIsClaimedByOrganization": false + "userIsClaimedByOrganization": false, + "useSso": false, + "useOrganizationDomains": false, + "useKeyConnector": false, + "useScim": false, + "useCustomPermissions": false, + "useResetPassword": false, + "useSecretsManager": false, + "usePasswordManager": false, + "useActivateAutofillPolicy": false, + "useAutomaticUserConfirmation": false, + "ssoBound": false, + "resetPasswordEnrolled": false, + "organizationUserId": "mockOrganizationUserId-1", + "hasPublicAndPrivateKeys": false, + "isProviderUser": false, + "isMember": false, + "familySponsorshipAvailable": false, + "productTierType": 0, + "accessSecretsManager": false, + "limitCollectionCreation": false, + "limitCollectionDeletion": false, + "limitItemDeletion": false, + "allowAdminAccessToAllCollectionItems": false, + "useAccessIntelligence": false, + "useAdminSponsoredFamilies": false, + "useDisableSmAdsForUsers": false, + "isAdminInitiated": false, + "ssoEnabled": false, + "ssoMemberDecryptionType": null, + "usePhishingBlocker": false, + "useMyItems": false } ], "providers": [ @@ -187,7 +251,8 @@ private const val SYNC_SUCCESS_JSON = """ "editAnyCollection": false, "accessEventLogs": false, "createNewCollections": false, - "editAssignedCollections": false + "editAssignedCollections": false, + "manageScim": false }, "name": "mockName-1", "id": "mockId-1", @@ -222,7 +287,8 @@ private const val SYNC_SUCCESS_JSON = """ "editAnyCollection": false, "accessEventLogs": false, "createNewCollections": false, - "editAssignedCollections": false + "editAssignedCollections": false, + "manageScim": false }, "providerId": "mockProviderId-1", "id": "mockId-1", @@ -244,7 +310,38 @@ private const val SYNC_SUCCESS_JSON = """ "useApi": false, "familySponsorshipValidUntil": "2023-10-27T12:00:00.00Z", "status": 2, - "userIsClaimedByOrganization": false + "userIsClaimedByOrganization": false, + "useSso": false, + "useOrganizationDomains": false, + "useKeyConnector": false, + "useScim": false, + "useCustomPermissions": false, + "useResetPassword": false, + "useSecretsManager": false, + "usePasswordManager": false, + "useActivateAutofillPolicy": false, + "useAutomaticUserConfirmation": false, + "ssoBound": false, + "resetPasswordEnrolled": false, + "organizationUserId": "mockOrganizationUserId-1", + "hasPublicAndPrivateKeys": false, + "isProviderUser": false, + "isMember": false, + "familySponsorshipAvailable": false, + "productTierType": 0, + "accessSecretsManager": false, + "limitCollectionCreation": false, + "limitCollectionDeletion": false, + "limitItemDeletion": false, + "allowAdminAccessToAllCollectionItems": false, + "useAccessIntelligence": false, + "useAdminSponsoredFamilies": false, + "useDisableSmAdsForUsers": false, + "isAdminInitiated": false, + "ssoEnabled": false, + "ssoMemberDecryptionType": null, + "usePhishingBlocker": false, + "useMyItems": false } ] }, diff --git a/network/src/testFixtures/kotlin/com/bitwarden/network/model/SyncResponseProfileUtil.kt b/network/src/testFixtures/kotlin/com/bitwarden/network/model/SyncResponseProfileUtil.kt index 6292a316fb7..c2763b01dcb 100644 --- a/network/src/testFixtures/kotlin/com/bitwarden/network/model/SyncResponseProfileUtil.kt +++ b/network/src/testFixtures/kotlin/com/bitwarden/network/model/SyncResponseProfileUtil.kt @@ -63,16 +63,17 @@ fun createMockProfile( /** * Create a mock [SyncResponseJson.Profile.Organization] with a given [number]. */ +@Suppress("LongMethod") fun createMockOrganizationNetwork( number: Int, shouldUsePolicies: Boolean = false, - shouldUseKeyConnector: Boolean = false, + isKeyConnectorEnabled: Boolean = false, keyConnectorUrl: String? = "mockKeyConnectorUrl-$number", type: OrganizationType = OrganizationType.ADMIN, - seats: Int? = 1, + seats: UInt? = 1u, isEnabled: Boolean = false, - providerType: Int? = 1, - maxCollections: Int? = 1, + providerType: ProviderType? = ProviderType.RESELLER, + maxCollections: UInt? = 1u, isSelfHost: Boolean = false, permissions: SyncResponseJson.Profile.Permissions = createMockPermissions(), providerId: String? = "mockProviderId-$number", @@ -82,7 +83,7 @@ fun createMockOrganizationNetwork( key: String? = "mockKey-$number", providerName: String? = "mockProviderName-$number", shouldUsersGetPremium: Boolean = false, - maxStorageGb: Int? = 1, + maxStorageGb: UInt? = 1u, identifier: String? = "mockIdentifier-$number", use2fa: Boolean = false, familySponsorshipToDelete: Boolean? = false, @@ -97,10 +98,40 @@ fun createMockOrganizationNetwork( status: OrganizationStatusType = OrganizationStatusType.CONFIRMED, userIsClaimedByOrganization: Boolean = false, limitItemDeletion: Boolean = false, + useSso: Boolean = false, + useOrganizationDomains: Boolean = false, + shouldUseKeyConnector: Boolean = false, + useScim: Boolean = false, + useCustomPermissions: Boolean = false, + useResetPassword: Boolean = false, + useSecretsManager: Boolean = false, + usePasswordManager: Boolean = false, + useActivateAutofillPolicy: Boolean = false, + useAutomaticUserConfirmation: Boolean = false, + ssoBound: Boolean = false, + resetPasswordEnrolled: Boolean = false, + organizationUserId: String? = "mockOrganizationUserId-$number", + hasPublicAndPrivateKeys: Boolean = false, + isProviderUser: Boolean = false, + isMember: Boolean = false, + familySponsorshipAvailable: Boolean = false, + productTierType: ProductTierType = ProductTierType.FREE, + accessSecretsManager: Boolean = false, + limitCollectionCreation: Boolean = false, + limitCollectionDeletion: Boolean = false, + allowAdminAccessToAllCollectionItems: Boolean = false, + useAccessIntelligence: Boolean = false, + useAdminSponsoredFamilies: Boolean = false, + useDisableSmAdsForUsers: Boolean = false, + isAdminInitiated: Boolean = false, + ssoEnabled: Boolean = false, + ssoMemberDecryptionType: MemberDecryptionType? = null, + usePhishingBlocker: Boolean = false, + useMyItems: Boolean = false, ): SyncResponseJson.Profile.Organization = SyncResponseJson.Profile.Organization( shouldUsePolicies = shouldUsePolicies, - shouldUseKeyConnector = shouldUseKeyConnector, + isKeyConnectorEnabled = isKeyConnectorEnabled, keyConnectorUrl = keyConnectorUrl, type = type, seats = seats, @@ -131,6 +162,36 @@ fun createMockOrganizationNetwork( status = status, userIsClaimedByOrganization = userIsClaimedByOrganization, limitItemDeletion = limitItemDeletion, + useSso = useSso, + useOrganizationDomains = useOrganizationDomains, + shouldUseKeyConnector = shouldUseKeyConnector, + useScim = useScim, + useCustomPermissions = useCustomPermissions, + useResetPassword = useResetPassword, + useSecretsManager = useSecretsManager, + usePasswordManager = usePasswordManager, + useActivateAutofillPolicy = useActivateAutofillPolicy, + useAutomaticUserConfirmation = useAutomaticUserConfirmation, + ssoBound = ssoBound, + resetPasswordEnrolled = resetPasswordEnrolled, + organizationUserId = organizationUserId, + hasPublicAndPrivateKeys = hasPublicAndPrivateKeys, + isProviderUser = isProviderUser, + isMember = isMember, + familySponsorshipAvailable = familySponsorshipAvailable, + productTierType = productTierType, + accessSecretsManager = accessSecretsManager, + limitCollectionCreation = limitCollectionCreation, + limitCollectionDeletion = limitCollectionDeletion, + allowAdminAccessToAllCollectionItems = allowAdminAccessToAllCollectionItems, + useAccessIntelligence = useAccessIntelligence, + useAdminSponsoredFamilies = useAdminSponsoredFamilies, + useDisableSmAdsForUsers = useDisableSmAdsForUsers, + isAdminInitiated = isAdminInitiated, + ssoEnabled = ssoEnabled, + ssoMemberDecryptionType = ssoMemberDecryptionType, + usePhishingBlocker = usePhishingBlocker, + useMyItems = useMyItems, ) /** @@ -150,10 +211,30 @@ fun createMockOrganizationKeys( fun createMockPermissions( shouldManageResetPassword: Boolean = false, shouldManagePolicies: Boolean = false, + accessEventLogs: Boolean = false, + accessImportExport: Boolean = false, + accessReports: Boolean = false, + createNewCollections: Boolean = false, + editAnyCollection: Boolean = false, + deleteAnyCollection: Boolean = false, + manageGroups: Boolean = false, + manageSso: Boolean = false, + manageUsers: Boolean = false, + manageScim: Boolean = false, ): SyncResponseJson.Profile.Permissions = SyncResponseJson.Profile.Permissions( shouldManageResetPassword = shouldManageResetPassword, shouldManagePolicies = shouldManagePolicies, + accessEventLogs = accessEventLogs, + accessImportExport = accessImportExport, + accessReports = accessReports, + createNewCollections = createNewCollections, + editAnyCollection = editAnyCollection, + deleteAnyCollection = deleteAnyCollection, + manageGroups = manageGroups, + manageSso = manageSso, + manageUsers = manageUsers, + manageScim = manageScim, ) /**