Skip to content

Commit a3bcff9

Browse files
PM-37911: Feat: Update Organization model (#6960)
1 parent aca9949 commit a3bcff9

15 files changed

Lines changed: 949 additions & 67 deletions

File tree

app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,7 @@ class AuthRepositoryImpl(
10571057
?: return RemovePasswordResult.Error(error = MissingPropertyException("User Key"))
10581058
val keyConnectorUrl = organizations
10591059
.find {
1060-
it.shouldUseKeyConnector &&
1060+
it.isKeyConnectorEnabled &&
10611061
it.role != OrganizationType.OWNER &&
10621062
it.role != OrganizationType.ADMIN
10631063
}

app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/model/Organization.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import com.bitwarden.network.model.OrganizationType
99
* @property name The name of the organization (if applicable).
1010
* @property shouldManageResetPassword Indicates that this user has the permission to manage their
1111
* own password.
12-
* @property shouldUseKeyConnector Indicates that the organization uses a key connector.
12+
* @property isKeyConnectorEnabled Indicates that the organization uses a key connector.
1313
* @property role The user's role in the organization.
1414
* @property keyConnectorUrl The key connector domain (if applicable).
1515
* @property userIsClaimedByOrganization Indicates that the user is claimed by the organization.
@@ -20,7 +20,7 @@ data class Organization(
2020
val id: String,
2121
val name: String,
2222
val shouldManageResetPassword: Boolean,
23-
val shouldUseKeyConnector: Boolean,
23+
val isKeyConnectorEnabled: Boolean,
2424
val role: OrganizationType,
2525
val keyConnectorUrl: String?,
2626
val userIsClaimedByOrganization: Boolean,

app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/util/SyncResponseJsonExtensions.kt

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
package com.x8bit.bitwarden.data.auth.repository.util
22

33
import com.bitwarden.core.data.util.decodeFromStringOrNull
4+
import com.bitwarden.network.model.MemberDecryptionType
5+
import com.bitwarden.network.model.OrganizationStatusType
6+
import com.bitwarden.network.model.OrganizationType
7+
import com.bitwarden.network.model.ProductTierType
8+
import com.bitwarden.network.model.ProviderType
49
import com.bitwarden.network.model.SyncResponseJson
10+
import com.bitwarden.organizations.OrganizationUserStatusType
11+
import com.bitwarden.organizations.OrganizationUserType
12+
import com.bitwarden.organizations.Permissions
13+
import com.bitwarden.organizations.ProfileOrganization
514
import com.bitwarden.policies.PolicyType
615
import com.bitwarden.policies.PolicyView
716
import com.x8bit.bitwarden.data.auth.repository.model.Organization
817
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
918
import kotlinx.serialization.json.Json
19+
import com.bitwarden.organizations.MemberDecryptionType as SdkMemberDecryptionType
20+
import com.bitwarden.organizations.ProductTierType as SdkProductTierType
21+
import com.bitwarden.organizations.ProviderType as SdkProviderType
1022

1123
private val JSON = Json {
1224
ignoreUnknownKeys = true
@@ -22,7 +34,7 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization? =
2234
Organization(
2335
id = this.id,
2436
name = it,
25-
shouldUseKeyConnector = this.shouldUseKeyConnector,
37+
isKeyConnectorEnabled = this.isKeyConnectorEnabled,
2638
role = this.type,
2739
shouldManageResetPassword = this.permissions.shouldManageResetPassword,
2840
keyConnectorUrl = this.keyConnectorUrl,
@@ -39,6 +51,86 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization? =
3951
fun List<SyncResponseJson.Profile.Organization>.toOrganizations(): List<Organization> =
4052
this.mapNotNull { it.toOrganization() }
4153

54+
/**
55+
* Maps the given list of [SyncResponseJson.Profile.Organization] to a list of
56+
* [ProfileOrganization]s.
57+
*/
58+
@Suppress("MaxLineLength")
59+
fun List<SyncResponseJson.Profile.Organization>.toSdkProfileOrganizations(): List<ProfileOrganization> =
60+
this.mapNotNull { it.toSdkProfileOrganization() }
61+
62+
/**
63+
* Maps the given [SyncResponseJson.Profile.Organization] to a [ProfileOrganization] or `null` if
64+
* the [SyncResponseJson.Profile.Organization.name] is not present.
65+
*/
66+
@Suppress("LongMethod")
67+
private fun SyncResponseJson.Profile.Organization.toSdkProfileOrganization(): ProfileOrganization? =
68+
this.name?.let {
69+
ProfileOrganization(
70+
id = this.id,
71+
name = it,
72+
status = this.status.toSdkOrganizationUserStatusType(),
73+
type = this.type.toSdkOrganizationUserType(),
74+
enabled = this.isEnabled,
75+
usePolicies = this.shouldUsePolicies,
76+
useGroups = this.shouldUseGroups,
77+
useDirectory = this.shouldUseDirectory,
78+
useEvents = this.shouldUseEvents,
79+
useTotp = this.shouldUseTotp,
80+
use2fa = this.use2fa,
81+
useApi = this.shouldUseApi,
82+
useSso = this.useSso,
83+
useOrganizationDomains = this.useOrganizationDomains,
84+
useKeyConnector = this.shouldUseKeyConnector,
85+
useScim = this.useScim,
86+
useCustomPermissions = this.useCustomPermissions,
87+
useResetPassword = this.useResetPassword,
88+
useSecretsManager = this.useSecretsManager,
89+
usePasswordManager = this.usePasswordManager,
90+
useActivateAutofillPolicy = this.useActivateAutofillPolicy,
91+
useAutomaticUserConfirmation = this.useAutomaticUserConfirmation,
92+
selfHost = this.isSelfHost,
93+
usersGetPremium = this.shouldUsersGetPremium,
94+
seats = this.seats,
95+
maxCollections = this.maxCollections,
96+
maxStorageGb = this.maxStorageGb,
97+
ssoBound = this.ssoBound,
98+
identifier = this.identifier,
99+
permissions = this.permissions.toSdkPermissions(),
100+
resetPasswordEnrolled = this.resetPasswordEnrolled,
101+
userId = this.userId,
102+
organizationUserId = this.organizationUserId,
103+
hasPublicAndPrivateKeys = this.hasPublicAndPrivateKeys,
104+
providerId = this.providerId,
105+
providerName = this.providerName,
106+
providerType = this.providerType?.toSdkProviderType(),
107+
isProviderUser = this.isProviderUser,
108+
isMember = this.isMember,
109+
familySponsorshipFriendlyName = this.familySponsorshipFriendlyName,
110+
familySponsorshipAvailable = this.familySponsorshipAvailable,
111+
productTierType = this.productTierType.toSdkProductTierType(),
112+
keyConnectorEnabled = this.isKeyConnectorEnabled,
113+
keyConnectorUrl = this.keyConnectorUrl,
114+
familySponsorshipLastSyncDate = this.familySponsorshipLastSyncDate,
115+
familySponsorshipValidUntil = this.familySponsorshipValidUntil,
116+
familySponsorshipToDelete = this.familySponsorshipToDelete,
117+
accessSecretsManager = this.accessSecretsManager,
118+
limitCollectionCreation = this.limitCollectionCreation,
119+
limitCollectionDeletion = this.limitCollectionDeletion,
120+
limitItemDeletion = this.limitItemDeletion,
121+
allowAdminAccessToAllCollectionItems = this.allowAdminAccessToAllCollectionItems,
122+
userIsManagedByOrganization = this.userIsClaimedByOrganization,
123+
useAccessIntelligence = this.useAccessIntelligence,
124+
useAdminSponsoredFamilies = this.useAdminSponsoredFamilies,
125+
useDisableSmAdsForUsers = this.useDisableSmAdsForUsers,
126+
isAdminInitiated = this.isAdminInitiated,
127+
ssoEnabled = this.ssoEnabled,
128+
ssoMemberDecryptionType = this.ssoMemberDecryptionType?.toSdkMemberDecryptionType(),
129+
usePhishingBlocker = this.usePhishingBlocker,
130+
useMyItems = this.useMyItems,
131+
)
132+
}
133+
42134
/**
43135
* Convert the JSON data of the [PolicyView] object into [PolicyInformation] data.
44136
*/
@@ -64,3 +156,60 @@ val PolicyView.policyInformation: PolicyInformation?
64156
else -> null
65157
}
66158
}
159+
160+
private fun SyncResponseJson.Profile.Permissions.toSdkPermissions(): Permissions =
161+
Permissions(
162+
accessEventLogs = this.accessEventLogs,
163+
accessImportExport = this.accessImportExport,
164+
accessReports = this.accessReports,
165+
createNewCollections = this.createNewCollections,
166+
editAnyCollection = this.editAnyCollection,
167+
deleteAnyCollection = this.deleteAnyCollection,
168+
manageGroups = this.manageGroups,
169+
manageSso = this.manageSso,
170+
managePolicies = this.shouldManagePolicies,
171+
manageUsers = this.manageUsers,
172+
manageResetPassword = this.shouldManageResetPassword,
173+
manageScim = this.manageScim,
174+
)
175+
176+
private fun OrganizationStatusType.toSdkOrganizationUserStatusType(): OrganizationUserStatusType =
177+
when (this) {
178+
OrganizationStatusType.REVOKED -> OrganizationUserStatusType.REVOKED
179+
OrganizationStatusType.INVITED -> OrganizationUserStatusType.INVITED
180+
OrganizationStatusType.ACCEPTED -> OrganizationUserStatusType.ACCEPTED
181+
OrganizationStatusType.CONFIRMED -> OrganizationUserStatusType.CONFIRMED
182+
}
183+
184+
private fun OrganizationType.toSdkOrganizationUserType(): OrganizationUserType =
185+
when (this) {
186+
OrganizationType.OWNER -> OrganizationUserType.OWNER
187+
OrganizationType.ADMIN -> OrganizationUserType.ADMIN
188+
OrganizationType.USER -> OrganizationUserType.USER
189+
OrganizationType.CUSTOM -> OrganizationUserType.CUSTOM
190+
}
191+
192+
private fun ProviderType.toSdkProviderType(): SdkProviderType =
193+
when (this) {
194+
ProviderType.MSP -> SdkProviderType.MSP
195+
ProviderType.RESELLER -> SdkProviderType.RESELLER
196+
ProviderType.BUSINESS_UNIT -> SdkProviderType.BUSINESS_UNIT
197+
}
198+
199+
private fun ProductTierType.toSdkProductTierType(): SdkProductTierType =
200+
when (this) {
201+
ProductTierType.FREE -> SdkProductTierType.FREE
202+
ProductTierType.FAMILIES -> SdkProductTierType.FAMILIES
203+
ProductTierType.TEAMS -> SdkProductTierType.TEAMS
204+
ProductTierType.ENTERPRISE -> SdkProductTierType.ENTERPRISE
205+
ProductTierType.TEAMS_STARTER -> SdkProductTierType.TEAMS_STARTER
206+
}
207+
208+
private fun MemberDecryptionType.toSdkMemberDecryptionType(): SdkMemberDecryptionType =
209+
when (this) {
210+
MemberDecryptionType.MASTER_PASSWORD -> SdkMemberDecryptionType.MASTER_PASSWORD
211+
MemberDecryptionType.KEY_CONNECTOR -> SdkMemberDecryptionType.KEY_CONNECTOR
212+
MemberDecryptionType.TRUSTED_DEVICE_ENCRYPTION -> {
213+
SdkMemberDecryptionType.TRUSTED_DEVICE_ENCRYPTION
214+
}
215+
}

app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class RemovePasswordViewModel @Inject constructor(
3232
val org = authRepository.userStateFlow.value
3333
?.activeAccount
3434
?.organizations
35-
?.firstOrNull { it.shouldUseKeyConnector }
35+
?.firstOrNull { it.isKeyConnectorEnabled }
3636

3737
RemovePasswordState(
3838
input = "",

app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ class RootNavViewModel @Inject constructor(
268268
?.let(::parseJwtTokenDataOrNull)
269269
?.isExternal == true
270270
val usesKeyConnectorAndNotAdmin = this.activeAccount.organizations.any {
271-
it.shouldUseKeyConnector &&
271+
it.isKeyConnectorEnabled &&
272272
it.role != OrganizationType.OWNER &&
273273
it.role != OrganizationType.ADMIN
274274
}

app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5383,7 +5383,7 @@ class AuthRepositoryTest {
53835383
val organizations = listOf(
53845384
createMockOrganizationNetwork(
53855385
number = 1,
5386-
shouldUseKeyConnector = true,
5386+
isKeyConnectorEnabled = true,
53875387
type = OrganizationType.USER,
53885388
keyConnectorUrl = null,
53895389
),
@@ -5408,7 +5408,7 @@ class AuthRepositoryTest {
54085408
val organizations = listOf(
54095409
createMockOrganizationNetwork(
54105410
number = 1,
5411-
shouldUseKeyConnector = true,
5411+
isKeyConnectorEnabled = true,
54125412
type = OrganizationType.USER,
54135413
keyConnectorUrl = url,
54145414
),
@@ -5441,7 +5441,7 @@ class AuthRepositoryTest {
54415441
val organizations = listOf(
54425442
createMockOrganizationNetwork(
54435443
number = 1,
5444-
shouldUseKeyConnector = true,
5444+
isKeyConnectorEnabled = true,
54455445
type = OrganizationType.USER,
54465446
keyConnectorUrl = url,
54475447
),
@@ -5477,7 +5477,7 @@ class AuthRepositoryTest {
54775477
val organizations = listOf(
54785478
createMockOrganizationNetwork(
54795479
number = 1,
5480-
shouldUseKeyConnector = true,
5480+
isKeyConnectorEnabled = true,
54815481
type = OrganizationType.USER,
54825482
keyConnectorUrl = url,
54835483
),
@@ -5512,7 +5512,7 @@ class AuthRepositoryTest {
55125512
val organizations = listOf(
55135513
createMockOrganizationNetwork(
55145514
number = 1,
5515-
shouldUseKeyConnector = true,
5515+
isKeyConnectorEnabled = true,
55165516
type = OrganizationType.USER,
55175517
keyConnectorUrl = url,
55185518
),

app/src/test/kotlin/com/x8bit/bitwarden/data/auth/repository/model/OrganizationUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fun createMockOrganization(
2222
id = id,
2323
name = name,
2424
shouldManageResetPassword = shouldManageResetPassword,
25-
shouldUseKeyConnector = shouldUseKeyConnector,
25+
isKeyConnectorEnabled = shouldUseKeyConnector,
2626
role = role,
2727
keyConnectorUrl = keyConnectorUrl,
2828
userIsClaimedByOrganization = userIsClaimedByOrganization,

0 commit comments

Comments
 (0)