Moved to better error handling system

This commit is contained in:
xeovalyte 2025-02-07 09:03:51 +01:00
parent 35527cbeb7
commit f7b7ebbb1c
Signed by: xeovalyte
SSH Key Fingerprint: SHA256:GWI1hq+MNKR2UOcvk7n9tekASXT8vyazK7vDF9Xyciw
4 changed files with 64 additions and 35 deletions

View File

@ -51,7 +51,7 @@ where
},
};
Err(AuthError::Unexpected.into())
Err(AuthError::Unauthorized.into())
}
}

View File

@ -6,6 +6,7 @@ pub enum AuthError {
InvalidToken,
Unexpected,
InvalidPassword,
Unauthorized,
}
impl Display for AuthError {
@ -15,6 +16,7 @@ impl Display for AuthError {
Self::InvalidToken => write!(f, "{}", "Invalid token"),
Self::Unexpected => write!(f, "{}", "Unexpected error"),
Self::InvalidPassword => write!(f, "{}", "Password is incorrect"),
Self::Unauthorized => write!(f, "{}", "Authentication is required"),
}
}
}

View File

@ -1,6 +1,9 @@
use std::collections::HashMap;
use axum::{extract::State, Json};
use axum::{
extract::{FromRef, State},
Json,
};
use itertools::Itertools;
use sqlx::PgPool;
@ -53,10 +56,13 @@ pub async fn migrate_confirm<'a>(
tracing::info!("Migration is confirmed");
// TODO: Implement better error naming
let count = match body.trim().parse::<u32>() {
Ok(c) => c,
Err(_) => return Err(crate::Error::NotFound),
Err(_) => {
return Err(crate::Error::BadRequest {
expected: String::from("u32"),
})
}
};
let mut store = state.migration_store.lock().await;

View File

@ -7,50 +7,71 @@ use axum::{
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("CSV error: {0}")]
#[error(transparent)]
Csv(#[from] csv::Error),
#[error("Auth error: {0}")]
#[error(transparent)]
Auth(#[from] crate::auth::AuthError),
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error(transparent)]
Sqlx(#[from] sqlx::Error),
#[error("Resource not found")]
#[error("resource not found")]
NotFound,
#[error("Invalid request, expected {expected:?}")]
BadRequest { expected: String },
}
#[derive(serde::Serialize)]
struct ErrorResponse {
code: &'static str,
description: String,
}
impl ErrorResponse {
fn new(code: &'static str, description: String) -> Self {
Self { code, description }
}
}
impl IntoResponse for Error {
fn into_response(self) -> Response {
tracing::error!("Error... {:?}", self);
let (status_code, code) = match self {
Self::Sqlx(ref err_kind) => match err_kind {
sqlx::Error::RowNotFound => (StatusCode::NOT_FOUND, "DATABSE_ROW_NOT_FOUND"),
_ => (StatusCode::INTERNAL_SERVER_ERROR, "DATABASE_ERROR"),
},
let (status, error_message) = match self {
Error::Auth(AuthError::NoPermssions) => {
(StatusCode::UNAUTHORIZED, String::from("No permissions"))
}
Error::Auth(AuthError::InvalidToken) => {
(StatusCode::BAD_REQUEST, String::from("Invalid token"))
}
Error::Auth(AuthError::Unexpected) => (
StatusCode::INTERNAL_SERVER_ERROR,
String::from("Unexpected error occured"),
),
Error::Auth(AuthError::InvalidPassword) => (
StatusCode::INTERNAL_SERVER_ERROR,
String::from("Invalid password"),
),
Error::Csv(err) => (StatusCode::BAD_REQUEST, err.to_string()),
Error::NotFound => (
StatusCode::BAD_REQUEST,
String::from("Could not find resource"),
),
Error::Database(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()),
Self::Csv(ref err_kind) => match err_kind.kind() {
csv::ErrorKind::UnequalLengths { .. } => {
(StatusCode::BAD_REQUEST, "CSV_INPUT_INVALID")
}
_ => (StatusCode::INTERNAL_SERVER_ERROR, "CSV_ERROR"),
},
Self::Auth(ref err_kind) => match err_kind {
crate::auth::AuthError::NoPermssions => {
(StatusCode::FORBIDDEN, "AUTH_NO_PERMISSIONS")
}
crate::auth::AuthError::Unauthorized => {
(StatusCode::UNAUTHORIZED, "AUTH_UNAUTHORIZED")
}
crate::auth::AuthError::InvalidToken => {
(StatusCode::BAD_REQUEST, "AUTH_INVALID_TOKEN")
}
crate::auth::AuthError::InvalidPassword => {
(StatusCode::BAD_REQUEST, "AUTH_INVALID_PASSWORD")
}
_ => (StatusCode::INTERNAL_SERVER_ERROR, "AUTH_ERROR"),
},
Self::BadRequest { .. } => (StatusCode::BAD_REQUEST, "INVALID_BODY"),
Self::NotFound => (StatusCode::NOT_FOUND, "NOT_FOUND"),
};
let body = Json(serde_json::json!({
"error": error_message
}));
let body = ErrorResponse::new(code, self.to_string());
(status, body).into_response()
(status_code, Json(body)).into_response()
}
}