use axum::{ http::{self, StatusCode}, response::IntoResponse, }; use openidconnect::{ core::CoreErrorResponseType, ClaimsVerificationError, StandardErrorResponse, }; use tracing::error; type UserInfoError = openidconnect::UserInfoError>; type RequestTokenError = openidconnect::RequestTokenError< openidconnect::reqwest::Error, StandardErrorResponse, >; #[derive(thiserror::Error, Debug)] pub enum BridgeError { #[error("Invalid request: {0}")] InvalidRequest(String), #[error("Version conflict when updating object {0} to version {1}")] JournalConflict(String, i64), #[error("Requesting token failed")] OpenidRequestTokenError(#[from] RequestTokenError), #[error("Requesting user info failed")] OpenidUserInfoError(#[from] UserInfoError), #[error("Failed to configure OpenId request")] OpenIdConfigurationError(#[from] openidconnect::ConfigurationError), #[error("Unexpected authorization error")] UnexpectedInvalidAuthorization(#[from] ClaimsVerificationError), #[error("User is not logged in")] NotLoggedIn, #[error("Anyhow error")] AnyhowError(#[from] anyhow::Error), #[error("Authentication error")] SigningFailed(#[from] openidconnect::SigningError), #[error("Database error")] SqlxError(#[from] sqlx::Error), #[error("Uuid parse failed")] UuidError(#[from] uuid::Error), #[error("Serialization error")] SerdeError(#[from] serde_json::Error), #[error("Internal server error: {0}")] Internal(String), #[error("Duration out of range")] DurationOutOfRange(#[from] chrono::OutOfRangeError), #[error("Not found: {0}")] NotFound(String), #[error("Sequence number mismatch: {0} ≠ {1}")] UpdateConflict(i64, i64), } impl BridgeError { pub fn as_rejection(&self) -> (http::StatusCode, String) { match self { BridgeError::NotLoggedIn => { (StatusCode::UNAUTHORIZED, "Must be logged in".to_string()) } BridgeError::OpenidRequestTokenError(_) => { (StatusCode::UNAUTHORIZED, "Error fetching token".to_string()) } _ => (StatusCode::INTERNAL_SERVER_ERROR, "Error: {self}".to_string()), } } } impl IntoResponse for BridgeError { fn into_response(self) -> axum::response::Response { error!("Error occurred: {self:?}"); self.as_rejection().into_response() } }