manas_access_control/model/pdp/
mod.rs1use std::{collections::HashSet, fmt::Debug, ops::Deref, sync::Arc};
6
7use acp::model::{access_mode::HAccessMode, attribute::HAttribute, context::DContext};
8use dyn_problem::{define_anon_problem_types, ProbFuture};
9use http_uri::invariant::NormalAbsoluteHttpUri;
10use itertools::Itertools;
11use manas_space::{resource::slot::SolidResourceSlot, SolidStorageSpace};
12use rdf_utils::model::{
13 graph::{InfallibleGraph, InfallibleMutableGraph},
14 handle::Handle,
15 term::ArcTerm,
16};
17use sophia_api::term::Term;
18
19use super::AccessGrantSet;
20use crate::model::prp::SlotAcrChain;
21
22pub mod impl_;
23
24#[derive(Debug, Clone)]
26pub struct AccessGrantResponse<Space: SolidStorageSpace> {
27 pub res_slot: Option<SolidResourceSlot<Space>>,
30
31 pub access_grant_set: AccessGrantSet,
33}
34
35pub trait PolicyDecisionPoint: Debug + Send + Sync + 'static {
40 type StSpace: SolidStorageSpace;
42
43 type Graph: InfallibleMutableGraph + Default + Send + Sync + 'static;
45
46 fn supported_access_modes(&self) -> &HashSet<HAccessMode<ArcTerm>>;
48
49 fn supported_attrs(&self) -> &HashSet<HAttribute<ArcTerm>>;
51
52 fn resolve_grants(
54 &self,
55 context: ResourceAccessContext<Self::Graph>,
56 acr_chain: SlotAcrChain<Self::StSpace, Self::Graph, Arc<Self::Graph>>,
57 ) -> ProbFuture<'static, AccessGrantResponse<Self::StSpace>>;
58}
59
60pub struct ResourceAccessContext<G: InfallibleGraph> {
62 target_uri: NormalAbsoluteHttpUri,
63 inner: DContext<G, G>,
64}
65
66impl<G: InfallibleGraph> TryFrom<DContext<G, G>> for ResourceAccessContext<G> {
67 type Error = InvalidTargetAttribute;
68
69 fn try_from(context: DContext<G, G>) -> Result<Self, Self::Error> {
70 let h_target = context
72 .h_target::<ArcTerm>()
73 .exactly_one()
74 .map_err(|_| InvalidTargetAttribute::InvalidCardinality)?;
75
76 let target_uri = h_target
78 .as_term()
79 .iri()
80 .and_then(|iri| NormalAbsoluteHttpUri::try_new_from(iri.as_str()).ok())
81 .ok_or(InvalidTargetAttribute::UriIsNotNormalAbsolute)?;
82
83 Ok(Self {
84 target_uri,
85 inner: context,
86 })
87 }
88}
89
90impl<G: InfallibleGraph> Deref for ResourceAccessContext<G> {
91 type Target = DContext<G, G>;
92
93 #[inline]
94 fn deref(&self) -> &Self::Target {
95 &self.inner
96 }
97}
98
99impl<G: InfallibleGraph> ResourceAccessContext<G> {
100 #[inline]
104 pub(crate) fn new_unchecked(target_uri: NormalAbsoluteHttpUri, inner: DContext<G, G>) -> Self {
105 Self { target_uri, inner }
106 }
107
108 #[inline]
110 pub fn target_uri(&self) -> &NormalAbsoluteHttpUri {
111 &self.target_uri
112 }
113
114 #[inline]
116 pub fn into_inner(self) -> DContext<G, G> {
117 self.inner
118 }
119}
120
121#[derive(Debug, thiserror::Error)]
123pub enum InvalidTargetAttribute {
124 #[error("Invalid cardinality of `acp:target` in access context graph.")]
126 InvalidCardinality,
127
128 #[error("acp:target attribute value is not a normal absolute http uri.")]
130 UriIsNotNormalAbsolute,
131}
132
133define_anon_problem_types!(
134 UNKNOWN_TARGET_RESOURCE: (
136 "Unknown target resource."
137 );
138
139 INVALID_PRP_RESPONSE: (
141 "Invalid prp response."
142 );
143);