| 1 |
|
| 2 |
|
| 3 |
use axum::{extract::State, response::IntoResponse}; |
| 4 |
|
| 5 |
use sqlx::PgPool; |
| 6 |
|
| 7 |
use crate::{ |
| 8 |
auth::AuthUser, |
| 9 |
constants, db, |
| 10 |
error::{AppError, Result}, |
| 11 |
templates::AlertTemplate, |
| 12 |
}; |
| 13 |
|
| 14 |
|
| 15 |
#[tracing::instrument(skip_all, name = "api::create_invite")] |
| 16 |
pub(in crate::routes::api) async fn create_invite( |
| 17 |
State(db): State<PgPool>, |
| 18 |
AuthUser(user): AuthUser, |
| 19 |
) -> Result<impl IntoResponse> { |
| 20 |
user.check_not_sandbox()?; |
| 21 |
if !constants::INVITES_ENABLED { |
| 22 |
return Ok(AlertTemplate::new("error", "Invites are currently disabled.").into_response()); |
| 23 |
} |
| 24 |
|
| 25 |
|
| 26 |
let db_user = db::users::get_user_by_id(&db, user.id) |
| 27 |
.await? |
| 28 |
.ok_or(AppError::NotFound)?; |
| 29 |
|
| 30 |
if !db_user.can_create_projects { |
| 31 |
return Ok(AlertTemplate::new( |
| 32 |
"error", |
| 33 |
"You need creator access to generate invite codes.", |
| 34 |
) |
| 35 |
.into_response()); |
| 36 |
} |
| 37 |
|
| 38 |
|
| 39 |
let active_count = db::invites::count_active_invites(&db, user.id).await?; |
| 40 |
if active_count >= constants::INVITE_LIMIT_PER_CREATOR { |
| 41 |
return Ok(AlertTemplate::new( |
| 42 |
"error", |
| 43 |
&format!( |
| 44 |
"You have reached the limit of {} active invite codes.", |
| 45 |
constants::INVITE_LIMIT_PER_CREATOR |
| 46 |
), |
| 47 |
) |
| 48 |
.into_response()); |
| 49 |
} |
| 50 |
|
| 51 |
|
| 52 |
let code = db::invites::generate_invite_code(); |
| 53 |
db::invites::create_invite_code(&db, user.id, &code).await?; |
| 54 |
|
| 55 |
let formatted = db::invites::format_invite_code(&code); |
| 56 |
let link = format!("makenot.work/join?invite={formatted}"); |
| 57 |
|
| 58 |
Ok(AlertTemplate::new("success", &format!("Invite code: {formatted} {link}")).into_response()) |
| 59 |
} |
| 60 |
|