use axum::{ extract::rejection::JsonRejection, response::{IntoResponse, Response}, }; use axum_extra::typed_header::TypedHeaderRejection; use crate::response::{ErrorResponse, FailResponse, SuccessResponse}; pub type ApiResult = Result, ApiError>; pub enum ApiError { // 400 BadJsonBody(String), BadAuthTokenHeader(String), UserAlreadyExists { username: String }, InvalidPassword, NotAuthorized, // 500 Database(String), PasswordHash(String), InternalJwt(String), } impl From for ApiError { fn from(value: JsonRejection) -> Self { Self::BadJsonBody(value.body_text()) } } impl From for ApiError { fn from(value: TypedHeaderRejection) -> Self { Self::BadAuthTokenHeader(value.to_string()) } } impl From for ApiError { fn from(value: sea_orm::DbErr) -> Self { Self::Database(value.to_string()) } } impl From for ApiError { fn from(value: argon2::password_hash::Error) -> Self { Self::PasswordHash(value.to_string()) } } impl ToString for ApiError { fn to_string(&self) -> String { match self { // 400 ApiError::BadJsonBody(..) => "BadJsonBody", ApiError::BadAuthTokenHeader(..) => "BadAuthTokenHeader", ApiError::UserAlreadyExists { .. } => "UserAlreadyExists", ApiError::InvalidPassword => "InvalidPassword", ApiError::NotAuthorized => "NotAuthorized", // 500 ApiError::Database(..) => "Database", ApiError::PasswordHash(..) => "PasswordHash", ApiError::InternalJwt(..) => "InternalJwt", } .to_string() } } impl IntoResponse for ApiError { fn into_response(self) -> Response { let kind = self.to_string(); match self { // 400 ApiError::BadJsonBody(msg) => FailResponse(kind, msg).into_response(), ApiError::BadAuthTokenHeader(msg) => FailResponse(kind, msg).into_response(), ApiError::UserAlreadyExists { username } => FailResponse( kind, format!("user with username `{}` already exists", username), ) .into_response(), ApiError::InvalidPassword => { FailResponse(kind, "password is invalid".to_string()).into_response() } ApiError::NotAuthorized => { FailResponse(kind, "user is not authorized".to_string()).into_response() } // 500 ApiError::Database(msg) => ErrorResponse(kind, msg).into_response(), ApiError::PasswordHash(msg) => ErrorResponse(kind, msg).into_response(), ApiError::InternalJwt(msg) => ErrorResponse(kind, msg).into_response(), } } }