Initial work on payouts (badges, perms, splits) (#440)

* Initial work on payouts (badges, perms, splits)

* Fix clippy error, bitflag consistency
This commit is contained in:
Geometrically
2022-09-02 12:38:58 -07:00
committed by GitHub
parent 4c1dca73c4
commit e7c3f8bf47
13 changed files with 1030 additions and 801 deletions

View File

@@ -28,8 +28,6 @@ pub enum DatabaseError {
Database(#[from] sqlx::error::Error),
#[error("Error while trying to generate random ID")]
RandomId,
#[error("Invalid permissions bitflag!")]
Bitflag,
#[error("A database request failed")]
Other(String),
}

View File

@@ -1,6 +1,7 @@
use super::ids::*;
use crate::database::models::User;
use crate::models::teams::Permissions;
use crate::models::users::Badges;
pub struct TeamBuilder {
pub members: Vec<TeamMemberBuilder>,
@@ -10,6 +11,7 @@ pub struct TeamMemberBuilder {
pub role: String,
pub permissions: Permissions,
pub accepted: bool,
pub payouts_split: f32,
}
impl TeamBuilder {
@@ -41,6 +43,7 @@ impl TeamBuilder {
role: member.role,
permissions: member.permissions,
accepted: member.accepted,
payouts_split: member.payouts_split,
};
sqlx::query!(
@@ -78,6 +81,7 @@ pub struct TeamMember {
pub role: String,
pub permissions: Permissions,
pub accepted: bool,
pub payouts_split: f32,
}
/// A member of a team
@@ -89,6 +93,7 @@ pub struct QueryTeamMember {
pub role: String,
pub permissions: Permissions,
pub accepted: bool,
pub payouts_split: f32,
}
impl TeamMember {
@@ -104,7 +109,7 @@ impl TeamMember {
let team_members = sqlx::query!(
"
SELECT id, user_id, role, permissions, accepted
SELECT id, user_id, role, permissions, accepted, payouts_split
FROM team_members
WHERE team_id = $1
",
@@ -113,19 +118,16 @@ impl TeamMember {
.fetch_many(executor)
.try_filter_map(|e| async {
if let Some(m) = e.right() {
let permissions = Permissions::from_bits(m.permissions as u64);
if let Some(perms) = permissions {
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: id,
user_id: UserId(m.user_id),
role: m.role,
permissions: perms,
accepted: m.accepted,
})))
} else {
Ok(Some(Err(super::DatabaseError::Bitflag)))
}
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: id,
user_id: UserId(m.user_id),
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
})))
} else {
Ok(None)
}
@@ -152,10 +154,10 @@ impl TeamMember {
let team_members = sqlx::query!(
"
SELECT tm.id id, tm.role member_role, tm.permissions permissions, tm.accepted accepted,
SELECT tm.id id, tm.role member_role, tm.permissions permissions, tm.accepted accepted, tm.payouts_split payouts_split,
u.id user_id, u.github_id github_id, u.name user_name, u.email email,
u.avatar_url avatar_url, u.username username, u.bio bio,
u.created created, u.role user_role
u.created created, u.role user_role, u.badges badges
FROM team_members tm
INNER JOIN users u ON u.id = tm.user_id
WHERE tm.team_id = $1
@@ -165,13 +167,12 @@ impl TeamMember {
.fetch_many(executor)
.try_filter_map(|e| async {
if let Some(m) = e.right() {
let permissions = Permissions::from_bits(m.permissions as u64);
if let Some(perms) = permissions {
Ok(Some(Ok(QueryTeamMember {
id: TeamMemberId(m.id),
team_id: id,
role: m.member_role,
permissions: perms,
permissions: Permissions::from_bits(m.permissions as u64).unwrap_or_default(),
accepted: m.accepted,
user: User {
id: UserId(m.user_id),
@@ -183,11 +184,10 @@ impl TeamMember {
bio: m.bio,
created: m.created,
role: m.user_role,
badges: Badges::from_bits(m.badges as u64).unwrap_or_default(),
},
payouts_split: m.payouts_split
})))
} else {
Ok(Some(Err(super::DatabaseError::Bitflag)))
}
} else {
Ok(None)
}
@@ -216,10 +216,10 @@ impl TeamMember {
let teams = sqlx::query!(
"
SELECT tm.id id, tm.team_id team_id, tm.role member_role, tm.permissions permissions, tm.accepted accepted,
SELECT tm.id id, tm.team_id team_id, tm.role member_role, tm.permissions permissions, tm.accepted accepted, tm.payouts_split payouts_split,
u.id user_id, u.github_id github_id, u.name user_name, u.email email,
u.avatar_url avatar_url, u.username username, u.bio bio,
u.created created, u.role user_role
u.created created, u.role user_role, u.badges badges
FROM team_members tm
INNER JOIN users u ON u.id = tm.user_id
WHERE tm.team_id = ANY($1)
@@ -230,13 +230,12 @@ impl TeamMember {
.fetch_many(exec)
.try_filter_map(|e| async {
if let Some(m) = e.right() {
let permissions = Permissions::from_bits(m.permissions as u64);
if let Some(perms) = permissions {
Ok(Some(Ok(QueryTeamMember {
id: TeamMemberId(m.id),
team_id: TeamId(m.team_id),
role: m.member_role,
permissions: perms,
permissions: Permissions::from_bits(m.permissions as u64).unwrap_or_default(),
accepted: m.accepted,
user: User {
id: UserId(m.user_id),
@@ -248,11 +247,10 @@ impl TeamMember {
bio: m.bio,
created: m.created,
role: m.user_role,
badges: Badges::from_bits(m.badges as u64).unwrap_or_default(),
},
payouts_split: m.payouts_split
})))
} else {
Ok(Some(Err(super::DatabaseError::Bitflag)))
}
} else {
Ok(None)
}
@@ -279,7 +277,7 @@ impl TeamMember {
let team_members = sqlx::query!(
"
SELECT id, team_id, role, permissions, accepted
SELECT id, team_id, role, permissions, accepted, payouts_split
FROM team_members
WHERE (user_id = $1 AND accepted = TRUE)
",
@@ -288,19 +286,16 @@ impl TeamMember {
.fetch_many(executor)
.try_filter_map(|e| async {
if let Some(m) = e.right() {
let permissions = Permissions::from_bits(m.permissions as u64);
if let Some(perms) = permissions {
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: TeamId(m.team_id),
user_id: id,
role: m.role,
permissions: perms,
accepted: m.accepted,
})))
} else {
Ok(Some(Err(super::DatabaseError::Bitflag)))
}
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: TeamId(m.team_id),
user_id: id,
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
})))
} else {
Ok(None)
}
@@ -327,7 +322,7 @@ impl TeamMember {
let team_members = sqlx::query!(
"
SELECT id, team_id, role, permissions, accepted
SELECT id, team_id, role, permissions, accepted, payouts_split
FROM team_members
WHERE user_id = $1
",
@@ -336,19 +331,16 @@ impl TeamMember {
.fetch_many(executor)
.try_filter_map(|e| async {
if let Some(m) = e.right() {
let permissions = Permissions::from_bits(m.permissions as u64);
if let Some(perms) = permissions {
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: TeamId(m.team_id),
user_id: id,
role: m.role,
permissions: perms,
accepted: m.accepted,
})))
} else {
Ok(Some(Err(super::DatabaseError::Bitflag)))
}
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: TeamId(m.team_id),
user_id: id,
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
})))
} else {
Ok(None)
}
@@ -374,7 +366,7 @@ impl TeamMember {
{
let result = sqlx::query!(
"
SELECT id, user_id, role, permissions, accepted
SELECT id, user_id, role, permissions, accepted, payouts_split
FROM team_members
WHERE (team_id = $1 AND user_id = $2 AND accepted = TRUE)
",
@@ -391,8 +383,9 @@ impl TeamMember {
user_id,
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.ok_or(super::DatabaseError::Bitflag)?,
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
}))
} else {
Ok(None)
@@ -415,7 +408,7 @@ impl TeamMember {
let team_members = sqlx::query!(
"
SELECT id, team_id, user_id, role, permissions, accepted
SELECT id, team_id, user_id, role, permissions, accepted, payouts_split
FROM team_members
WHERE (team_id = ANY($1) AND user_id = $2 AND accepted = TRUE)
",
@@ -425,19 +418,15 @@ impl TeamMember {
.fetch_many(executor)
.try_filter_map(|e| async {
if let Some(m) = e.right() {
let permissions = Permissions::from_bits(m.permissions as u64);
if let Some(perms) = permissions {
Ok(Some(Ok(TeamMember {
id: TeamMemberId(m.id),
team_id: TeamId(m.team_id),
user_id,
role: m.role,
permissions: perms,
permissions: Permissions::from_bits(m.permissions as u64).unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split
})))
} else {
Ok(Some(Err(super::DatabaseError::Bitflag)))
}
} else {
Ok(None)
}
@@ -463,7 +452,7 @@ impl TeamMember {
{
let result = sqlx::query!(
"
SELECT id, user_id, role, permissions, accepted
SELECT id, user_id, role, permissions, accepted, payouts_split
FROM team_members
WHERE (team_id = $1 AND user_id = $2)
",
@@ -480,8 +469,9 @@ impl TeamMember {
user_id,
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.ok_or(super::DatabaseError::Bitflag)?,
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
}))
} else {
Ok(None)
@@ -550,6 +540,7 @@ impl TeamMember {
new_permissions: Option<Permissions>,
new_role: Option<String>,
new_accepted: Option<bool>,
new_payouts_split: Option<f32>,
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<(), super::DatabaseError> {
if let Some(permissions) = new_permissions {
@@ -598,6 +589,21 @@ impl TeamMember {
}
}
if let Some(payouts_split) = new_payouts_split {
sqlx::query!(
"
UPDATE team_members
SET payouts_split = $1
WHERE (team_id = $2 AND user_id = $3)
",
payouts_split,
id as TeamId,
user_id as UserId,
)
.execute(&mut *transaction)
.await?;
}
Ok(())
}
@@ -611,7 +617,7 @@ impl TeamMember {
{
let result = sqlx::query!(
"
SELECT tm.id, tm.team_id, tm.user_id, tm.role, tm.permissions, tm.accepted FROM mods m
SELECT tm.id, tm.team_id, tm.user_id, tm.role, tm.permissions, tm.accepted, tm.payouts_split FROM mods m
INNER JOIN team_members tm ON tm.team_id = m.team_id AND user_id = $2 AND accepted = TRUE
WHERE m.id = $1
",
@@ -628,8 +634,9 @@ impl TeamMember {
user_id,
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.ok_or(super::DatabaseError::Bitflag)?,
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
}))
} else {
Ok(None)
@@ -646,7 +653,7 @@ impl TeamMember {
{
let result = sqlx::query!(
"
SELECT tm.id, tm.team_id, tm.user_id, tm.role, tm.permissions, tm.accepted FROM versions v
SELECT tm.id, tm.team_id, tm.user_id, tm.role, tm.permissions, tm.accepted, tm.payouts_split FROM versions v
INNER JOIN mods m ON m.id = v.mod_id
INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.user_id = $2 AND tm.accepted = TRUE
WHERE v.id = $1
@@ -664,8 +671,9 @@ impl TeamMember {
user_id,
role: m.role,
permissions: Permissions::from_bits(m.permissions as u64)
.ok_or(super::DatabaseError::Bitflag)?,
.unwrap_or_default(),
accepted: m.accepted,
payouts_split: m.payouts_split,
}))
} else {
Ok(None)

View File

@@ -1,4 +1,5 @@
use super::ids::{ProjectId, UserId};
use crate::models::users::Badges;
use chrono::{DateTime, Utc};
pub struct User {
@@ -11,6 +12,7 @@ pub struct User {
pub bio: Option<String>,
pub created: DateTime<Utc>,
pub role: String,
pub badges: Badges,
}
impl User {
@@ -54,7 +56,7 @@ impl User {
"
SELECT u.github_id, u.name, u.email,
u.avatar_url, u.username, u.bio,
u.created, u.role
u.created, u.role, u.badges
FROM users u
WHERE u.id = $1
",
@@ -74,6 +76,8 @@ impl User {
bio: row.bio,
created: row.created,
role: row.role,
badges: Badges::from_bits(row.badges as u64)
.unwrap_or_default(),
}))
} else {
Ok(None)
@@ -91,7 +95,7 @@ impl User {
"
SELECT u.id, u.name, u.email,
u.avatar_url, u.username, u.bio,
u.created, u.role
u.created, u.role, u.badges
FROM users u
WHERE u.github_id = $1
",
@@ -111,6 +115,8 @@ impl User {
bio: row.bio,
created: row.created,
role: row.role,
badges: Badges::from_bits(row.badges as u64)
.unwrap_or_default(),
}))
} else {
Ok(None)
@@ -128,7 +134,7 @@ impl User {
"
SELECT u.id, u.github_id, u.name, u.email,
u.avatar_url, u.username, u.bio,
u.created, u.role
u.created, u.role, u.badges
FROM users u
WHERE LOWER(u.username) = LOWER($1)
",
@@ -148,6 +154,8 @@ impl User {
bio: row.bio,
created: row.created,
role: row.role,
badges: Badges::from_bits(row.badges as u64)
.unwrap_or_default(),
}))
} else {
Ok(None)
@@ -169,7 +177,8 @@ impl User {
"
SELECT u.id, u.github_id, u.name, u.email,
u.avatar_url, u.username, u.bio,
u.created, u.role FROM users u
u.created, u.role, u.badges
FROM users u
WHERE u.id = ANY($1)
",
&user_ids_parsed
@@ -186,6 +195,7 @@ impl User {
bio: u.bio,
created: u.created,
role: u.role,
badges: Badges::from_bits(u.badges as u64).unwrap_or_default(),
}))
})
.try_collect::<Vec<User>>()