2020-07-01 15:24:42 -05:00
use super ::ids ::Base62Id ;
2023-10-11 15:55:01 -07:00
use crate ::bitflags_serde_impl ;
2021-06-02 18:33:11 -07:00
use crate ::models ::users ::User ;
2022-10-30 23:34:56 -07:00
use rust_decimal ::Decimal ;
2020-09-28 21:05:42 -07:00
use serde ::{ Deserialize , Serialize } ;
2020-07-01 15:24:42 -05:00
/// The ID of a team
#[ derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize) ]
#[ serde(from = " Base62Id " ) ]
#[ serde(into = " Base62Id " ) ]
pub struct TeamId ( pub u64 ) ;
2020-10-14 13:19:38 -07:00
pub const OWNER_ROLE : & str = " Owner " ;
2021-07-27 16:50:07 -07:00
pub const DEFAULT_ROLE : & str = " Member " ;
2020-10-14 13:19:38 -07:00
2021-05-30 15:02:07 -07:00
/// A team of users who control a project
2020-07-01 15:24:42 -05:00
#[ derive(Serialize, Deserialize) ]
pub struct Team {
/// The id of the team
pub id : TeamId ,
/// A list of the members of the team
pub members : Vec < TeamMember > ,
}
2020-11-09 19:39:23 -07:00
bitflags ::bitflags! {
2023-10-11 15:55:01 -07:00
#[ derive(Copy, Clone, Debug) ]
2023-10-02 10:56:57 -07:00
pub struct ProjectPermissions : u64 {
2020-11-09 19:39:23 -07:00
const UPLOAD_VERSION = 1 < < 0 ;
const DELETE_VERSION = 1 < < 1 ;
const EDIT_DETAILS = 1 < < 2 ;
const EDIT_BODY = 1 < < 3 ;
const MANAGE_INVITES = 1 < < 4 ;
const REMOVE_MEMBER = 1 < < 5 ;
const EDIT_MEMBER = 1 < < 6 ;
2021-05-30 15:02:07 -07:00
const DELETE_PROJECT = 1 < < 7 ;
2022-09-02 12:38:58 -07:00
const VIEW_ANALYTICS = 1 < < 8 ;
const VIEW_PAYOUTS = 1 < < 9 ;
2023-09-13 22:22:32 -07:00
2022-09-02 12:38:58 -07:00
const ALL = 0b1111111111 ;
2020-11-09 19:39:23 -07:00
}
}
2023-10-11 15:55:01 -07:00
bitflags_serde_impl! ( ProjectPermissions , u64 ) ;
2023-10-02 10:56:57 -07:00
impl Default for ProjectPermissions {
fn default ( ) -> ProjectPermissions {
ProjectPermissions ::UPLOAD_VERSION | ProjectPermissions ::DELETE_VERSION
2020-11-09 19:39:23 -07:00
}
}
2023-10-02 10:56:57 -07:00
impl ProjectPermissions {
2023-09-11 14:21:50 -04:00
pub fn get_permissions_by_role (
role : & crate ::models ::users ::Role ,
2023-10-02 10:56:57 -07:00
project_team_member : & Option < crate ::database ::models ::TeamMember > , // team member of the user in the project
organization_team_member : & Option < crate ::database ::models ::TeamMember > , // team member of the user in the organization
2023-09-11 14:21:50 -04:00
) -> Option < Self > {
if role . is_admin ( ) {
2023-10-02 10:56:57 -07:00
return Some ( ProjectPermissions ::ALL ) ;
}
if let Some ( member ) = project_team_member {
return Some ( member . permissions ) ;
}
if let Some ( member ) = organization_team_member {
return Some ( member . permissions ) ; // Use default project permissions for the organization team member
}
if role . is_mod ( ) {
Some (
ProjectPermissions ::EDIT_DETAILS
| ProjectPermissions ::EDIT_BODY
| ProjectPermissions ::UPLOAD_VERSION ,
)
2023-09-11 14:21:50 -04:00
} else {
None
}
}
}
2023-10-02 10:56:57 -07:00
bitflags ::bitflags! {
2023-10-11 15:55:01 -07:00
#[ derive(Copy, Clone, Debug) ]
2023-10-02 10:56:57 -07:00
pub struct OrganizationPermissions : u64 {
const EDIT_DETAILS = 1 < < 0 ;
const EDIT_BODY = 1 < < 1 ;
const MANAGE_INVITES = 1 < < 2 ;
const REMOVE_MEMBER = 1 < < 3 ;
const EDIT_MEMBER = 1 < < 4 ;
const ADD_PROJECT = 1 < < 5 ;
const REMOVE_PROJECT = 1 < < 6 ;
const DELETE_ORGANIZATION = 1 < < 8 ;
const EDIT_MEMBER_DEFAULT_PERMISSIONS = 1 < < 9 ; // Separate from EDIT_MEMBER
const ALL = 0b1111111111 ;
const NONE = 0b0 ;
}
}
2023-10-11 15:55:01 -07:00
bitflags_serde_impl! ( OrganizationPermissions , u64 ) ;
2023-10-02 10:56:57 -07:00
impl Default for OrganizationPermissions {
fn default ( ) -> OrganizationPermissions {
OrganizationPermissions ::NONE
}
}
impl OrganizationPermissions {
pub fn get_permissions_by_role (
role : & crate ::models ::users ::Role ,
team_member : & Option < crate ::database ::models ::TeamMember > ,
) -> Option < Self > {
if role . is_admin ( ) {
return Some ( OrganizationPermissions ::ALL ) ;
}
if let Some ( member ) = team_member {
return member . organization_permissions ;
}
if role . is_mod ( ) {
return Some (
OrganizationPermissions ::EDIT_DETAILS
| OrganizationPermissions ::EDIT_BODY
| OrganizationPermissions ::ADD_PROJECT ,
) ;
}
None
}
}
2020-07-01 15:24:42 -05:00
/// A member of a team
2020-07-16 10:16:35 -07:00
#[ derive(Serialize, Deserialize, Clone) ]
2020-07-01 15:24:42 -05:00
pub struct TeamMember {
2020-12-27 18:50:10 -07:00
/// The ID of the team this team member is a member of
pub team_id : TeamId ,
2021-06-02 18:33:11 -07:00
/// The user associated with the member
pub user : User ,
2020-10-01 00:07:52 -05:00
/// The role of the user in the team
2020-07-16 10:16:35 -07:00
pub role : String ,
2023-10-02 10:56:57 -07:00
/// A bitset containing the user's permissions in this team.
/// In an organization-controlled project, these are the unique overriding permissions for the user's role for any project in the organization, if they exist.
/// In an organization, these are the default project permissions for any project in the organization.
/// Not optional- only None if they are being hidden from the user.
pub permissions : Option < ProjectPermissions > ,
/// A bitset containing the user's permissions in this organization.
/// In a project team, this is None.
pub organization_permissions : Option < OrganizationPermissions > ,
2020-12-26 22:49:07 -07:00
/// Whether the user has joined the team or is just invited to it
pub accepted : bool ,
2022-10-30 23:34:56 -07:00
#[ serde(with = " rust_decimal::serde::float_option " ) ]
2022-09-02 12:38:58 -07:00
/// Payouts split. This is a weighted average. For example. if a team has two members with this
/// value set to 25.0 for both members, they split revenue 50/50
2022-10-30 23:34:56 -07:00
pub payouts_split : Option < Decimal > ,
2022-12-23 14:34:04 -05:00
/// Ordering of the member in the list
pub ordering : i64 ,
2020-07-01 15:24:42 -05:00
}
2021-10-12 11:26:59 +08:00
impl TeamMember {
2023-07-08 14:29:17 -07:00
pub fn from (
data : crate ::database ::models ::team_item ::TeamMember ,
user : crate ::database ::models ::User ,
override_permissions : bool ,
) -> Self {
let user : User = user . into ( ) ;
2023-10-02 10:56:57 -07:00
Self ::from_model ( data , user , override_permissions )
}
2022-11-20 19:50:14 -07:00
2023-10-02 10:56:57 -07:00
// Use the User model directly instead of the database model,
// if already available.
// (Avoids a db query in some cases)
pub fn from_model (
data : crate ::database ::models ::team_item ::TeamMember ,
user : crate ::models ::users ::User ,
override_permissions : bool ,
) -> Self {
2021-10-12 11:26:59 +08:00
Self {
team_id : data . team_id . into ( ) ,
2022-11-20 19:50:14 -07:00
user ,
2021-10-12 11:26:59 +08:00
role : data . role ,
permissions : if override_permissions {
None
} else {
Some ( data . permissions )
} ,
2023-10-02 10:56:57 -07:00
organization_permissions : if override_permissions {
None
} else {
data . organization_permissions
} ,
2021-10-12 11:26:59 +08:00
accepted : data . accepted ,
2022-09-02 12:38:58 -07:00
payouts_split : if override_permissions {
None
} else {
Some ( data . payouts_split )
} ,
2022-12-23 14:34:04 -05:00
ordering : data . ordering ,
2021-10-12 11:26:59 +08:00
}
}
}