use axum::response::IntoResponse;
use http::StatusCode;
use crate::authorization::domain::action::Action;
use crate::authorization::domain::resource::ResourceIdentifier;
use crate::authorization::domain::resource::ResourceType;
use crate::user::domain::User;
#[derive(Debug, Clone, thiserror::Error)]
pub enum RenderError {
#[error("unable to extract router state")]
StateExtraction,
#[error("unable to find resource: {resource_name}")]
ResourceNotFound { resource_name: String },
#[error("{} is not authorized to {} the {:?}: {:?}", user.name, action, resource_type, resource_identifier)]
NotAuthorized {
user: Box<User>,
action: Action,
resource_identifier: Option<ResourceIdentifier>,
resource_type: ResourceType,
},
#[error("user is not authenticated")]
NotAuthenticated,
#[error("the server is not configured correctly: {message}")]
ServerConfiguration { message: String },
#[error("a generic server error: {message}")]
ServerError { message: String },
#[error("an error was experienced during authentication: {message}")]
AuthenticationFlow { message: String },
#[error("there is an issue with the the server infrastructure: {message}")]
Infrastucture { message: String },
}
impl IntoResponse for RenderError {
fn into_response(self) -> axum::response::Response {
tracing::error!("{self}");
match self {
RenderError::StateExtraction
| RenderError::ServerConfiguration { .. }
| RenderError::ServerError { .. }
| RenderError::Infrastucture { .. } => {
(StatusCode::INTERNAL_SERVER_ERROR).into_response()
}
RenderError::ResourceNotFound { .. } => {
(StatusCode::NOT_FOUND, self.to_string()).into_response()
}
RenderError::NotAuthorized { .. } => {
(StatusCode::FORBIDDEN, self.to_string()).into_response()
}
RenderError::NotAuthenticated | RenderError::AuthenticationFlow { .. } => {
(StatusCode::UNAUTHORIZED).into_response()
}
}
}
}