Skip to main content

coil_auth/
schema.rs

1use super::*;
2
3pub fn default_schema() -> Schema {
4    SchemaBuilder::new()
5        .namespace(Namespace::Tenant.as_str(), top_level_namespace())
6        .namespace(
7            Namespace::Site.as_str(),
8            inherited_namespace(Relation::Tenant),
9        )
10        .namespace(
11            Namespace::Brand.as_str(),
12            inherited_namespace(Relation::Site),
13        )
14        .namespace(
15            Namespace::Storefront.as_str(),
16            storefront_namespace(Relation::Brand),
17        )
18        .namespace(Namespace::Group.as_str(), principal_set_namespace())
19        .namespace(Namespace::Team.as_str(), principal_set_namespace())
20        .namespace(
21            Namespace::Page.as_str(),
22            inherited_namespace(Relation::Site),
23        )
24        .namespace(
25            Namespace::Navigation.as_str(),
26            inherited_namespace(Relation::Site),
27        )
28        .namespace(
29            Namespace::Product.as_str(),
30            inherited_namespace(Relation::Storefront),
31        )
32        .namespace(
33            Namespace::Collection.as_str(),
34            inherited_namespace(Relation::Storefront),
35        )
36        .namespace(
37            Namespace::Order.as_str(),
38            order_namespace(Relation::Storefront),
39        )
40        .namespace(
41            Namespace::Subscription.as_str(),
42            inherited_namespace(Relation::Storefront),
43        )
44        .namespace(
45            Namespace::MembershipTier.as_str(),
46            inherited_namespace(Relation::Storefront),
47        )
48        .namespace(
49            Namespace::Event.as_str(),
50            inherited_namespace(Relation::Site),
51        )
52        .namespace(
53            Namespace::EventSlot.as_str(),
54            event_slot_namespace(Relation::Event),
55        )
56        .namespace(
57            Namespace::Booking.as_str(),
58            booking_namespace(Relation::Slot),
59        )
60        .namespace(
61            Namespace::MediaLibrary.as_str(),
62            inherited_namespace(Relation::Site),
63        )
64        .namespace(
65            Namespace::Media.as_str(),
66            media_namespace(Relation::Library),
67        )
68        .namespace(
69            Namespace::AssetFolder.as_str(),
70            inherited_namespace(Relation::Site),
71        )
72        .namespace(Namespace::Asset.as_str(), asset_namespace(Relation::Folder))
73        .namespace(
74            Namespace::ThemeAssetBundle.as_str(),
75            inherited_namespace(Relation::Site),
76        )
77        .namespace(
78            Namespace::AdminModule.as_str(),
79            admin_module_namespace(Relation::Site),
80        )
81        .build()
82}
83
84fn top_level_namespace() -> NamespaceConfig {
85    NamespaceConfig {
86        rules: permission_ladder(),
87    }
88}
89
90fn principal_set_namespace() -> NamespaceConfig {
91    let mut rules = permission_ladder();
92    rules.insert(
93        Relation::View.to_string(),
94        vec![
95            inherit(Relation::Member),
96            inherit(Relation::Viewer),
97            inherit(Relation::Support),
98            inherit(Relation::Edit),
99        ],
100    );
101    NamespaceConfig { rules }
102}
103
104fn inherited_namespace(link_relation: Relation) -> NamespaceConfig {
105    let mut rules = permission_ladder();
106    add_inherited_roles(&mut rules, link_relation);
107    NamespaceConfig { rules }
108}
109
110fn storefront_namespace(link_relation: Relation) -> NamespaceConfig {
111    let mut rules = permission_ladder();
112    add_inherited_roles(&mut rules, link_relation);
113    rules.insert(
114        Relation::Checkout.to_string(),
115        vec![inherit(Relation::View), inherit(Relation::Member)],
116    );
117    NamespaceConfig { rules }
118}
119
120fn order_namespace(link_relation: Relation) -> NamespaceConfig {
121    let mut rules = permission_ladder();
122    add_inherited_roles(&mut rules, link_relation);
123    rules.insert(
124        Relation::Refund.to_string(),
125        vec![inherit(Relation::Manage), inherit(Relation::Support)],
126    );
127    NamespaceConfig { rules }
128}
129
130fn event_slot_namespace(link_relation: Relation) -> NamespaceConfig {
131    let mut rules = permission_ladder();
132    add_inherited_roles(&mut rules, link_relation);
133    rules.insert(
134        Relation::Book.to_string(),
135        vec![inherit(Relation::View), inherit(Relation::Member)],
136    );
137    NamespaceConfig { rules }
138}
139
140fn booking_namespace(link_relation: Relation) -> NamespaceConfig {
141    let mut rules = permission_ladder();
142    add_inherited_roles(&mut rules, link_relation);
143    rules.insert(
144        Relation::CheckIn.to_string(),
145        vec![inherit(Relation::Manage), inherit(Relation::Support)],
146    );
147    NamespaceConfig { rules }
148}
149
150fn media_namespace(link_relation: Relation) -> NamespaceConfig {
151    let mut rules = permission_ladder();
152    add_inherited_roles(&mut rules, link_relation);
153    rules.insert(Relation::Read.to_string(), vec![inherit(Relation::View)]);
154    NamespaceConfig { rules }
155}
156
157fn admin_module_namespace(link_relation: Relation) -> NamespaceConfig {
158    let mut rules = permission_ladder();
159    add_inherited_roles(&mut rules, link_relation);
160    rules.insert(Relation::Read.to_string(), vec![inherit(Relation::View)]);
161    NamespaceConfig { rules }
162}
163
164fn asset_namespace(link_relation: Relation) -> NamespaceConfig {
165    let mut rules = permission_ladder();
166    add_inherited_roles(&mut rules, link_relation);
167    rules.insert(Relation::Read.to_string(), vec![inherit(Relation::View)]);
168    rules.insert(Relation::Replace.to_string(), vec![inherit(Relation::Edit)]);
169    rules.insert(
170        Relation::Delete.to_string(),
171        vec![inherit(Relation::Manage)],
172    );
173    rules.insert(
174        Relation::Unpublish.to_string(),
175        vec![inherit(Relation::Manage)],
176    );
177    rules.insert(
178        Relation::ManageStorage.to_string(),
179        vec![inherit(Relation::Manage)],
180    );
181    NamespaceConfig { rules }
182}
183
184fn permission_ladder() -> HashMap<String, Vec<RelationRule>> {
185    HashMap::from([
186        (
187            Relation::Manage.to_string(),
188            vec![inherit(Relation::Owner), inherit(Relation::Admin)],
189        ),
190        (
191            Relation::Publish.to_string(),
192            vec![inherit(Relation::Manage), inherit(Relation::Editor)],
193        ),
194        (
195            Relation::Edit.to_string(),
196            vec![inherit(Relation::Publish), inherit(Relation::Editor)],
197        ),
198        (
199            Relation::View.to_string(),
200            vec![
201                inherit(Relation::Edit),
202                inherit(Relation::Viewer),
203                inherit(Relation::Support),
204            ],
205        ),
206    ])
207}
208
209fn add_inherited_roles(rules: &mut HashMap<String, Vec<RelationRule>>, link_relation: Relation) {
210    for relation in [
211        Relation::Member,
212        Relation::Owner,
213        Relation::Admin,
214        Relation::Editor,
215        Relation::Viewer,
216        Relation::Support,
217    ] {
218        rules.insert(
219            relation.to_string(),
220            vec![computed(link_relation, relation)],
221        );
222    }
223}
224
225fn inherit(relation: Relation) -> RelationRule {
226    RelationRule::Inherit(relation.to_string())
227}
228
229fn computed(tuple_relation: Relation, target_relation: Relation) -> RelationRule {
230    RelationRule::Computed {
231        tuple_relation: tuple_relation.to_string(),
232        target_relation: target_relation.to_string(),
233    }
234}