|
|
|
@ -5,8 +5,9 @@ use std::{ |
|
|
|
|
|
|
|
use chrono::{NaiveDateTime, Utc}; |
|
|
|
use derive_more::{AsRef, Deref, Display, From}; |
|
|
|
use diesel::prelude::*; |
|
|
|
use diesel::{deserialize::FromSql, prelude::*, serialize::ToSql, sql_types::SmallInt}; |
|
|
|
use num_traits::FromPrimitive; |
|
|
|
#[cfg(feature = "sqlite")] |
|
|
|
use serde_json::Value; |
|
|
|
|
|
|
|
use crate::{ |
|
|
|
@ -28,6 +29,53 @@ use super::{ |
|
|
|
OrgPolicyType, TwoFactor, User, UserId, |
|
|
|
}; |
|
|
|
|
|
|
|
#[repr(i16)] |
|
|
|
pub enum OrgCollectionSetting { |
|
|
|
AllowAdminAccessToAllCollectionItems = 0b1, |
|
|
|
LimitCollectionCreation = 0b10, |
|
|
|
LimitCollectionDeletion = 0b100, |
|
|
|
LimitItemDeletion = 0b1000, |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, FromSqlRow, AsExpression)] |
|
|
|
#[diesel(sql_type = SmallInt)] |
|
|
|
pub struct OrganizationCollectionSettings(i16); |
|
|
|
|
|
|
|
impl OrganizationCollectionSettings { |
|
|
|
pub fn get_flag(self, flag: OrgCollectionSetting) -> bool { |
|
|
|
(self.0 & flag as i16) > 0 |
|
|
|
} |
|
|
|
|
|
|
|
pub fn set_flag(&mut self, flag: OrgCollectionSetting, val: bool) { |
|
|
|
if val { |
|
|
|
self.0 |= flag as i16; |
|
|
|
} else { |
|
|
|
self.0 &= i16::MAX - flag as i16; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<DB> ToSql<SmallInt, DB> for OrganizationCollectionSettings |
|
|
|
where |
|
|
|
DB: diesel::backend::Backend, |
|
|
|
i16: ToSql<SmallInt, DB>, |
|
|
|
{ |
|
|
|
fn to_sql<'b>(&'b self, out: &mut diesel::serialize::Output<'b, '_, DB>) -> diesel::serialize::Result { |
|
|
|
self.0.to_sql(out) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<DB> FromSql<SmallInt, DB> for OrganizationCollectionSettings |
|
|
|
where |
|
|
|
DB: diesel::backend::Backend, |
|
|
|
i16: FromSql<SmallInt, DB>, |
|
|
|
{ |
|
|
|
fn from_sql(bytes: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> { |
|
|
|
let val = i16::from_sql(bytes)?; |
|
|
|
Ok(Self(val)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Identifiable, Queryable, Insertable, AsChangeset)] |
|
|
|
#[diesel(table_name = organizations)] |
|
|
|
#[diesel(treat_none_as_null = true)] |
|
|
|
@ -38,6 +86,8 @@ pub struct Organization { |
|
|
|
pub billing_email: String, |
|
|
|
pub private_key: Option<String>, |
|
|
|
pub public_key: Option<String>, |
|
|
|
|
|
|
|
pub collection_settings: OrganizationCollectionSettings, |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Identifiable, Queryable, Insertable, AsChangeset)] |
|
|
|
@ -193,6 +243,11 @@ impl Organization { |
|
|
|
billing_email, |
|
|
|
private_key, |
|
|
|
public_key, |
|
|
|
|
|
|
|
// Collection Management Settings default to AllowAdminAccessToAllCollectionItems
|
|
|
|
collection_settings: OrganizationCollectionSettings( |
|
|
|
OrgCollectionSetting::AllowAdminAccessToAllCollectionItems as i16, |
|
|
|
), |
|
|
|
} |
|
|
|
} |
|
|
|
// https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/AdminConsole/Models/Response/Organizations/OrganizationResponseModel.cs
|
|
|
|
@ -219,9 +274,10 @@ impl Organization { |
|
|
|
"useApi": true, |
|
|
|
"hasPublicAndPrivateKeys": self.private_key.is_some() && self.public_key.is_some(), |
|
|
|
"useResetPassword": CONFIG.mail_enabled(), |
|
|
|
"allowAdminAccessToAllCollectionItems": true, |
|
|
|
"limitCollectionCreation": true, |
|
|
|
"limitCollectionDeletion": true, |
|
|
|
"allowAdminAccessToAllCollectionItems": self.collection_settings.get_flag(OrgCollectionSetting::AllowAdminAccessToAllCollectionItems), |
|
|
|
"limitCollectionCreation": self.collection_settings.get_flag(OrgCollectionSetting::LimitCollectionCreation), |
|
|
|
"limitCollectionDeletion": self.collection_settings.get_flag(OrgCollectionSetting::LimitCollectionDeletion), |
|
|
|
"limitItemDeletion": self.collection_settings.get_flag(OrgCollectionSetting::LimitItemDeletion), |
|
|
|
|
|
|
|
"businessName": self.name, |
|
|
|
"businessAddress1": null, |
|
|
|
@ -396,6 +452,20 @@ impl Organization { |
|
|
|
conn.run(move |conn| organizations::table.filter(organizations::uuid.eq(uuid)).first::<Self>(conn).ok()).await |
|
|
|
} |
|
|
|
|
|
|
|
pub async fn find_collection_settings_by_uuid( |
|
|
|
uuid: &OrganizationId, |
|
|
|
conn: &DbConn, |
|
|
|
) -> Option<OrganizationCollectionSettings> { |
|
|
|
conn.run(move |conn| { |
|
|
|
organizations::table |
|
|
|
.filter(organizations::uuid.eq(uuid)) |
|
|
|
.select(organizations::collection_settings) |
|
|
|
.first::<OrganizationCollectionSettings>(conn) |
|
|
|
.ok() |
|
|
|
}) |
|
|
|
.await |
|
|
|
} |
|
|
|
|
|
|
|
pub async fn find_by_name(name: &str, conn: &DbConn) -> Option<Self> { |
|
|
|
conn.run(move |conn| organizations::table.filter(organizations::name.eq(name)).first::<Self>(conn).ok()).await |
|
|
|
} |
|
|
|
@ -455,9 +525,9 @@ impl Membership { |
|
|
|
"accessImportExport": false, |
|
|
|
"accessReports": false, |
|
|
|
// If the following 3 Collection roles are set to true a custom user has access all permission
|
|
|
|
"createNewCollections": membership_type == 4 && self.access_all, |
|
|
|
"createNewCollections": membership_type == 4 && self.access_all && !org.collection_settings.get_flag(OrgCollectionSetting::LimitCollectionCreation), |
|
|
|
"editAnyCollection": membership_type == 4 && self.access_all, |
|
|
|
"deleteAnyCollection": membership_type == 4 && self.access_all, |
|
|
|
"deleteAnyCollection": membership_type == 4 && self.access_all && !org.collection_settings.get_flag(OrgCollectionSetting::LimitCollectionCreation), |
|
|
|
"manageGroups": false, |
|
|
|
"managePolicies": false, |
|
|
|
"manageSso": false, // Not supported
|
|
|
|
@ -509,11 +579,12 @@ impl Membership { |
|
|
|
"familySponsorshipValidUntil": null, |
|
|
|
"familySponsorshipToDelete": null, |
|
|
|
"accessSecretsManager": false, |
|
|
|
// limit collection creation to managers with access_all permission to prevent issues
|
|
|
|
"limitCollectionCreation": self.atype < MembershipType::Manager || !self.access_all, |
|
|
|
"limitCollectionDeletion": true, |
|
|
|
"limitItemDeletion": false, |
|
|
|
"allowAdminAccessToAllCollectionItems": true, |
|
|
|
|
|
|
|
"allowAdminAccessToAllCollectionItems": org.collection_settings.get_flag(OrgCollectionSetting::AllowAdminAccessToAllCollectionItems), |
|
|
|
"limitCollectionCreation": org.collection_settings.get_flag(OrgCollectionSetting::LimitCollectionCreation), |
|
|
|
"limitCollectionDeletion": org.collection_settings.get_flag(OrgCollectionSetting::LimitCollectionDeletion), |
|
|
|
"limitItemDeletion": org.collection_settings.get_flag(OrgCollectionSetting::LimitItemDeletion), |
|
|
|
|
|
|
|
"userIsManagedByOrganization": false, // Means not managed via the Members UI, like SSO
|
|
|
|
"userIsClaimedByOrganization": false, // The new key instead of the obsolete userIsManagedByOrganization
|
|
|
|
|
|
|
|
|