1
use axum::{
2
    http::StatusCode,
3
    response::{IntoResponse, Response},
4
    Json,
5
};
6
use bcrypt::BcryptError;
7
use serde_json::json;
8
use tokio::task::JoinError;
9

            
10
#[derive(thiserror::Error, Debug)]
11
#[error("...")]
12
pub enum Error {
13
    #[error("Error parsing ObjectID {0}")]
14
    ParseObjectID(String),
15

            
16
    #[error("{0}")]
17
    Authenticate(#[from] AuthenticateError),
18

            
19
    #[error("{0}")]
20
    BadRequest(#[from] BadRequest),
21

            
22
    #[error("{0}")]
23
    NotFound(#[from] NotFound),
24

            
25
    #[error("{0}")]
26
    RunSyncTask(#[from] JoinError),
27

            
28
    #[error("{0}")]
29
    HashPassword(#[from] BcryptError),
30

            
31
    #[error("{0}")]
32
    System(#[from] mailpot::Error),
33
}
34

            
35
impl Error {
36
    fn get_codes(&self) -> (StatusCode, u16) {
37
        match *self {
38
            // 4XX Errors
39
            Error::ParseObjectID(_) => (StatusCode::BAD_REQUEST, 40001),
40
            Error::BadRequest(_) => (StatusCode::BAD_REQUEST, 40002),
41
            Error::NotFound(_) => (StatusCode::NOT_FOUND, 40003),
42
            Error::Authenticate(AuthenticateError::WrongCredentials) => {
43
                (StatusCode::UNAUTHORIZED, 40004)
44
            }
45
            Error::Authenticate(AuthenticateError::InvalidToken) => {
46
                (StatusCode::UNAUTHORIZED, 40005)
47
            }
48
            Error::Authenticate(AuthenticateError::Locked) => (StatusCode::LOCKED, 40006),
49

            
50
            // 5XX Errors
51
            Error::Authenticate(AuthenticateError::TokenCreation) => {
52
                (StatusCode::INTERNAL_SERVER_ERROR, 5001)
53
            }
54
            Error::RunSyncTask(_) => (StatusCode::INTERNAL_SERVER_ERROR, 5005),
55
            Error::HashPassword(_) => (StatusCode::INTERNAL_SERVER_ERROR, 5006),
56
            Error::System(_) => (StatusCode::INTERNAL_SERVER_ERROR, 5007),
57
        }
58
    }
59

            
60
    pub fn bad_request() -> Self {
61
        Error::BadRequest(BadRequest {})
62
    }
63

            
64
    pub fn not_found() -> Self {
65
        Error::NotFound(NotFound {})
66
    }
67
}
68

            
69
impl IntoResponse for Error {
70
    fn into_response(self) -> Response {
71
        let (status_code, code) = self.get_codes();
72
        let message = self.to_string();
73
        let body = Json(json!({ "code": code, "message": message }));
74

            
75
        (status_code, body).into_response()
76
    }
77
}
78

            
79
#[derive(thiserror::Error, Debug)]
80
#[error("...")]
81
pub enum AuthenticateError {
82
    #[error("Wrong authentication credentials")]
83
    WrongCredentials,
84
    #[error("Failed to create authentication token")]
85
    TokenCreation,
86
    #[error("Invalid authentication credentials")]
87
    InvalidToken,
88
    #[error("User is locked")]
89
    Locked,
90
}
91

            
92
#[derive(thiserror::Error, Debug)]
93
#[error("Bad Request")]
94
pub struct BadRequest {}
95

            
96
#[derive(thiserror::Error, Debug)]
97
#[error("Not found")]
98
pub struct NotFound {}