1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Controllers for requests starting with `/api/v0/course_material/chapters`.

use models::pages::{Page, PageVisibility, PageWithExercises};

use crate::prelude::*;

/**
GET `/api/v0/course-material/chapters/:chapter_id/pages` - Returns a list of pages in chapter.
*/
#[instrument(skip(pool))]
async fn get_public_chapter_pages(
    chapter_id: web::Path<Uuid>,
    pool: web::Data<PgPool>,
    auth: Option<AuthUser>,
) -> ControllerResult<web::Json<Vec<Page>>> {
    let mut conn = pool.acquire().await?;
    let token = authorize(
        &mut conn,
        Act::View,
        auth.map(|u| u.id),
        Res::Chapter(*chapter_id),
    )
    .await?;
    let chapter_pages: Vec<Page> = models::pages::get_course_pages_by_chapter_id_and_visibility(
        &mut conn,
        *chapter_id,
        PageVisibility::Public,
    )
    .await?;
    token.authorized_ok(web::Json(chapter_pages))
}

/**
GET `/api/v0/course-material/chapters/:chapter_id/exercises` - Returns a list of pages and its exercises in chapter.
*/
#[instrument(skip(pool))]
async fn get_chapters_exercises(
    chapter_id: web::Path<Uuid>,
    pool: web::Data<PgPool>,
    auth: Option<AuthUser>,
) -> ControllerResult<web::Json<Vec<PageWithExercises>>> {
    let mut conn = pool.acquire().await?;
    let token = authorize(
        &mut conn,
        Act::View,
        auth.map(|u| u.id),
        Res::Chapter(*chapter_id),
    )
    .await?;

    let chapter_pages_with_exercises =
        models::pages::get_chapters_pages_with_exercises(&mut conn, *chapter_id).await?;
    token.authorized_ok(web::Json(chapter_pages_with_exercises))
}

/**
GET `/api/v0/course-material/chapters/:chapter_id/pages-exclude-mainfrontpage` - Returns a list of pages in chapter mainfrontpage excluded.
*/
#[instrument(skip(pool))]
async fn get_chapters_pages_without_main_frontpage(
    chapter_id: web::Path<Uuid>,
    pool: web::Data<PgPool>,
    auth: Option<AuthUser>,
) -> ControllerResult<web::Json<Vec<Page>>> {
    let mut conn = pool.acquire().await?;
    let token = authorize(
        &mut conn,
        Act::View,
        auth.map(|u| u.id),
        Res::Chapter(*chapter_id),
    )
    .await?;
    let chapter_pages =
        models::pages::get_chapters_visible_pages_exclude_main_frontpage(&mut conn, *chapter_id)
            .await?
            .into_iter()
            .collect();
    token.authorized_ok(web::Json(chapter_pages))
}

/**
Add a route for each controller in this module.

The name starts with an underline in order to appear before other functions in the module documentation.

We add the routes by calling the route method instead of using the route annotations because this method preserves the function signatures for documentation.
*/
pub fn _add_routes(cfg: &mut ServiceConfig) {
    cfg.route(
        "/{chapter_id}/pages",
        web::get().to(get_public_chapter_pages),
    )
    .route(
        "/{chapter_id}/exercises",
        web::get().to(get_chapters_exercises),
    )
    .route(
        "/{chapter_id}/pages-exclude-mainfrontpage",
        web::get().to(get_chapters_pages_without_main_frontpage),
    );
}