You've already forked AstralRinth
forked from didirus/AstralRinth
Search test + v3 (#731)
* search patch for accurate loader/gv filtering * backup * basic search test * finished test * incomplete commit; backing up * Working multipat reroute backup * working rough draft v3 * most tests passing * works * search v2 conversion * added some tags.rs v2 conversions * Worked through warnings, unwraps, prints * refactors * new search test * version files changes fixes * redesign to revs * removed old caches * removed games * fmt clippy * merge conflicts * fmt, prepare * moved v2 routes over to v3 * fixes; tests passing * project type changes * moved files over * fmt, clippy, prepare, etc * loaders to loader_fields, added tests * fmt, clippy, prepare * fixed sorting bug * reversed back- wrong order for consistency * fmt; clippy; prepare --------- Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
200
src/models/v3/teams.rs
Normal file
200
src/models/v3/teams.rs
Normal file
@@ -0,0 +1,200 @@
|
||||
use super::ids::Base62Id;
|
||||
use crate::bitflags_serde_impl;
|
||||
use crate::models::users::User;
|
||||
use rust_decimal::Decimal;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The ID of a team
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(from = "Base62Id")]
|
||||
#[serde(into = "Base62Id")]
|
||||
pub struct TeamId(pub u64);
|
||||
|
||||
pub const OWNER_ROLE: &str = "Owner";
|
||||
pub const DEFAULT_ROLE: &str = "Member";
|
||||
|
||||
/// A team of users who control a project
|
||||
#[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>,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ProjectPermissions: u64 {
|
||||
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;
|
||||
const DELETE_PROJECT = 1 << 7;
|
||||
const VIEW_ANALYTICS = 1 << 8;
|
||||
const VIEW_PAYOUTS = 1 << 9;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags_serde_impl!(ProjectPermissions, u64);
|
||||
|
||||
impl Default for ProjectPermissions {
|
||||
fn default() -> ProjectPermissions {
|
||||
ProjectPermissions::UPLOAD_VERSION | ProjectPermissions::DELETE_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
impl ProjectPermissions {
|
||||
pub fn get_permissions_by_role(
|
||||
role: &crate::models::users::Role,
|
||||
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
|
||||
) -> Option<Self> {
|
||||
if role.is_admin() {
|
||||
return Some(ProjectPermissions::all());
|
||||
}
|
||||
|
||||
if let Some(member) = project_team_member {
|
||||
if member.accepted {
|
||||
return Some(member.permissions);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(member) = organization_team_member {
|
||||
if member.accepted {
|
||||
return Some(member.permissions);
|
||||
}
|
||||
}
|
||||
|
||||
if role.is_mod() {
|
||||
Some(
|
||||
ProjectPermissions::EDIT_DETAILS
|
||||
| ProjectPermissions::EDIT_BODY
|
||||
| ProjectPermissions::UPLOAD_VERSION,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OrganizationPermissions: u64 {
|
||||
const EDIT_DETAILS = 1 << 0;
|
||||
const MANAGE_INVITES = 1 << 1;
|
||||
const REMOVE_MEMBER = 1 << 2;
|
||||
const EDIT_MEMBER = 1 << 3;
|
||||
const ADD_PROJECT = 1 << 4;
|
||||
const REMOVE_PROJECT = 1 << 5;
|
||||
const DELETE_ORGANIZATION = 1 << 6;
|
||||
const EDIT_MEMBER_DEFAULT_PERMISSIONS = 1 << 7; // Separate from EDIT_MEMBER
|
||||
const NONE = 0b0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags_serde_impl!(OrganizationPermissions, u64);
|
||||
|
||||
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 {
|
||||
if member.accepted {
|
||||
return member.organization_permissions;
|
||||
}
|
||||
}
|
||||
if role.is_mod() {
|
||||
return Some(
|
||||
OrganizationPermissions::EDIT_DETAILS | OrganizationPermissions::ADD_PROJECT,
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// A member of a team
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct TeamMember {
|
||||
/// The ID of the team this team member is a member of
|
||||
pub team_id: TeamId,
|
||||
/// The user associated with the member
|
||||
pub user: User,
|
||||
/// The role of the user in the team
|
||||
pub role: String,
|
||||
/// 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>,
|
||||
|
||||
/// Whether the user has joined the team or is just invited to it
|
||||
pub accepted: bool,
|
||||
|
||||
#[serde(with = "rust_decimal::serde::float_option")]
|
||||
/// 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
|
||||
pub payouts_split: Option<Decimal>,
|
||||
/// Ordering of the member in the list
|
||||
pub ordering: i64,
|
||||
}
|
||||
|
||||
impl TeamMember {
|
||||
pub fn from(
|
||||
data: crate::database::models::team_item::TeamMember,
|
||||
user: crate::database::models::User,
|
||||
override_permissions: bool,
|
||||
) -> Self {
|
||||
let user: User = user.into();
|
||||
Self::from_model(data, user, override_permissions)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Self {
|
||||
team_id: data.team_id.into(),
|
||||
user,
|
||||
role: data.role,
|
||||
permissions: if override_permissions {
|
||||
None
|
||||
} else {
|
||||
Some(data.permissions)
|
||||
},
|
||||
organization_permissions: if override_permissions {
|
||||
None
|
||||
} else {
|
||||
data.organization_permissions
|
||||
},
|
||||
accepted: data.accepted,
|
||||
payouts_split: if override_permissions {
|
||||
None
|
||||
} else {
|
||||
Some(data.payouts_split)
|
||||
},
|
||||
ordering: data.ordering,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user