headless_lms_server/controllers/course_material/
code_giveaways.rs1use crate::{domain::authorization::skip_authorize, prelude::*};
4use models::code_giveaways::CodeGiveawayStatus;
5
6#[instrument(skip(pool))]
10async fn get_giveaway_status(
11 user: AuthUser,
12 code_giveaway_id: web::Path<Uuid>,
13 pool: web::Data<PgPool>,
14) -> ControllerResult<web::Json<CodeGiveawayStatus>> {
15 let mut conn = pool.acquire().await?;
16 let token = skip_authorize();
17 let res =
18 models::code_giveaways::get_code_giveaway_status(&mut conn, *code_giveaway_id, user.id)
19 .await?;
20 token.authorized_ok(web::Json(res))
21}
22
23#[instrument(skip(pool))]
27async fn claim_code_from_code_giveaway(
28 user: AuthUser,
29 code_giveaway_id: web::Path<Uuid>,
30 pool: web::Data<PgPool>,
31) -> ControllerResult<web::Json<String>> {
32 let mut conn = pool.acquire().await?;
33 let token = skip_authorize();
34 let code_giveaway = models::code_giveaways::get_by_id(&mut conn, *code_giveaway_id).await?;
35 if !code_giveaway.enabled {
36 return Err(ControllerError::new(
37 ControllerErrorType::Forbidden,
38 "Code giveaway is not enabled.".to_string(),
39 None,
40 ));
41 }
42 if let Some(course_module_id) = code_giveaway.course_module_id {
43 let course_module_completions =
44 models::course_module_completions::get_all_by_user_id_and_course_module_id(
45 &mut conn,
46 user.id,
47 course_module_id,
48 )
49 .await?;
50
51 course_module_completions
52 .iter()
53 .find(|c| c.passed)
54 .ok_or_else(|| {
55 ControllerError::new(
56 ControllerErrorType::BadRequest,
57 "You have not completed the required course module.".to_string(),
58 None,
59 )
60 })?;
61 } else {
62 return Err(ControllerError::new(
63 ControllerErrorType::BadRequest,
64 "The required course module has not been configured to this code giveaway.".to_string(),
65 None,
66 ));
67 }
68
69 if let Some(question_id) = code_giveaway.require_course_specific_consent_form_question_id {
70 let answers =
71 models::research_forms::get_all_research_form_answers_with_user_course_and_question_id(
72 &mut conn,
73 user.id,
74 code_giveaway.course_id,
75 question_id,
76 )
77 .await
78 .optional()?;
79 if let Some(answers) = answers {
80 let consented = answers.iter().any(|a| a.research_consent);
81 if !consented {
82 return Err(ControllerError::new(
83 ControllerErrorType::BadRequest,
84 "You're not eligible for the code.".to_string(),
85 None,
86 ));
87 }
88 } else {
89 return Err(ControllerError::new(
90 ControllerErrorType::BadRequest,
91 "You have not completed the required research form.".to_string(),
92 None,
93 ));
94 }
95 }
96
97 let already_given_code =
98 models::code_giveaway_codes::get_code_given_to_user(&mut conn, *code_giveaway_id, user.id)
99 .await?
100 .map(|o| o.code);
101
102 if let Some(code) = already_given_code {
103 return token.authorized_ok(web::Json(code));
105 }
106
107 let give_code_result =
108 models::code_giveaway_codes::give_some_code_to_user(&mut conn, *code_giveaway_id, user.id)
109 .await;
110
111 if let Err(_e) = &give_code_result {
112 let codes_left =
113 models::code_giveaway_codes::are_any_codes_left(&mut conn, *code_giveaway_id).await?;
114 if !codes_left {
115 return Err(ControllerError::new(
116 ControllerErrorType::BadRequest,
117 "The giveaway has ran out of codes.".to_string(),
118 None,
119 ));
120 }
121 }
122
123 let code = give_code_result?.code;
124 token.authorized_ok(web::Json(code))
125}
126
127pub fn _add_routes(cfg: &mut ServiceConfig) {
128 cfg.route("/{id}/status", web::get().to(get_giveaway_status))
129 .route("/{id}/claim", web::post().to(claim_code_from_code_giveaway));
130}