Skip to main content

headless_lms_server/controllers/main_frontend/
email_templates.rs

1//! Controllers for requests starting with `/api/v0/main-frontend/email-templates/`.
2
3use models::email_templates::{EmailTemplate, EmailTemplateNew};
4use utoipa::OpenApi;
5
6use crate::controllers::helpers::email_content::parse_email_content;
7use crate::domain::error::missing_controller_error;
8use crate::prelude::*;
9
10#[derive(OpenApi)]
11#[openapi(paths(get_all_email_templates, create_email_template, delete_email_template))]
12pub(crate) struct MainFrontendEmailTemplatesApiDoc;
13
14/**
15GET `/api/v0/main-frontend/email-templates`
16*/
17#[instrument(skip(pool))]
18#[utoipa::path(
19    get,
20    path = "",
21    operation_id = "getEmailTemplates",
22    tag = "email_templates",
23    responses(
24        (status = 200, description = "Email templates", body = Vec<EmailTemplate>)
25    )
26)]
27async fn get_all_email_templates(
28    pool: web::Data<PgPool>,
29    user: AuthUser,
30) -> ControllerResult<web::Json<Vec<EmailTemplate>>> {
31    let mut conn = pool.acquire().await?;
32    let token = authorize(
33        &mut conn,
34        Act::Administrate,
35        Some(user.id),
36        Res::GlobalPermissions,
37    )
38    .await?;
39    let email_templates = models::email_templates::get_all_email_templates(&mut conn).await?;
40    token.authorized_ok(web::Json(email_templates))
41}
42
43/**
44POST `/api/v0/main-frontend/email-templates`
45
46Creates a global template; rejects a second live one for the same type and language.
47*/
48#[instrument(skip(pool))]
49#[utoipa::path(
50    post,
51    path = "",
52    operation_id = "createEmailTemplate",
53    tag = "email_templates",
54    request_body = EmailTemplateNew,
55    responses(
56        (status = 200, description = "Created email template", body = EmailTemplate)
57    )
58)]
59async fn create_email_template(
60    payload: web::Json<EmailTemplateNew>,
61    pool: web::Data<PgPool>,
62    user: AuthUser,
63) -> ControllerResult<web::Json<EmailTemplate>> {
64    let mut conn = pool.acquire().await?;
65    let token = authorize(
66        &mut conn,
67        Act::Administrate,
68        Some(user.id),
69        Res::GlobalPermissions,
70    )
71    .await?;
72    let mut new_template = payload.into_inner();
73    let content = new_template
74        .content
75        .get_or_insert_with(|| serde_json::json!([]));
76    parse_email_content(content)?;
77    let created =
78        models::email_templates::insert_global_email_template_if_absent(&mut conn, new_template)
79            .await?
80            .ok_or_else(missing_controller_error(
81                ControllerErrorType::BadRequest,
82                "A template of this type and language already exists.",
83            ))?;
84    token.authorized_ok(web::Json(created))
85}
86
87/**
88DELETE `/api/v0/main-frontend/email-templates/:id`
89*/
90#[instrument(skip(pool))]
91#[utoipa::path(
92    delete,
93    path = "/{email_template_id}",
94    operation_id = "deleteEmailTemplate",
95    tag = "email_templates",
96    params(
97        ("email_template_id" = Uuid, Path, description = "Email template id")
98    ),
99    responses(
100        (status = 200, description = "Deleted email template", body = EmailTemplate)
101    )
102)]
103async fn delete_email_template(
104    email_template_id: web::Path<Uuid>,
105    pool: web::Data<PgPool>,
106    user: AuthUser,
107) -> ControllerResult<web::Json<EmailTemplate>> {
108    let mut conn = pool.acquire().await?;
109    let email_template =
110        models::email_templates::get_email_template(&mut conn, *email_template_id).await?;
111    let token = if let Some(course_id) = email_template.course_id {
112        authorize(&mut conn, Act::Teach, Some(user.id), Res::Course(course_id)).await?
113    } else {
114        authorize(
115            &mut conn,
116            Act::Administrate,
117            Some(user.id),
118            Res::GlobalPermissions,
119        )
120        .await?
121    };
122    let deleted =
123        models::email_templates::delete_email_template(&mut conn, *email_template_id).await?;
124
125    token.authorized_ok(web::Json(deleted))
126}
127
128/**
129Add a route for each controller in this module.
130
131The name starts with an underline in order to appear before other functions in the module documentation.
132
133We add the routes by calling the route method instead of using the route annotations because this method preserves the function signatures for documentation.
134*/
135pub fn _add_routes(cfg: &mut ServiceConfig) {
136    cfg.route("", web::get().to(get_all_email_templates))
137        .route("", web::post().to(create_email_template))
138        .route(
139            "/{email_template_id}",
140            web::delete().to(delete_email_template),
141        );
142}