refactor: add DomainError::Forbidden + centralize error-to-HTTP mapping

Ownership checks (delete_review, confirm/dismiss watch events) now
return Forbidden instead of Unauthorized. Presentation layer maps
DomainError→StatusCode via domain_error_response helper, replacing
verbose per-handler match arms.
This commit is contained in:
2026-06-02 21:00:22 +02:00
parent 28170c95d4
commit 4067dedb28
8 changed files with 61 additions and 127 deletions

View File

@@ -4,6 +4,28 @@ use axum::{
};
use domain::errors::DomainError;
pub fn domain_error_status(e: &DomainError) -> StatusCode {
match e {
DomainError::InvalidRating { .. } | DomainError::ValidationError(_) => {
StatusCode::BAD_REQUEST
}
DomainError::NotFound(_) => StatusCode::NOT_FOUND,
DomainError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
DomainError::Forbidden(_) => StatusCode::FORBIDDEN,
DomainError::InfrastructureError(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
pub fn domain_error_response(e: DomainError) -> Response {
match &e {
DomainError::InfrastructureError(_) => {
tracing::error!("Internal error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR.into_response()
}
_ => (domain_error_status(&e), e.to_string()).into_response(),
}
}
pub struct ApiError(pub DomainError);
impl From<DomainError> for ApiError {
@@ -14,20 +36,6 @@ impl From<DomainError> for ApiError {
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let (status, error_message) = match self.0 {
DomainError::InvalidRating { .. } => (StatusCode::BAD_REQUEST, self.0.to_string()),
DomainError::ValidationError(msg) => (StatusCode::BAD_REQUEST, msg),
DomainError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
DomainError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, msg),
DomainError::InfrastructureError(_) => {
tracing::error!("Internal Infrastructure Error: {:?}", self.0);
(
StatusCode::INTERNAL_SERVER_ERROR,
"Internal server error".to_string(),
)
}
};
(status, error_message).into_response()
domain_error_response(self.0)
}
}