headless_lms_server/controllers/main_frontend/
course_modules.rs1use headless_lms_models::course_module_completions::CourseModuleCompletion;
2use headless_lms_models::suspected_cheaters::ThresholdData;
3use models::{
4 course_modules::{self, CourseModule},
5 library::progressing::{CompletionRegistrationLink, UserCompletionInformation},
6 suspected_cheaters,
7};
8
9use crate::prelude::*;
10
11#[instrument(skip(pool))]
17async fn get_course_module(
18 course_module_id: web::Path<Uuid>,
19 pool: web::Data<PgPool>,
20 user: AuthUser,
21) -> ControllerResult<web::Json<CourseModule>> {
22 let mut conn = pool.acquire().await?;
23 let course_module = course_modules::get_by_id(&mut conn, *course_module_id).await?;
24 let token = authorize(
25 &mut conn,
26 Act::View,
27 Some(user.id),
28 Res::Course(course_module.course_id),
29 )
30 .await?;
31 token.authorized_ok(web::Json(course_module))
32}
33
34#[instrument(skip(pool))]
40async fn get_course_module_completion_information_for_user(
41 course_module_id: web::Path<Uuid>,
42 pool: web::Data<PgPool>,
43 user: AuthUser,
44) -> ControllerResult<web::Json<UserCompletionInformation>> {
45 let mut conn = pool.acquire().await?;
46 let course_module = course_modules::get_by_id(&mut conn, *course_module_id).await?;
47 let token = authorize(
49 &mut conn,
50 Act::View,
51 Some(user.id),
52 Res::Course(course_module.course_id),
53 )
54 .await?;
55 let information = models::library::progressing::get_user_completion_information(
56 &mut conn,
57 user.id,
58 &course_module,
59 )
60 .await?;
61 token.authorized_ok(web::Json(information))
62}
63
64#[instrument(skip(pool))]
68async fn get_course_module_completion_registration_link(
69 course_module_id: web::Path<Uuid>,
70 pool: web::Data<PgPool>,
71 user: AuthUser,
72) -> ControllerResult<web::Json<CompletionRegistrationLink>> {
73 let mut conn = pool.acquire().await?;
74 let course_module = course_modules::get_by_id(&mut conn, *course_module_id).await?;
75 let token = authorize(
77 &mut conn,
78 Act::View,
79 Some(user.id),
80 Res::Course(course_module.course_id),
81 )
82 .await?;
83 let completion_registration_link =
84 models::library::progressing::get_completion_registration_link_and_save_attempt(
85 &mut conn,
86 user.id,
87 &course_module,
88 )
89 .await?;
90 token.authorized_ok(web::Json(completion_registration_link))
91}
92
93async fn enable_or_disable_certificate_generation(
94 params: web::Path<(Uuid, bool)>,
95 pool: web::Data<PgPool>,
96 user: AuthUser,
97) -> ControllerResult<web::Json<bool>> {
98 let mut conn = pool.acquire().await?;
99 let (course_module_id, enabled) = params.into_inner();
100
101 let course_module = course_modules::get_by_id(&mut conn, course_module_id).await?;
102 let token = authorize(
104 &mut conn,
105 Act::Edit,
106 Some(user.id),
107 Res::Course(course_module.course_id),
108 )
109 .await?;
110 models::course_modules::update_certification_enabled(&mut conn, course_module_id, enabled)
111 .await?;
112
113 token.authorized_ok(web::Json(true))
114}
115
116#[instrument(skip(pool))]
122async fn get_best_course_module_completion_for_user(
123 course_module_id: web::Path<Uuid>,
124 pool: web::Data<PgPool>,
125 user: AuthUser,
126) -> ControllerResult<web::Json<Option<CourseModuleCompletion>>> {
127 let mut conn = pool.acquire().await?;
128 let course_module = course_modules::get_by_id(&mut conn, *course_module_id).await?;
129
130 let token = authorize(
131 &mut conn,
132 Act::View,
133 Some(user.id),
134 Res::Course(course_module.course_id),
135 )
136 .await?;
137
138 let information =
139 models::course_module_completions::get_best_completion_by_user_and_course_module_id(
140 &mut conn,
141 user.id,
142 *course_module_id,
143 )
144 .await?;
145 token.authorized_ok(web::Json(information))
146}
147
148#[instrument(skip(pool))]
152async fn insert_threshold_for_module(
153 pool: web::Data<PgPool>,
154 params: web::Path<Uuid>,
155 payload: web::Json<ThresholdData>,
156 user: AuthUser,
157) -> ControllerResult<web::Json<()>> {
158 let mut conn = pool.acquire().await?;
159
160 let course_module_id = params.into_inner();
161 let new_threshold = payload.0;
162
163 let course_module = course_modules::get_by_id(&mut conn, course_module_id).await?;
164 let token = authorize(
165 &mut conn,
166 Act::Edit,
167 Some(user.id),
168 Res::Course(course_module.course_id),
169 )
170 .await?;
171
172 suspected_cheaters::insert_thresholds_by_module_id(
173 &mut conn,
174 course_module_id,
175 new_threshold.duration_seconds,
176 )
177 .await?;
178
179 token.authorized_ok(web::Json(()))
180}
181
182#[instrument(skip(pool))]
186async fn delete_threshold_for_module(
187 pool: web::Data<PgPool>,
188 params: web::Path<Uuid>,
189 user: AuthUser,
190) -> ControllerResult<web::Json<()>> {
191 let mut conn = pool.acquire().await?;
192
193 let course_module_id = params.into_inner();
194
195 let course_module = course_modules::get_by_id(&mut conn, course_module_id).await?;
196 let token = authorize(
197 &mut conn,
198 Act::Edit,
199 Some(user.id),
200 Res::Course(course_module.course_id),
201 )
202 .await?;
203
204 suspected_cheaters::delete_threshold_for_module(&mut conn, course_module_id).await?;
205
206 token.authorized_ok(web::Json(()))
207}
208
209pub fn _add_routes(cfg: &mut ServiceConfig) {
217 cfg.route("/{course_module_id}", web::get().to(get_course_module))
218 .route(
219 "/{course_module_id}/user-completion",
220 web::get().to(get_course_module_completion_information_for_user),
221 )
222 .route(
223 "/{course_module_id}/completion-registration-link",
224 web::get().to(get_course_module_completion_registration_link),
225 )
226 .route(
227 "/{course_module_id}/set-certificate-generation/{enabled}",
228 web::post().to(enable_or_disable_certificate_generation),
229 )
230 .route(
231 "/{course_module_id}/course-module-completion",
232 web::get().to(get_best_course_module_completion_for_user),
233 )
234 .route(
235 "/{course_module_id}/threshold",
236 web::post().to(insert_threshold_for_module),
237 )
238 .route(
239 "/{course_module_id}/threshold",
240 web::delete().to(delete_threshold_for_module),
241 );
242}