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