@ -73,6 +73,8 @@ impl UserOrgType {
"1" | "Admin" = > Some ( UserOrgType ::Admin ) ,
"2" | "User" = > Some ( UserOrgType ::User ) ,
"3" | "Manager" = > Some ( UserOrgType ::Manager ) ,
// HACK: We convert the custom role to a manager role
"4" | "Custom" = > Some ( UserOrgType ::Manager ) ,
_ = > None ,
}
}
@ -85,7 +87,7 @@ impl Ord for UserOrgType {
3 , // Owner
2 , // Admin
0 , // User
1 , // Manager
1 , // Manager && Custom
] ;
ACCESS_LEVEL [ * self as usize ] . cmp ( & ACCESS_LEVEL [ * other as usize ] )
}
@ -158,33 +160,46 @@ impl Organization {
pub fn to_json ( & self ) -> Value {
json ! ( {
"id" : self . uuid ,
"identifier" : null , // not supported by us
"name" : self . name ,
"seats" : null ,
"maxCollections" : null ,
"maxStorageGb" : i16 ::MAX , // The value doesn't matter, we don't check server-side
"use2fa" : true ,
"useCustomPermissions" : fals e,
"useCustomPermissions" : tru e,
"useDirectory" : false , // Is supported, but this value isn't checked anywhere (yet)
"useEvents" : CONFIG . org_events_enabled ( ) ,
"useGroups" : CONFIG . org_groups_enabled ( ) ,
"useTotp" : true ,
"usePolicies" : true ,
// "useScim": false, // Not supported (Not AGPLv3 Licensed)
"useScim" : false , // Not supported (Not AGPLv3 Licensed)
"useSso" : false , // Not supported
// "useKeyConnector": false, // Not supported
"useKeyConnector" : false , // Not supported
"usePasswordManager" : true ,
"useSecretsManager" : false , // Not supported (Not AGPLv3 Licensed)
"selfHost" : true ,
"useApi" : true ,
"hasPublicAndPrivateKeys" : self . private_key . is_some ( ) & & self . public_key . is_some ( ) ,
"useResetPassword" : CONFIG . mail_enabled ( ) ,
"allowAdminAccessToAllCollectionItems" : true ,
"limitCollectionCreation" : true ,
"limitCollectionCreationDeletion" : true ,
"limitCollectionDeletion" : true ,
"businessName" : null ,
"businessName" : self. name ,
"businessAddress1" : null ,
"businessAddress2" : null ,
"businessAddress3" : null ,
"businessCountry" : null ,
"businessTaxNumber" : null ,
"maxAutoscaleSeats" : null ,
"maxAutoscaleSmSeats" : null ,
"maxAutoscaleSmServiceAccounts" : null ,
"secretsManagerPlan" : null ,
"smSeats" : null ,
"smServiceAccounts" : null ,
"billingEmail" : self . billing_email ,
"planType" : 6 , // Custom plan
"usersGetPremium" : true ,
@ -252,6 +267,15 @@ impl UserOrganization {
}
false
}
/// HACK: Convert the manager type to a custom type
/// It will be converted back on other locations
pub fn type_manager_as_custom ( & self ) -> i32 {
match self . atype {
3 = > 4 ,
_ = > self . atype ,
}
}
}
impl OrganizationApiKey {
@ -356,17 +380,21 @@ impl UserOrganization {
pub async fn to_json ( & self , conn : & mut DbConn ) -> Value {
let org = Organization ::find_by_uuid ( & self . org_uuid , conn ) . await . unwrap ( ) ;
// HACK: Convert the manager type to a custom type
// It will be converted back on other locations
let user_org_type = self . type_manager_as_custom ( ) ;
let permissions = json ! ( {
// TODO: Add support for Custom User Roles
// TODO: Add full support for Custom User Roles
// See: https://bitwarden.com/help/article/user-types-access-control/#custom-role
// Currently we use the custom role as a manager role and link the 3 Collection roles to mimic the access_all permission
"accessEventLogs" : false ,
"accessImportExport" : false ,
"accessReports" : false ,
"createNewCollections" : false ,
"editAnyCollection" : false ,
"deleteAnyCollection" : false ,
"editAssignedCollections" : false ,
"deleteAssignedCollections" : false ,
// If the following 3 Collection roles are set to true a custom user has access all permission
"createNewCollections" : user_org_type = = 4 & & self . access_all ,
"editAnyCollection" : user_org_type = = 4 & & self . access_all ,
"deleteAnyCollection" : user_org_type = = 4 & & self . access_all ,
"manageGroups" : false ,
"managePolicies" : false ,
"manageSso" : false , // Not supported
@ -398,9 +426,9 @@ impl UserOrganization {
"ssoBound" : false , // Not supported
"useSso" : false , // Not supported
"useKeyConnector" : false ,
"useSecretsManager" : false ,
"useSecretsManager" : false , // Not supported (Not AGPLv3 Licensed)
"usePasswordManager" : true ,
"useCustomPermissions" : fals e,
"useCustomPermissions" : tru e,
"useActivateAutofillPolicy" : false ,
"organizationUserId" : self . uuid ,
@ -417,9 +445,11 @@ impl UserOrganization {
"familySponsorshipValidUntil" : null ,
"familySponsorshipToDelete" : null ,
"accessSecretsManager" : false ,
"limitCollectionCreationDeletion" : false , // This should be set to true only when we can handle roles like createNewCollections
"limitCollectionCreation" : true ,
"limitCollectionCreationDeletion" : true ,
"limitCollectionDeletion" : true ,
"allowAdminAccessToAllCollectionItems" : true ,
"flexibleCollections" : false ,
" userIsManagedByOrganization": false , // Means not managed via the Members UI, like SSO
"permissions" : permissions ,
@ -429,7 +459,7 @@ impl UserOrganization {
"userId" : self . user_uuid ,
"key" : self . akey ,
"status" : self . status ,
"type" : self. a type,
"type" : user_org_ type,
"enabled" : true ,
"object" : "profileOrganization" ,
@ -516,24 +546,34 @@ impl UserOrganization {
Vec ::with_capacity ( 0 )
} ;
let permissions = json ! ( {
// TODO: Add support for Custom User Roles
// See: https://bitwarden.com/help/article/user-types-access-control/#custom-role
"accessEventLogs" : false ,
"accessImportExport" : false ,
"accessReports" : false ,
"createNewCollections" : false ,
"editAnyCollection" : false ,
"deleteAnyCollection" : false ,
"editAssignedCollections" : false ,
"deleteAssignedCollections" : false ,
"manageGroups" : false ,
"managePolicies" : false ,
"manageSso" : false , // Not supported
"manageUsers" : false ,
"manageResetPassword" : false ,
"manageScim" : false // Not supported (Not AGPLv3 Licensed)
} ) ;
// HACK: Convert the manager type to a custom type
// It will be converted back on other locations
let user_org_type = self . type_manager_as_custom ( ) ;
// HACK: Only return permissions if the user is of type custom and has access_all
// Else Bitwarden will assume the defaults of all false
let permissions = if user_org_type = = 4 & & self . access_all {
json ! ( {
// TODO: Add full support for Custom User Roles
// See: https://bitwarden.com/help/article/user-types-access-control/#custom-role
// Currently we use the custom role as a manager role and link the 3 Collection roles to mimic the access_all permission
"accessEventLogs" : false ,
"accessImportExport" : false ,
"accessReports" : false ,
// If the following 3 Collection roles are set to true a custom user has access all permission
"createNewCollections" : true ,
"editAnyCollection" : true ,
"deleteAnyCollection" : true ,
"manageGroups" : false ,
"managePolicies" : false ,
"manageSso" : false , // Not supported
"manageUsers" : false ,
"manageResetPassword" : false ,
"manageScim" : false // Not supported (Not AGPLv3 Licensed)
} )
} else {
json ! ( null )
} ;
json ! ( {
"id" : self . uuid ,
@ -546,7 +586,7 @@ impl UserOrganization {
"collections" : collections ,
"status" : status ,
"type" : self. a type,
"type" : user_org_ type,
"accessAll" : self . access_all ,
"twoFactorEnabled" : twofactor_enabled ,
"resetPasswordEnrolled" : self . reset_password_key . is_some ( ) ,
@ -608,6 +648,29 @@ impl UserOrganization {
"object" : "organizationUserDetails" ,
} )
}
pub async fn to_json_mini_details ( & self , conn : & mut DbConn ) -> Value {
let user = User ::find_by_uuid ( & self . user_uuid , conn ) . await . unwrap ( ) ;
// Because BitWarden want the status to be -1 for revoked users we need to catch that here.
// We subtract/add a number so we can restore/activate the user to it's previous state again.
let status = if self . status < UserOrgStatus ::Revoked as i32 {
UserOrgStatus ::Revoked as i32
} else {
self . status
} ;
json ! ( {
"id" : self . uuid ,
"userId" : self . user_uuid ,
"type" : self . type_manager_as_custom ( ) , // HACK: Convert the manager type to a custom type
"status" : status ,
"name" : user . name ,
"email" : user . email ,
"object" : "organizationUserUserMiniDetails" ,
} )
}
pub async fn save ( & self , conn : & mut DbConn ) -> EmptyResult {
User ::update_uuid_revision ( & self . user_uuid , conn ) . await ;
@ -1015,5 +1078,6 @@ mod tests {
assert! ( UserOrgType ::Owner > UserOrgType ::Admin ) ;
assert! ( UserOrgType ::Admin > UserOrgType ::Manager ) ;
assert! ( UserOrgType ::Manager > UserOrgType ::User ) ;
assert! ( UserOrgType ::Manager = = UserOrgType ::from_str ( "4" ) . unwrap ( ) ) ;
}
}