Skip to main content

auth_service/
error.rs

1use axum::{
2    http::StatusCode,
3    response::{IntoResponse, Response},
4};
5use edda_auth::AuthError;
6
7/// What a request can fail with, and the status it answers.
8#[derive(Debug, thiserror::Error)]
9pub enum ApiError {
10    #[error("not found")]
11    NotFound,
12    #[error("{0}")]
13    BadRequest(String),
14    /// The caller couldn't prove who they are.
15    #[error("{0}")]
16    Unauthorized(String),
17    /// The caller is known but may not do this.
18    #[error("{0}")]
19    Forbidden(String),
20    #[error("{0}")]
21    Conflict(String),
22    #[error("{0}")]
23    Unprocessable(String),
24    #[error("database error: {0}")]
25    Database(#[from] sqlx::Error),
26    #[error("internal error: {0}")]
27    Internal(String),
28}
29
30impl From<AuthError> for ApiError {
31    fn from(e: AuthError) -> Self {
32        match e {
33            AuthError::Encoding(e) => ApiError::Internal(e),
34            e => ApiError::Unauthorized(e.to_string()),
35        }
36    }
37}
38
39impl IntoResponse for ApiError {
40    fn into_response(self) -> Response {
41        let status = match &self {
42            ApiError::NotFound => StatusCode::NOT_FOUND,
43            ApiError::BadRequest(_) => StatusCode::BAD_REQUEST,
44            ApiError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
45            ApiError::Forbidden(_) => StatusCode::FORBIDDEN,
46            ApiError::Conflict(_) => StatusCode::CONFLICT,
47            ApiError::Unprocessable(_) => StatusCode::UNPROCESSABLE_ENTITY,
48            ApiError::Database(_) | ApiError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
49        };
50        edda_server::error_response(status, &self)
51    }
52}