Skip to main content

gatekeep_axum/
error.rs

1use axum::{
2    Json,
3    http::StatusCode,
4    response::{IntoResponse, Response},
5};
6use serde::Serialize;
7
8use crate::DenialResponse;
9
10/// Framework-independent authorization failure.
11pub use gatekeep::AuthorizationError as GatekeepAxumError;
12
13/// Axum rejection returned by [`crate::Gatekeeper::authorize`].
14#[derive(Debug)]
15pub enum GatekeepRejection<Resolve, Audit> {
16    /// The policy denied the request.
17    Denied(DenialResponse),
18    /// The authorization boundary failed before a response could be trusted.
19    Error(GatekeepAxumError<Resolve, Audit>),
20}
21
22impl<Resolve, Audit> GatekeepRejection<Resolve, Audit> {
23    pub(crate) const fn from_error(error: GatekeepAxumError<Resolve, Audit>) -> Self {
24        Self::Error(error)
25    }
26}
27
28impl<Resolve, Audit> From<DenialResponse> for GatekeepRejection<Resolve, Audit> {
29    fn from(response: DenialResponse) -> Self {
30        Self::Denied(response)
31    }
32}
33
34impl<Resolve, Audit> From<GatekeepAxumError<Resolve, Audit>> for GatekeepRejection<Resolve, Audit> {
35    fn from(error: GatekeepAxumError<Resolve, Audit>) -> Self {
36        Self::Error(error)
37    }
38}
39
40impl<Resolve, Audit> IntoResponse for GatekeepRejection<Resolve, Audit> {
41    fn into_response(self) -> Response {
42        match self {
43            Self::Denied(denial) => denial.into_response(),
44            Self::Error(_error) => (
45                StatusCode::INTERNAL_SERVER_ERROR,
46                Json(ErrorBody {
47                    error: "authorization_error",
48                    message: "authorization failed",
49                }),
50            )
51                .into_response(),
52        }
53    }
54}
55
56#[derive(Serialize)]
57struct ErrorBody {
58    error: &'static str,
59    message: &'static str,
60}