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
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand All @@ -39,6 +51,86 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization? =
fun List<SyncResponseJson.Profile.Organization>.toOrganizations(): List<Organization> =
this.mapNotNull { it.toOrganization() }

/**
* Maps the given list of [SyncResponseJson.Profile.Organization] to a list of
* [ProfileOrganization]s.
*/
@Suppress("MaxLineLength")
fun List<SyncResponseJson.Profile.Organization>.toSdkProfileOrganizations(): List<ProfileOrganization> =
this.mapNotNull { it.toSdkProfileOrganization() }
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is currently used only for tests, but it will keep us in-sync with the SDK.

I will also be updating other spots in the app to use ProfileOrganization in a future PR.


/**
* 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.
*/
Expand All @@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class RemovePasswordViewModel @Inject constructor(
val org = authRepository.userStateFlow.value
?.activeAccount
?.organizations
?.firstOrNull { it.shouldUseKeyConnector }
?.firstOrNull { it.isKeyConnectorEnabled }

RemovePasswordState(
input = "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5383,7 +5383,7 @@ class AuthRepositoryTest {
val organizations = listOf(
createMockOrganizationNetwork(
number = 1,
shouldUseKeyConnector = true,
isKeyConnectorEnabled = true,
type = OrganizationType.USER,
keyConnectorUrl = null,
),
Expand All @@ -5408,7 +5408,7 @@ class AuthRepositoryTest {
val organizations = listOf(
createMockOrganizationNetwork(
number = 1,
shouldUseKeyConnector = true,
isKeyConnectorEnabled = true,
type = OrganizationType.USER,
keyConnectorUrl = url,
),
Expand Down Expand Up @@ -5441,7 +5441,7 @@ class AuthRepositoryTest {
val organizations = listOf(
createMockOrganizationNetwork(
number = 1,
shouldUseKeyConnector = true,
isKeyConnectorEnabled = true,
type = OrganizationType.USER,
keyConnectorUrl = url,
),
Expand Down Expand Up @@ -5477,7 +5477,7 @@ class AuthRepositoryTest {
val organizations = listOf(
createMockOrganizationNetwork(
number = 1,
shouldUseKeyConnector = true,
isKeyConnectorEnabled = true,
type = OrganizationType.USER,
keyConnectorUrl = url,
),
Expand Down Expand Up @@ -5512,7 +5512,7 @@ class AuthRepositoryTest {
val organizations = listOf(
createMockOrganizationNetwork(
number = 1,
shouldUseKeyConnector = true,
isKeyConnectorEnabled = true,
type = OrganizationType.USER,
keyConnectorUrl = url,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fun createMockOrganization(
id = id,
name = name,
shouldManageResetPassword = shouldManageResetPassword,
shouldUseKeyConnector = shouldUseKeyConnector,
isKeyConnectorEnabled = shouldUseKeyConnector,
role = role,
keyConnectorUrl = keyConnectorUrl,
userIsClaimedByOrganization = userIsClaimedByOrganization,
Expand Down
Loading
Loading