spicedb_rust/spicedb/
helpers.rs

1use crate::{Caveat, Entity, Relation, RelationshipOperation, Resource, WildCardId};
2
3use super::subject_filter::RelationFilter;
4use super::{
5    ContextualizedCaveat, ObjectReference, Precondition, Relationship, RelationshipFilter,
6    RelationshipUpdate, SubjectFilter, SubjectReference,
7};
8
9pub fn subject_filter<S>(id: Option<S::Id>, relation: Option<S::Relations>) -> SubjectFilter
10where
11    S: Entity,
12{
13    subject_filter_raw(S::object_type(), id, relation.map(|r| r.name()))
14}
15
16pub fn subject_filter_raw(
17    subject_type: impl Into<String>,
18    id: Option<impl Into<String>>,
19    relation: Option<impl Into<String>>,
20) -> SubjectFilter {
21    SubjectFilter {
22        subject_type: subject_type.into(),
23        optional_subject_id: id.map(Into::into).unwrap_or_default(),
24        optional_relation: relation.map(|r| RelationFilter { relation: r.into() }),
25    }
26}
27
28pub fn relationship_filter<R>(
29    resource_id: Option<R::Id>,
30    resource_id_prefix: Option<String>,
31    relation: Option<R::Relations>,
32    subject_filter: Option<SubjectFilter>,
33) -> RelationshipFilter
34where
35    R: Resource,
36{
37    relationship_filter_raw(
38        R::object_type(),
39        resource_id,
40        resource_id_prefix,
41        relation.map(|r| r.name()),
42        subject_filter,
43    )
44}
45
46pub fn relationship_filter_raw(
47    resource_type: impl Into<String>,
48    resource_id: Option<impl Into<String>>,
49    resource_id_prefix: Option<impl Into<String>>,
50    relation: Option<impl Into<String>>,
51    subject_filter: Option<SubjectFilter>,
52) -> RelationshipFilter {
53    RelationshipFilter {
54        resource_type: resource_type.into(),
55        optional_resource_id: resource_id.map(Into::into).unwrap_or_default(),
56        optional_resource_id_prefix: resource_id_prefix.map(Into::into).unwrap_or_default(),
57        optional_relation: relation.map(Into::into).unwrap_or_default(),
58        optional_subject_filter: subject_filter,
59    }
60}
61
62pub fn precondition<R>(
63    operation: super::precondition::Operation,
64    resource_id: Option<R::Id>,
65    resource_id_prefix: Option<String>,
66    relation: Option<R::Relations>,
67    subject_filter: Option<SubjectFilter>,
68) -> Precondition
69where
70    R: Resource,
71{
72    precondition_raw(
73        operation,
74        R::object_type(),
75        resource_id,
76        resource_id_prefix,
77        relation.map(|r| r.name()),
78        subject_filter,
79    )
80}
81
82pub fn precondition_raw(
83    operation: super::precondition::Operation,
84    resource_type: impl Into<String>,
85    resource_id: Option<impl Into<String>>,
86    resource_id_prefix: Option<impl Into<String>>,
87    relation: Option<impl Into<String>>,
88    subject_filter: Option<SubjectFilter>,
89) -> Precondition {
90    Precondition {
91        operation: operation as i32,
92        filter: Some(relationship_filter_raw(
93            resource_type,
94            resource_id,
95            resource_id_prefix,
96            relation,
97            subject_filter,
98        )),
99    }
100}
101
102pub fn subject_reference<S>(id: S::Id, relation: Option<S::Relations>) -> SubjectReference
103where
104    S: Entity,
105{
106    subject_reference_raw(id, S::object_type(), relation.map(|r| r.name()))
107}
108
109pub fn subject_reference_raw(
110    id: impl Into<String>,
111    object_type: impl Into<String>,
112    relation: Option<impl Into<String>>,
113) -> SubjectReference {
114    SubjectReference {
115        object: Some(ObjectReference {
116            object_type: object_type.into(),
117            object_id: id.into(),
118        }),
119        optional_relation: relation.map(Into::into).unwrap_or_default(),
120    }
121}
122
123pub fn object_reference<E>(id: E::Id) -> ObjectReference
124where
125    E: Entity,
126{
127    ObjectReference {
128        object_type: E::object_type().into(),
129        object_id: id.into(),
130    }
131}
132
133pub fn wildcard_relationship_update<S, R>(
134    operation: RelationshipOperation,
135    resource_id: impl Into<R::Id>,
136    relation: R::Relations,
137) -> RelationshipUpdate
138where
139    S: Entity,
140    R: Resource,
141{
142    let subject = subject_reference_raw(WildCardId, S::object_type(), None::<String>);
143    let resource = object_reference::<R>(Into::<R::Id>::into(resource_id));
144    RelationshipUpdate {
145        operation: operation as i32,
146        relationship: Some(Relationship {
147            resource: Some(resource),
148            relation: relation.name().to_owned(),
149            subject: Some(subject),
150            optional_caveat: None,
151        }),
152    }
153}
154
155pub fn relationship_update<S, R>(
156    operation: RelationshipOperation,
157    subject_id: impl Into<S::Id>,
158    subject_relation: Option<S::Relations>,
159    resource_id: impl Into<R::Id>,
160    relation: R::Relations,
161) -> RelationshipUpdate
162where
163    S: Entity,
164    R: Resource,
165{
166    let subject = subject_reference::<S>(Into::<S::Id>::into(subject_id), subject_relation);
167    let resource = object_reference::<R>(Into::<R::Id>::into(resource_id));
168    RelationshipUpdate {
169        operation: operation as i32,
170        relationship: Some(Relationship {
171            resource: Some(resource),
172            relation: relation.name().to_owned(),
173            subject: Some(subject),
174            optional_caveat: None,
175        }),
176    }
177}
178
179pub fn caveated_relationship_update<S, R, C>(
180    operation: RelationshipOperation,
181    subject_id: impl Into<S::Id>,
182    subject_relation: Option<S::Relations>,
183    resource_id: impl Into<R::Id>,
184    relation: R::Relations,
185    caveat_context: C::ContextStruct,
186) -> RelationshipUpdate
187where
188    S: Entity,
189    R: Resource,
190    C: Caveat,
191{
192    let subject = subject_reference::<S>(Into::<S::Id>::into(subject_id), subject_relation);
193    let resource = object_reference::<R>(Into::<R::Id>::into(resource_id));
194    RelationshipUpdate {
195        operation: operation as i32,
196        relationship: Some(Relationship {
197            resource: Some(resource),
198            relation: relation.name().to_owned(),
199            subject: Some(subject),
200            optional_caveat: Some(ContextualizedCaveat {
201                caveat_name: C::name().to_owned(),
202                context: Some(caveat_context.into()),
203            }),
204        }),
205    }
206}