diff --git a/backend/server/Cargo.toml b/backend/server/Cargo.toml index fd764748..84445fdc 100644 --- a/backend/server/Cargo.toml +++ b/backend/server/Cargo.toml @@ -14,6 +14,7 @@ sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "time" # Important secondary crates anyhow = "1.0" +thiserror = "1.0" serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.11", features = ["json"] } serde_json = "1.0" diff --git a/backend/server/src/models/auth.rs b/backend/server/src/models/auth.rs index 149c3a25..c292f092 100644 --- a/backend/server/src/models/auth.rs +++ b/backend/server/src/models/auth.rs @@ -91,6 +91,7 @@ where let claims = decode_auth_token(token, decoding_key, jwt_validator).ok_or(ChaosError::NotLoggedIn)?; + let pool = &app_state.db; let possible_user = is_super_user(claims.sub, pool).await; @@ -102,6 +103,6 @@ where } } - Err(ChaosError::NotLoggedIn) + Err(ChaosError::Unauthorized) } } diff --git a/backend/server/src/models/error.rs b/backend/server/src/models/error.rs index ca160d97..86c3004c 100644 --- a/backend/server/src/models/error.rs +++ b/backend/server/src/models/error.rs @@ -3,31 +3,42 @@ use axum::response::{IntoResponse, Redirect, Response}; /// Custom error enum for Chaos. /// -/// Handles all anyhow errors (when `?` is used) alongside +/// Handles all errors thrown by libraries (when `?` is used) alongside /// specific errors for business logic. +#[derive(thiserror::Error, Debug)] pub enum ChaosError { + #[error("Not logged in")] NotLoggedIn, + + #[error("Not authorized")] Unauthorized, + + #[error("Forbidden operation")] ForbiddenOperation, - ServerError(anyhow::Error), + + #[error("SQLx error")] + DatabaseError(#[from] sqlx::Error), + + #[error("Reqwest error")] + ReqwestError(#[from] reqwest::Error), + + #[error("OAuth2 error")] + OAuthError(#[from] oauth2::RequestTokenError, oauth2::StandardErrorResponse>) } +/// Implementation for converting errors into responses. Manages error code and message returned. impl IntoResponse for ChaosError { fn into_response(self) -> Response { match self { ChaosError::NotLoggedIn => Redirect::temporary("/auth/google").into_response(), ChaosError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized").into_response(), ChaosError::ForbiddenOperation => (StatusCode::FORBIDDEN, "Forbidden operation").into_response(), - ChaosError::ServerError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response() + ChaosError::DatabaseError(db_error) => match db_error { + // We only care about the RowNotFound error, as others are miscellaneous DB errors. + sqlx::Error::RowNotFound => (StatusCode::NOT_FOUND, "Not found").into_response(), + _ => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error").into_response(), + }, + _ => (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error").into_response() } } } - -impl From for ChaosError -where - E: Into, -{ - fn from(err: E) -> Self { - ChaosError::ServerError(err.into()) - } -}