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}