use cedar_policy::Decision;
use serde::ser::SerializeStruct;
use serde::{Serialize, Serializer};
use std::collections::HashSet;
use uuid7::Uuid;
#[derive(Debug, Clone, Serialize)]
pub struct AuthorizeResult {
#[serde(serialize_with = "serialize_response")]
pub response: cedar_policy::Response,
pub decision: bool,
pub request_id: String,
}
struct CedarResponse<'a>(&'a cedar_policy::Response);
impl Serialize for CedarResponse<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let response = &self.0;
let decision = match response.decision() {
Decision::Allow => "allow",
Decision::Deny => "deny",
};
let diagnostics = response.diagnostics();
let reason = diagnostics
.reason()
.map(std::string::ToString::to_string)
.collect::<HashSet<String>>();
let errors = diagnostics
.errors()
.map(std::string::ToString::to_string)
.collect::<HashSet<String>>();
let mut state = serializer.serialize_struct("Response", 3)?;
state.serialize_field("decision", decision)?;
state.serialize_field("reason", &reason)?;
state.serialize_field("errors", &errors)?;
state.end()
}
}
#[derive(Debug, Clone, Serialize)]
pub struct MultiIssuerAuthorizeResult {
#[serde(serialize_with = "serialize_response")]
pub response: cedar_policy::Response,
pub decision: bool,
pub request_id: String,
}
fn serialize_response<S>(value: &cedar_policy::Response, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
CedarResponse(value).serialize(serializer)
}
impl MultiIssuerAuthorizeResult {
pub(crate) fn new(response: cedar_policy::Response, request_id: Uuid) -> Self {
let decision = response.decision() == Decision::Allow;
Self {
response,
decision,
request_id: request_id.to_string(),
}
}
}
impl AuthorizeResult {
pub(crate) fn new(response: cedar_policy::Response, request_id: Uuid) -> Self {
let decision = response.decision() == Decision::Allow;
Self {
response,
decision,
request_id: request_id.to_string(),
}
}
#[must_use]
pub fn cedar_decision(&self) -> Decision {
if self.decision {
Decision::Allow
} else {
Decision::Deny
}
}
}