1use axum::{
2 Json,
3 http::StatusCode,
4 response::{IntoResponse, Response},
5};
6use serde::Serialize;
7use thiserror::Error;
8
9use crate::DenialResponse;
10
11#[derive(Debug, Error)]
13pub enum GatekeepAxumError<Resolve, Audit> {
14 #[error("failed to hash policy")]
16 PolicyHash(#[source] postcard::Error),
17 #[error(transparent)]
19 Resolve(#[from] gatekeep::ResolveError<Resolve>),
20 #[error(transparent)]
22 Trace(#[from] gatekeep::TraceError),
23 #[error("audit sink failed")]
25 Audit(#[source] Audit),
26}
27
28#[derive(Debug)]
30pub enum GatekeepRejection<Resolve, Audit> {
31 Denied(DenialResponse),
33 Error(GatekeepAxumError<Resolve, Audit>),
35}
36
37impl<Resolve, Audit> GatekeepRejection<Resolve, Audit> {
38 pub(crate) const fn from_error(error: GatekeepAxumError<Resolve, Audit>) -> Self {
39 Self::Error(error)
40 }
41}
42
43impl<Resolve, Audit> From<DenialResponse> for GatekeepRejection<Resolve, Audit> {
44 fn from(response: DenialResponse) -> Self {
45 Self::Denied(response)
46 }
47}
48
49impl<Resolve, Audit> From<GatekeepAxumError<Resolve, Audit>> for GatekeepRejection<Resolve, Audit> {
50 fn from(error: GatekeepAxumError<Resolve, Audit>) -> Self {
51 Self::Error(error)
52 }
53}
54
55impl<Resolve, Audit> IntoResponse for GatekeepRejection<Resolve, Audit> {
56 fn into_response(self) -> Response {
57 match self {
58 Self::Denied(denial) => denial.into_response(),
59 Self::Error(_error) => (
60 StatusCode::INTERNAL_SERVER_ERROR,
61 Json(ErrorBody {
62 error: "authorization_error",
63 message: "authorization failed",
64 }),
65 )
66 .into_response(),
67 }
68 }
69}
70
71#[derive(Serialize)]
72struct ErrorBody {
73 error: &'static str,
74 message: &'static str,
75}