Skip to main content

headless_lms_server/controllers/
errors.rs

1use models::errors::{self, NewErrorReport};
2use utoipa::OpenApi;
3
4use crate::{domain::authorization::skip_authorize, prelude::*};
5
6#[derive(OpenApi)]
7#[openapi(paths(post_error))]
8pub(crate) struct ErrorsRoutesApiDoc;
9
10/**
11POST `/api/v0/errors` - Reports an error occurrence.
12
13Accessible to both authenticated and anonymous users. If the user is logged in, their id is stored with the error occurrence.
14*/
15#[utoipa::path(
16    post,
17    path = "",
18    operation_id = "postError",
19    tag = "errors",
20    request_body = NewErrorReport,
21    responses(
22        (status = 204, description = "Error recorded successfully")
23    )
24)]
25#[instrument(skip(pool, user, payload))]
26pub async fn post_error(
27    pool: web::Data<PgPool>,
28    user: Option<AuthUser>,
29    payload: web::Json<NewErrorReport>,
30) -> ControllerResult<HttpResponse> {
31    let mut conn = pool.acquire().await?;
32    let user_id = user.map(|u| u.id);
33    errors::insert(&mut conn, user_id, &payload).await?;
34    if let Err(err) = errors::maybe_delete_expired(&mut conn).await {
35        warn!("best-effort error cleanup failed: {err}");
36    }
37    let token = skip_authorize();
38    token.authorized_ok(HttpResponse::NoContent().finish())
39}
40
41pub fn _add_routes(cfg: &mut ServiceConfig) {
42    cfg.route("", web::post().to(post_error));
43}