headless_lms_server/controllers/course_material/
pages.rs

1//! Controllers for requests starting with `/api/v0/course-material/pages`.
2
3use crate::{domain::authorization::skip_authorize, prelude::*};
4use models::pages::{
5    IsChapterFrontPage, Page, PageChapterAndCourseInformation, PageNavigationInformation,
6};
7use utoipa::OpenApi;
8
9#[derive(OpenApi)]
10#[openapi(paths(
11    get_by_exam_id,
12    get_chapter_front_page,
13    get_page_navigation,
14    get_chapter_and_course_information,
15    get_url_path,
16    is_chapter_front_page
17))]
18pub(crate) struct CourseMaterialPagesApiDoc;
19
20/**
21GET /api/v0/course-material/pages/exam/{page_id}
22*/
23#[utoipa::path(
24    get,
25    path = "/exam/{page_id}",
26    operation_id = "getCourseMaterialPageByExamId",
27    tag = "course-material-pages",
28    params(
29        ("page_id" = Uuid, Path, description = "Exam id")
30    ),
31    responses(
32        (status = 200, description = "Exam page", body = Page)
33    )
34)]
35#[instrument(skip(pool))]
36async fn get_by_exam_id(
37    exam_id: web::Path<Uuid>,
38    pool: web::Data<PgPool>,
39    auth: Option<AuthUser>,
40) -> ControllerResult<web::Json<Page>> {
41    let mut conn = pool.acquire().await?;
42    let user_id = auth.map(|u| u.id);
43    let page = models::pages::get_by_exam_id(&mut conn, *exam_id).await?;
44    let page = models::pages::filter_course_material_page(&mut conn, user_id, page).await?;
45    let token = skip_authorize();
46    token.authorized_ok(web::Json(page))
47}
48
49/**
50GET /api/v0/course-material/page/{page_id}
51*/
52#[utoipa::path(
53    get,
54    path = "/{current_page_id}/chapter-front-page",
55    operation_id = "getCourseMaterialChapterFrontPage",
56    tag = "course-material-pages",
57    params(
58        ("current_page_id" = Uuid, Path, description = "Current page id")
59    ),
60    responses(
61        (status = 200, description = "Chapter front page", body = Option<Page>)
62    )
63)]
64#[instrument(skip(pool))]
65async fn get_chapter_front_page(
66    page_id: web::Path<Uuid>,
67    pool: web::Data<PgPool>,
68    auth: Option<AuthUser>,
69) -> ControllerResult<web::Json<Option<Page>>> {
70    let mut conn = pool.acquire().await?;
71    let user_id = auth.map(|u| u.id);
72    let chapter_front_page =
73        models::pages::get_chapter_front_page_by_page_id(&mut conn, *page_id).await?;
74    let chapter_front_page = match chapter_front_page {
75        Some(page) => {
76            Some(models::pages::filter_course_material_page(&mut conn, user_id, page).await?)
77        }
78        None => None,
79    };
80    let token = skip_authorize();
81    token.authorized_ok(web::Json(chapter_front_page))
82}
83
84/**
85GET /api/v0/course-material/pages/:page_id/page-navigation - tells what's the next page, previous page, and the chapter front page given a page id.
86*/
87#[utoipa::path(
88    get,
89    path = "/{current_page_id}/page-navigation",
90    operation_id = "getCourseMaterialPageNavigation",
91    tag = "course-material-pages",
92    params(
93        ("current_page_id" = Uuid, Path, description = "Current page id")
94    ),
95    responses(
96        (status = 200, description = "Page navigation information", body = PageNavigationInformation)
97    )
98)]
99#[instrument(skip(pool))]
100async fn get_page_navigation(
101    page_id: web::Path<Uuid>,
102    pool: web::Data<PgPool>,
103) -> ControllerResult<web::Json<PageNavigationInformation>> {
104    let mut conn = pool.acquire().await?;
105    let token = skip_authorize();
106    let res = models::pages::get_page_navigation_data(&mut conn, *page_id).await?;
107
108    token.authorized_ok(web::Json(res))
109}
110
111/**
112 GET /api/v0/course-material/pages/:page_id/chapter-and-course-information - gives the page's chapter and course information -- useful for the breadcrumbs
113*/
114#[utoipa::path(
115    get,
116    path = "/{current_page_id}/chapter-and-course-information",
117    operation_id = "getCourseMaterialPageChapterAndCourseInformation",
118    tag = "course-material-pages",
119    params(
120        ("current_page_id" = Uuid, Path, description = "Current page id")
121    ),
122    responses(
123        (status = 200, description = "Page chapter and course information", body = PageChapterAndCourseInformation)
124    )
125)]
126#[instrument(skip(pool))]
127async fn get_chapter_and_course_information(
128    page_id: web::Path<Uuid>,
129    pool: web::Data<PgPool>,
130) -> ControllerResult<web::Json<PageChapterAndCourseInformation>> {
131    let mut conn = pool.acquire().await?;
132    let res = models::pages::get_page_chapter_and_course_information(&mut conn, *page_id).await?;
133
134    let token = skip_authorize();
135    token.authorized_ok(web::Json(res))
136}
137
138/**
139 GET /api/v0/course-material/pages/:page_id/url-path - returns the page's URL path.
140 # Example
141 ```json
142 "chapter-1/page-2"
143 ```
144*/
145#[utoipa::path(
146    get,
147    path = "/{current_page_id}/url-path",
148    operation_id = "getCourseMaterialPageUrlPath",
149    tag = "course-material-pages",
150    params(
151        ("current_page_id" = Uuid, Path, description = "Current page id")
152    ),
153    responses(
154        (status = 200, description = "Page URL path", body = String)
155    )
156)]
157#[instrument(skip(pool))]
158async fn get_url_path(
159    page_id: web::Path<Uuid>,
160    pool: web::Data<PgPool>,
161) -> ControllerResult<String> {
162    let mut conn = pool.acquire().await?;
163    let page = models::pages::get_page(&mut conn, *page_id).await?;
164
165    let token = skip_authorize();
166    token.authorized_ok(page.url_path)
167}
168
169#[utoipa::path(
170    get,
171    path = "/{current_page_id}/is-chapter-front-page",
172    operation_id = "getCourseMaterialIsPageChapterFrontPage",
173    tag = "course-material-pages",
174    params(
175        ("current_page_id" = Uuid, Path, description = "Current page id")
176    ),
177    responses(
178        (status = 200, description = "Whether page is chapter front page", body = IsChapterFrontPage)
179    )
180)]
181#[instrument(skip(pool))]
182async fn is_chapter_front_page(
183    page_id: web::Path<Uuid>,
184    pool: web::Data<PgPool>,
185) -> ControllerResult<web::Json<IsChapterFrontPage>> {
186    let mut conn = pool.acquire().await?;
187    let is_chapter_front_page = models::pages::is_chapter_front_page(&mut conn, *page_id).await?;
188    let token = skip_authorize();
189    token.authorized_ok(web::Json(is_chapter_front_page))
190}
191
192pub fn _add_routes(cfg: &mut ServiceConfig) {
193    cfg.route("/exam/{page_id}", web::get().to(get_by_exam_id))
194        .route(
195            "/{current_page_id}/chapter-front-page",
196            web::get().to(get_chapter_front_page),
197        )
198        .route("/{current_page_id}/url-path", web::get().to(get_url_path))
199        .route(
200            "/{current_page_id}/chapter-and-course-information",
201            web::get().to(get_chapter_and_course_information),
202        )
203        .route(
204            "/{current_page_id}/is-chapter-front-page",
205            web::get().to(is_chapter_front_page),
206        )
207        .route(
208            "/{current_page_id}/page-navigation",
209            web::get().to(get_page_navigation),
210        );
211}