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
//! Contains HTTP Handlers that directly receive and respond to requests to the server.
mod auth;
mod form;
mod health_check;
mod qr_code;

use actix_web::{
    http::{header, HeaderValue, StatusCode},
    HttpResponse, ResponseError,
};
pub use auth::*;
pub use form::*;
pub use health_check::*;
pub use qr_code::*;

use crate::auth::AuthenticationError;

pub type ApplicationResponse = Result<HttpResponse, ApplicationError>;

/// Error derived while handling an HTTP request
#[derive(thiserror::Error)]
pub enum ApplicationError {
    #[error("Authentication failed.")]
    AuthError(#[source] AuthenticationError),
    #[error(transparent)]
    UnexpectedError(#[from] anyhow::Error),
    #[error("Not Found")]
    NotFoundError(String),
}

impl ResponseError for ApplicationError {
    fn error_response(&self) -> HttpResponse {
        match self {
            Self::UnexpectedError(_e) => HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR),
            Self::AuthError(_e) => {
                let mut response = HttpResponse::new(StatusCode::UNAUTHORIZED);
                let header_value = HeaderValue::from_str(r#"Basic realm="publish""#).unwrap();
                response
                    .headers_mut()
                    .insert(header::WWW_AUTHENTICATE, header_value);
                response
            }
            Self::NotFoundError(_message) => HttpResponse::new(StatusCode::NOT_FOUND),
        }
    }

    fn status_code(&self) -> StatusCode {
        match self {
            Self::UnexpectedError(_e) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::AuthError(_e) => StatusCode::UNAUTHORIZED,
            Self::NotFoundError(_message) => StatusCode::NOT_FOUND,
        }
    }
}

pub fn json_response(data: impl serde::Serialize) -> ApplicationResponse {
    Ok(HttpResponse::Ok().json(data))
}

impl std::fmt::Debug for ApplicationError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        crate::error::error_chain_fmt(self, f)
    }
}

impl From<sqlx::Error> for ApplicationError {
    fn from(e: sqlx::Error) -> Self {
        Self::UnexpectedError(anyhow::anyhow!(e))
    }
}

impl From<serde_json::Error> for ApplicationError {
    fn from(e: serde_json::Error) -> Self {
        Self::UnexpectedError(anyhow::anyhow!(e))
    }
}