Skip to main content

headless_lms_server/controllers/main_frontend/courses/
chatbots.rs

1//! Controllers for requests starting with `/api/v0/main-frontend/{course_id}/chatbots`.
2use crate::prelude::*;
3
4use models::chatbot_configurations::ChatbotConfiguration;
5use utoipa::OpenApi;
6
7#[derive(OpenApi)]
8#[openapi(paths(get_chatbots, set_default_chatbot, set_non_default_chatbot))]
9pub(crate) struct MainFrontendCourseChatbotsApiDoc;
10
11/// GET `/api/v0/main-frontend/courses/{course_id}/chatbots`
12#[utoipa::path(
13    get,
14    path = "",
15    operation_id = "getCourseChatbots",
16    tag = "courses",
17    params(
18        ("course_id" = String, Path, description = "Course id")
19    ),
20    responses(
21        (status = 200, description = "Course chatbots", body = Vec<ChatbotConfiguration>)
22    )
23)]
24#[instrument(skip(pool))]
25async fn get_chatbots(
26    course_id: web::Path<Uuid>,
27    pool: web::Data<PgPool>,
28    user: AuthUser,
29) -> ControllerResult<web::Json<Vec<ChatbotConfiguration>>> {
30    let mut conn = pool.acquire().await?;
31    let token = authorize(&mut conn, Act::Edit, Some(user.id), Res::Course(*course_id)).await?;
32
33    let configurations =
34        models::chatbot_configurations::get_for_course(&mut conn, *course_id).await?;
35    token.authorized_ok(web::Json(configurations))
36}
37
38/// POST `/api/v0/main-frontend/courses/{course_id}/chatbots/{chatbot_configuration_id}/set-as-default`
39#[utoipa::path(
40    post,
41    path = "/{chatbot_configuration_id}/set-as-default",
42    operation_id = "setCourseChatbotAsDefault",
43    tag = "courses",
44    params(
45        ("course_id" = String, Path, description = "Course id"),
46        ("chatbot_configuration_id" = String, Path, description = "Chatbot configuration id")
47    ),
48    responses(
49        (status = 200, description = "Updated course chatbot", body = ChatbotConfiguration)
50    )
51)]
52#[instrument(skip(pool))]
53async fn set_default_chatbot(
54    ids: web::Path<(Uuid, Uuid)>,
55    pool: web::Data<PgPool>,
56    user: AuthUser,
57) -> ControllerResult<web::Json<ChatbotConfiguration>> {
58    let mut conn = pool.acquire().await?;
59    let (course_id, chatbot_configuration_id) = *ids;
60
61    let token = authorize(&mut conn, Act::Edit, Some(user.id), Res::Course(course_id)).await?;
62    let mut tx = conn.begin().await?;
63
64    models::chatbot_configurations::remove_default_chatbot_from_course(&mut tx, course_id).await?;
65
66    let chatbot =
67        models::chatbot_configurations::get_by_id(&mut tx, chatbot_configuration_id).await?;
68
69    if course_id
70        != chatbot.course_id.ok_or_else(|| {
71            ControllerError::new(
72                ControllerErrorType::BadRequest,
73                "Chatbot course id is missing.".to_string(),
74                None,
75            )
76        })?
77    {
78        return Err(ControllerError::new(
79            ControllerErrorType::BadRequest,
80            "Chatbot course id doesn't match the course id provided.".to_string(),
81            None,
82        ));
83    }
84
85    let configuration = models::chatbot_configurations::set_default_chatbot_for_course(
86        &mut tx,
87        chatbot_configuration_id,
88    )
89    .await?;
90    tx.commit().await?;
91
92    token.authorized_ok(web::Json(configuration))
93}
94
95/// POST `/api/v0/main-frontend/courses/{course_id}/chatbots/{chatbot_configuration_id}/set-as-non-default`
96#[utoipa::path(
97    post,
98    path = "/{chatbot_configuration_id}/set-as-non-default",
99    operation_id = "setCourseChatbotAsNonDefault",
100    tag = "courses",
101    params(
102        ("course_id" = String, Path, description = "Course id"),
103        ("chatbot_configuration_id" = String, Path, description = "Chatbot configuration id")
104    ),
105    responses(
106        (status = 200, description = "Updated course chatbot", body = ChatbotConfiguration)
107    )
108)]
109#[instrument(skip(pool))]
110async fn set_non_default_chatbot(
111    ids: web::Path<(Uuid, Uuid)>,
112    pool: web::Data<PgPool>,
113    user: AuthUser,
114) -> ControllerResult<web::Json<ChatbotConfiguration>> {
115    let mut conn = pool.acquire().await?;
116    let (course_id, chatbot_configuration_id) = *ids;
117
118    let token = authorize(&mut conn, Act::Edit, Some(user.id), Res::Course(course_id)).await?;
119    let mut tx = conn.begin().await?;
120
121    models::chatbot_configurations::remove_default_chatbot_from_course(&mut tx, course_id).await?;
122
123    let configuration =
124        models::chatbot_configurations::get_by_id(&mut tx, chatbot_configuration_id).await?;
125
126    if course_id
127        != configuration.course_id.ok_or_else(|| {
128            ControllerError::new(
129                ControllerErrorType::BadRequest,
130                "Chatbot course id is missing.".to_string(),
131                None,
132            )
133        })?
134    {
135        return Err(ControllerError::new(
136            ControllerErrorType::BadRequest,
137            "Chatbot course id doesn't match the course id provided.".to_string(),
138            None,
139        ));
140    }
141    tx.commit().await?;
142
143    token.authorized_ok(web::Json(configuration))
144}
145
146pub fn _add_routes(cfg: &mut web::ServiceConfig) {
147    cfg.route("", web::get().to(get_chatbots))
148        .route(
149            "/{chatbot_configuration_id}/set-as-default",
150            web::post().to(set_default_chatbot),
151        )
152        .route(
153            "/{chatbot_configuration_id}/set-as-non-default",
154            web::post().to(set_non_default_chatbot),
155        );
156}