use oauth2::http::{header, Response, StatusCode}; use std::fmt::{Display, Formatter}; use std::io; #[derive(Debug)] #[allow(clippy::enum_variant_names)] pub enum Error { IoError(io::Error), MissingToken, InvalidToken, ConfigurationError, IntrospectionServerError, AccessDenied, } impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(match self { Error::IoError(e) => return write!(f, "IO Error: {}", e), Error::AccessDenied => "Access denied", Error::MissingToken => "Missing authorization token", Error::InvalidToken => "Invalid access token", Error::ConfigurationError => "OAuth2 client configuration error", Error::IntrospectionServerError => { "Introspection endpoint returned an error" } }) } } impl From<&Error> for StatusCode { fn from(e: &Error) -> StatusCode { match e { Error::IoError(_) => StatusCode::INTERNAL_SERVER_ERROR, Error::AccessDenied => StatusCode::FORBIDDEN, Error::MissingToken => StatusCode::UNAUTHORIZED, Error::InvalidToken => StatusCode::UNAUTHORIZED, Error::ConfigurationError => StatusCode::INTERNAL_SERVER_ERROR, Error::IntrospectionServerError => StatusCode::SERVICE_UNAVAILABLE, } } } impl From for Response> { fn from(e: Error) -> Response> { let resp = Response::builder().status(StatusCode::from(&e)); match e { Error::IoError(_) => resp.body(None).unwrap(), Error::AccessDenied => resp .header(header::WWW_AUTHENTICATE, "Bearer") .body(Some("{\"error\": \"insufficient_scope\"}".to_string())) .unwrap(), Error::MissingToken => resp.body(None).unwrap(), Error::InvalidToken => resp .header(header::WWW_AUTHENTICATE, "Bearer") .body(Some("{\"error\": \"invalid_token\"}".to_string())) .unwrap(), Error::ConfigurationError => resp.body(None).unwrap(), Error::IntrospectionServerError => resp.body(None).unwrap(), } } } impl From for Error { fn from(e: io::Error) -> Self { Error::IoError(e) } }