junobuild_collections/assert/
stores.rs1use crate::types::rules::Permission;
2use candid::Principal;
3use junobuild_shared::segments::controllers::controller_can_write;
4use junobuild_shared::types::state::{Controllers, UserId};
5use junobuild_shared::utils::{principal_not_anonymous, principal_not_anonymous_and_equal};
6
7pub fn assert_permission(
8 permission: &Permission,
9 owner: Principal,
10 caller: Principal,
11 controllers: &Controllers,
12) -> bool {
13 assert_permission_with(permission, owner, caller, controllers, controller_can_write)
14}
15
16pub fn assert_permission_with(
17 permission: &Permission,
18 owner: Principal,
19 caller: Principal,
20 controllers: &Controllers,
21 is_allowed_controller: fn(UserId, &Controllers) -> bool,
22) -> bool {
23 match permission {
24 Permission::Public => true,
25 Permission::Private => is_owner_and_valid(caller, owner, controllers),
26 Permission::Managed => {
27 is_owner_and_valid(caller, owner, controllers)
30 || controller_can_write(caller, controllers)
31 }
32 Permission::Controllers => is_allowed_controller(caller, controllers),
33 }
34}
35
36pub fn assert_create_permission(
39 permission: &Permission,
40 caller: Principal,
41 controllers: &Controllers,
42) -> bool {
43 assert_create_permission_with(permission, caller, controllers, controller_can_write)
44}
45
46pub fn assert_create_permission_with(
47 permission: &Permission,
48 caller: Principal,
49 controllers: &Controllers,
50 is_allowed_controller: fn(UserId, &Controllers) -> bool,
51) -> bool {
52 match permission {
53 Permission::Public => true,
54 Permission::Controllers => is_allowed_controller(caller, controllers),
55 _ => {
56 assert_not_anonymous(caller)
57 && (is_not_controller(caller, controllers)
58 || controller_can_write(caller, controllers))
59 }
60 }
61}
62
63fn is_owner(caller: Principal, owner: Principal) -> bool {
64 principal_not_anonymous_and_equal(caller, owner)
65}
66
67fn assert_not_anonymous(caller: Principal) -> bool {
68 principal_not_anonymous(caller)
69}
70
71pub fn public_permission(permission: &Permission) -> bool {
72 matches!(permission, Permission::Public)
73}
74
75fn is_controller(caller: Principal, controllers: &Controllers) -> bool {
76 controllers.contains_key(&caller)
77}
78
79fn is_not_controller(caller: Principal, controllers: &Controllers) -> bool {
80 !is_controller(caller, controllers)
81}
82
83fn is_owner_and_valid(caller: Principal, owner: Principal, controllers: &Controllers) -> bool {
84 is_owner(caller, owner)
85 && (is_not_controller(caller, controllers) || controller_can_write(caller, controllers))
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use junobuild_shared::types::state::{Controller, ControllerScope, Controllers};
92 use std::collections::HashMap;
93
94 fn test_principal(id: u8) -> Principal {
95 Principal::from_slice(&[id])
96 }
97
98 fn create_controller(scope: ControllerScope, expires_at: Option<u64>) -> Controller {
99 Controller {
100 metadata: HashMap::new(),
101 created_at: 1000,
102 updated_at: 1000,
103 expires_at,
104 scope,
105 kind: None,
106 }
107 }
108
109 fn mock_time() -> u64 {
110 1_000_000_000_000
111 }
112
113 #[test]
114 fn test_is_owner() {
115 let owner = test_principal(1);
116 let caller = test_principal(1);
117 let other = test_principal(2);
118
119 assert!(is_owner(caller, owner));
120 assert!(!is_owner(other, owner));
121 assert!(!is_owner(Principal::anonymous(), owner));
122 }
123
124 #[test]
125 fn test_is_controller() {
126 let mut controllers = Controllers::new();
127 let controller_principal = test_principal(1);
128 let non_controller = test_principal(2);
129
130 controllers.insert(
131 controller_principal,
132 create_controller(ControllerScope::Write, None),
133 );
134
135 assert!(is_controller(controller_principal, &controllers));
136 assert!(!is_controller(non_controller, &controllers));
137 }
138
139 #[test]
140 fn test_public_permission_allows_anyone() {
141 let controllers = Controllers::new();
142 let owner = test_principal(1);
143 let caller = test_principal(2);
144
145 assert!(assert_permission(
146 &Permission::Public,
147 owner,
148 caller,
149 &controllers
150 ));
151 }
152
153 #[test]
154 fn test_private_permission_allows_owner_not_controller() {
155 let controllers = Controllers::new();
156 let owner = test_principal(1);
157
158 assert!(assert_permission(
159 &Permission::Private,
160 owner,
161 owner,
162 &controllers
163 ));
164 }
165
166 #[test]
167 fn test_private_permission_allows_owner_valid_controller() {
168 let mut controllers = Controllers::new();
169 let owner = test_principal(1);
170
171 controllers.insert(
172 owner,
173 create_controller(ControllerScope::Write, Some(mock_time() + 1000)),
174 );
175
176 assert!(assert_permission(
177 &Permission::Private,
178 owner,
179 owner,
180 &controllers
181 ));
182 }
183
184 #[test]
185 fn test_private_permission_rejects_owner_expired_controller() {
186 let mut controllers = Controllers::new();
187 let owner = test_principal(1);
188
189 controllers.insert(
190 owner,
191 create_controller(ControllerScope::Write, Some(mock_time() - 1)),
192 );
193
194 assert!(!assert_permission(
195 &Permission::Private,
196 owner,
197 owner,
198 &controllers
199 ));
200 }
201
202 #[test]
203 fn test_private_permission_rejects_non_owner() {
204 let controllers = Controllers::new();
205 let owner = test_principal(1);
206 let caller = test_principal(2);
207
208 assert!(!assert_permission(
209 &Permission::Private,
210 owner,
211 caller,
212 &controllers
213 ));
214 }
215
216 #[test]
217 fn test_managed_permission_allows_owner_not_controller() {
218 let controllers = Controllers::new();
219 let owner = test_principal(1);
220
221 assert!(assert_permission(
222 &Permission::Managed,
223 owner,
224 owner,
225 &controllers
226 ));
227 }
228
229 #[test]
230 fn test_managed_permission_allows_owner_valid_controller() {
231 let mut controllers = Controllers::new();
232 let owner = test_principal(1);
233
234 controllers.insert(
235 owner,
236 create_controller(ControllerScope::Write, Some(mock_time() + 1000)),
237 );
238
239 assert!(assert_permission(
240 &Permission::Managed,
241 owner,
242 owner,
243 &controllers
244 ));
245 }
246
247 #[test]
248 fn test_managed_permission_rejects_owner_expired_controller() {
249 let mut controllers = Controllers::new();
250 let owner = test_principal(1);
251
252 controllers.insert(
253 owner,
254 create_controller(ControllerScope::Write, Some(mock_time() - 1)),
255 );
256
257 assert!(!assert_permission(
258 &Permission::Managed,
259 owner,
260 owner,
261 &controllers
262 ));
263 }
264
265 #[test]
266 fn test_managed_permission_allows_valid_write_controller() {
267 let mut controllers = Controllers::new();
268 let owner = test_principal(1);
269 let controller = test_principal(2);
270
271 controllers.insert(
272 controller,
273 create_controller(ControllerScope::Write, Some(mock_time() + 1000)),
274 );
275
276 assert!(assert_permission(
277 &Permission::Managed,
278 owner,
279 controller,
280 &controllers
281 ));
282 }
283
284 #[test]
285 fn test_managed_permission_rejects_expired_write_controller() {
286 let mut controllers = Controllers::new();
287 let owner = test_principal(1);
288 let controller = test_principal(2);
289
290 controllers.insert(
291 controller,
292 create_controller(ControllerScope::Write, Some(mock_time() - 1)),
293 );
294
295 assert!(!assert_permission(
296 &Permission::Managed,
297 owner,
298 controller,
299 &controllers
300 ));
301 }
302
303 #[test]
304 fn test_managed_permission_rejects_submit_controller() {
305 let mut controllers = Controllers::new();
306 let owner = test_principal(1);
307 let controller = test_principal(2);
308
309 controllers.insert(controller, create_controller(ControllerScope::Submit, None));
310
311 assert!(!assert_permission(
312 &Permission::Managed,
313 owner,
314 controller,
315 &controllers
316 ));
317 }
318
319 #[test]
320 fn test_controllers_permission_allows_valid_controller() {
321 let mut controllers = Controllers::new();
322 let owner = test_principal(1);
323 let controller = test_principal(2);
324
325 controllers.insert(
326 controller,
327 create_controller(ControllerScope::Write, Some(mock_time() + 1000)),
328 );
329
330 assert!(assert_permission(
331 &Permission::Controllers,
332 owner,
333 controller,
334 &controllers
335 ));
336 }
337
338 #[test]
339 fn test_controllers_permission_rejects_expired_controller() {
340 let mut controllers = Controllers::new();
341 let owner = test_principal(1);
342 let controller = test_principal(2);
343
344 controllers.insert(
345 controller,
346 create_controller(ControllerScope::Write, Some(mock_time() - 1)),
347 );
348
349 assert!(!assert_permission(
350 &Permission::Controllers,
351 owner,
352 controller,
353 &controllers
354 ));
355 }
356
357 #[test]
359 fn test_create_public_allows_anyone() {
360 let controllers = Controllers::new();
361 let caller = test_principal(1);
362
363 assert!(assert_create_permission(
364 &Permission::Public,
365 caller,
366 &controllers
367 ));
368 }
369
370 #[test]
371 fn test_create_private_allows_non_controller() {
372 let controllers = Controllers::new();
373 let caller = test_principal(1);
374
375 assert!(assert_create_permission(
376 &Permission::Private,
377 caller,
378 &controllers
379 ));
380 }
381
382 #[test]
383 fn test_create_private_allows_valid_controller() {
384 let mut controllers = Controllers::new();
385 let caller = test_principal(1);
386
387 controllers.insert(
388 caller,
389 create_controller(ControllerScope::Write, Some(mock_time() + 1000)),
390 );
391
392 assert!(assert_create_permission(
393 &Permission::Private,
394 caller,
395 &controllers
396 ));
397 }
398
399 #[test]
400 fn test_create_private_rejects_expired_controller() {
401 let mut controllers = Controllers::new();
402 let caller = test_principal(1);
403
404 controllers.insert(
405 caller,
406 create_controller(ControllerScope::Write, Some(mock_time() - 1)),
407 );
408
409 assert!(!assert_create_permission(
410 &Permission::Private,
411 caller,
412 &controllers
413 ));
414 }
415
416 #[test]
417 fn test_create_controllers_allows_valid_write_controller() {
418 let mut controllers = Controllers::new();
419 let caller = test_principal(1);
420
421 controllers.insert(
422 caller,
423 create_controller(ControllerScope::Write, Some(mock_time() + 1000)),
424 );
425
426 assert!(assert_create_permission(
427 &Permission::Controllers,
428 caller,
429 &controllers
430 ));
431 }
432
433 #[test]
434 fn test_create_controllers_rejects_submit_controller() {
435 let mut controllers = Controllers::new();
436 let caller = test_principal(1);
437
438 controllers.insert(caller, create_controller(ControllerScope::Submit, None));
439
440 assert!(!assert_create_permission(
441 &Permission::Controllers,
442 caller,
443 &controllers
444 ));
445 }
446}