Files
AstralRinth/apps/labrinth/src/models/v3/user_limits.rs
aecsocket f466470d06 Hard caps on creating projects/orgs/collections (#4430)
* implement backend limits on project creation

* implement collection, org creation hard caps

* Fix limit api

* Fix clippy

* Fix limits

* Update sqlx queries

* Address PR comments on user limit structure

* sqlx prepare and clippy

* fix test maybe
2025-09-28 10:01:00 +00:00

100 lines
2.6 KiB
Rust

use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use crate::{
database::models::{DBUserId, user_limits::DBUserLimits},
models::users::User,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserLimits {
pub current: u64,
pub max: u64,
}
impl UserLimits {
fn adjust_for_user(self, user: &User) -> Self {
if user.role.is_admin() {
Self {
current: self.current,
max: u64::MAX,
}
} else {
self
}
}
pub async fn get_for_projects(
user: &User,
pool: &PgPool,
) -> Result<Self, sqlx::Error> {
let user_id = DBUserId::from(user.id);
let db_limits =
DBUserLimits::get(DBUserId::from(user.id), pool).await?;
let current = sqlx::query_scalar!(
"SELECT COUNT(*) FROM mods m
JOIN teams t ON m.team_id = t.id
JOIN team_members tm ON t.id = tm.team_id
WHERE tm.user_id = $1",
user_id as DBUserId,
)
.fetch_one(pool)
.await?
.map_or(0, |x| x as u64);
Ok(Self {
current,
max: db_limits.projects,
}
.adjust_for_user(user))
}
pub async fn get_for_organizations(
user: &User,
pool: &PgPool,
) -> Result<Self, sqlx::Error> {
let user_id = DBUserId::from(user.id);
let db_limits =
DBUserLimits::get(DBUserId::from(user.id), pool).await?;
let current = sqlx::query_scalar!(
"SELECT COUNT(*) FROM organizations o
JOIN teams t ON o.team_id = t.id
JOIN team_members tm ON t.id = tm.team_id
WHERE tm.user_id = $1",
user_id as DBUserId,
)
.fetch_one(pool)
.await?
.map_or(0, |x| x as u64);
Ok(Self {
current,
max: db_limits.organizations,
}
.adjust_for_user(user))
}
pub async fn get_for_collections(
user: &User,
pool: &PgPool,
) -> Result<Self, sqlx::Error> {
let user_id = DBUserId::from(user.id);
let db_limits =
DBUserLimits::get(DBUserId::from(user.id), pool).await?;
let current = sqlx::query_scalar!(
"SELECT COUNT(*) FROM collections
WHERE user_id = $1",
user_id as DBUserId,
)
.fetch_one(pool)
.await?
.map_or(0, |x| x as u64);
Ok(Self {
current,
max: db_limits.collections,
}
.adjust_for_user(user))
}
}