headless_lms_server/controllers/main_frontend/
users.rs

1use crate::prelude::*;
2use models::{
3    course_instance_enrollments::CourseInstanceEnrollmentsInfo, courses::Course,
4    exercise_reset_logs::ExerciseResetLog, research_forms::ResearchFormQuestionAnswer,
5    user_research_consents::UserResearchConsent, users::User,
6};
7
8/**
9GET `/api/v0/main-frontend/users/:id`
10*/
11#[instrument(skip(pool))]
12pub async fn get_user(
13    user_id: web::Path<Uuid>,
14    pool: web::Data<PgPool>,
15) -> ControllerResult<web::Json<User>> {
16    let mut conn = pool.acquire().await?;
17    let user = models::users::get_by_id(&mut conn, *user_id).await?;
18
19    let token = authorize(&mut conn, Act::Teach, Some(*user_id), Res::AnyCourse).await?;
20    token.authorized_ok(web::Json(user))
21}
22
23/**
24GET `/api/v0/main-frontend/users/:id/course-instance-enrollments`
25*/
26#[instrument(skip(pool))]
27pub async fn get_course_instance_enrollments_for_user(
28    user_id: web::Path<Uuid>,
29    pool: web::Data<PgPool>,
30    auth_user: AuthUser,
31) -> ControllerResult<web::Json<CourseInstanceEnrollmentsInfo>> {
32    let mut conn = pool.acquire().await?;
33    let token = authorize(
34        &mut conn,
35        Act::ViewUserProgressOrDetails,
36        Some(auth_user.id),
37        Res::GlobalPermissions,
38    )
39    .await?;
40    let mut res =
41        models::course_instance_enrollments::get_course_instance_enrollments_info_for_user(
42            &mut conn, *user_id,
43        )
44        .await?;
45
46    res.course_instance_enrollments
47        .sort_by(|a, b| a.created_at.cmp(&b.created_at));
48
49    token.authorized_ok(web::Json(res))
50}
51
52#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
53#[cfg_attr(feature = "ts_rs", derive(TS))]
54pub struct ConsentData {
55    pub consent: bool,
56}
57
58/**
59POST `/api/v0/main-frontend/users/user-research-consents` - Adds a research consent for a student.
60*/
61#[instrument(skip(pool))]
62pub async fn post_user_consents(
63    payload: web::Json<ConsentData>,
64    user: AuthUser,
65    pool: web::Data<PgPool>,
66) -> ControllerResult<web::Json<UserResearchConsent>> {
67    let mut conn = pool.acquire().await?;
68    let token = skip_authorize();
69
70    let res = models::user_research_consents::upsert(
71        &mut conn,
72        PKeyPolicy::Generate,
73        user.id,
74        payload.consent,
75    )
76    .await?;
77    token.authorized_ok(web::Json(res))
78}
79
80/**
81GET `/api/v0/main-frontend/users/get-user-research-consent` - Gets users research consent.
82*/
83#[instrument(skip(pool))]
84pub async fn get_research_consent_by_user_id(
85    user: AuthUser,
86    pool: web::Data<PgPool>,
87) -> ControllerResult<web::Json<UserResearchConsent>> {
88    let mut conn = pool.acquire().await?;
89    let token = skip_authorize();
90
91    let res =
92        models::user_research_consents::get_research_consent_by_user_id(&mut conn, user.id).await?;
93
94    token.authorized_ok(web::Json(res))
95}
96
97/**
98GET `/api/v0/main-frontend/users/get-user-research-consents` - Gets all users research consents for a course specific research form.
99*/
100#[instrument(skip(pool))]
101async fn get_all_research_form_answers_with_user_id(
102    user: AuthUser,
103    pool: web::Data<PgPool>,
104) -> ControllerResult<web::Json<Vec<ResearchFormQuestionAnswer>>> {
105    let mut conn = pool.acquire().await?;
106    let token = skip_authorize();
107
108    let res =
109        models::research_forms::get_all_research_form_answers_with_user_id(&mut conn, user.id)
110            .await?;
111
112    token.authorized_ok(web::Json(res))
113}
114
115/**
116GET `/api/v0/main-frontend/users/my-courses` - Gets all the courses the user has either started or gotten a permission to.
117*/
118#[instrument(skip(pool))]
119async fn get_my_courses(
120    user: AuthUser,
121    pool: web::Data<PgPool>,
122) -> ControllerResult<web::Json<Vec<Course>>> {
123    let mut conn = pool.acquire().await?;
124    let token = skip_authorize();
125
126    let courses_enrolled_to =
127        models::courses::all_courses_user_enrolled_to(&mut conn, user.id).await?;
128
129    let courses_with_roles =
130        models::courses::all_courses_with_roles_for_user(&mut conn, user.id).await?;
131
132    let combined = courses_enrolled_to
133        .clone()
134        .into_iter()
135        .chain(
136            courses_with_roles
137                .into_iter()
138                .filter(|c| !courses_enrolled_to.iter().any(|c2| c.id == c2.id)),
139        )
140        .collect();
141
142    token.authorized_ok(web::Json(combined))
143}
144
145/**
146GET `/api/v0/main-frontend/users/:id/user-reset-exercise-logs` - Get all logs of reset exercises for a user
147*/
148#[instrument(skip(pool))]
149pub async fn get_user_reset_exercise_logs(
150    user_id: web::Path<Uuid>,
151    pool: web::Data<PgPool>,
152    auth_user: AuthUser,
153) -> ControllerResult<web::Json<Vec<ExerciseResetLog>>> {
154    let mut conn = pool.acquire().await?;
155    let token = authorize(
156        &mut conn,
157        Act::ViewUserProgressOrDetails,
158        Some(auth_user.id),
159        Res::GlobalPermissions,
160    )
161    .await?;
162    let res =
163        models::exercise_reset_logs::get_exercise_reset_logs_for_user(&mut conn, *user_id).await?;
164
165    token.authorized_ok(web::Json(res))
166}
167
168pub fn _add_routes(cfg: &mut ServiceConfig) {
169    cfg.route(
170        "/user-research-form-question-answers",
171        web::get().to(get_all_research_form_answers_with_user_id),
172    )
173    .route("/my-courses", web::get().to(get_my_courses))
174    .route(
175        "/get-user-research-consent",
176        web::get().to(get_research_consent_by_user_id),
177    )
178    .route("/{user_id}", web::get().to(get_user))
179    .route(
180        "/{user_id}/course-instance-enrollments",
181        web::get().to(get_course_instance_enrollments_for_user),
182    )
183    .route(
184        "/user-research-consents",
185        web::post().to(post_user_consents),
186    )
187    .route(
188        "/{user_id}/user-reset-exercise-logs",
189        web::get().to(get_user_reset_exercise_logs),
190    );
191}