Skip to main content

max / makenotwork

1.8 KB · 55 lines History Blame Raw
1 //! Invite code generation for creators.
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 /// Generate a new invite code for the authenticated creator.
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 // Only creators can generate invites
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 // Check limit
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 // Generate and store
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