1use derive_more::Display;
2use std::{
3 any::type_name,
4 fmt::{self, Debug},
5 ops::{BitAnd, BitOr},
6};
7
8use super::Role;
9use crate::claims::common::ScalarOrArray;
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
14#[display("{_0}")]
15pub struct Scope(PermissionFlags);
16
17impl Default for Scope {
18 fn default() -> Self {
21 Self::with_no_permissions()
22 }
23}
24
25#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct PermissionFlags(u64);
30
31#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
35pub enum Permission {
36 #[display("access_key:{_0}")]
37 AccessKey(AccessKeyPermission),
38
39 #[display("dataset:{_0}")]
40 Keyset(KeysetPermission),
41
42 #[display("client:{_0}")]
43 Client(ClientPermission),
44
45 #[display("data_key:{_0}")]
46 DataKey(DataKeyPermission),
47
48 #[display("cs_support:{_0}")]
49 Support(SupportPermission),
50
51 #[display("logging:{_0}")]
52 Logging(LoggingPermission),
53
54 #[display("actor:{_0}")]
55 Actor(ActorPermission),
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
62#[repr(u8)]
63pub enum SupportPermission {
64 #[display("admin")]
65 Admin = 0b0000_0001,
66}
67
68#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
72#[repr(u8)]
73pub enum LoggingPermission {
74 #[display("append")]
75 Append = 0b0000_0001,
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
80#[repr(u8)]
81pub enum AccessKeyPermission {
82 #[display("create")]
84 Create = 0b0000_0001,
85
86 #[display("list")]
88 List = 0b0000_0010,
89
90 #[display("delete")]
92 Delete = 0b0000_0100,
93
94 #[display("update")]
96 Update = 0b0000_1000,
97}
98
99#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
101#[repr(u8)]
102pub enum KeysetPermission {
103 #[display("create")]
105 Create = 0b0000_0001,
106
107 #[display("list")]
109 List = 0b0000_0010,
110
111 #[display("disable")]
113 Disable = 0b0000_0100,
114
115 #[display("enable")]
117 Enable = 0b0000_1000,
118
119 #[display("grant")]
121 Grant = 0b0001_0000,
122
123 #[display("modify")]
125 Modify = 0b0010_0000,
126
127 #[display("revoke")]
129 Revoke = 0b0100_0000,
130}
131
132#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
134#[repr(u8)]
135pub enum ClientPermission {
136 #[display("create")]
138 Create = 0b0000_0001,
139
140 #[display("list")]
142 List = 0b0000_0010,
143
144 #[display("delete")]
146 Delete = 0b0000_0100,
147}
148
149#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
151#[repr(u8)]
152pub enum DataKeyPermission {
153 #[display("generate")]
155 Generate = 0b0000_0001,
156
157 #[display("retrieve")]
159 Retrieve = 0b0000_0010,
160}
161
162#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
164#[repr(u8)]
165pub enum ActorPermission {
166 #[display("create")]
168 Create = 0b0000_0001,
169
170 #[display("list")]
172 List = 0b0000_0010,
173
174 #[display("delete")]
176 Delete = 0b0000_0100,
177}
178
179impl Permission {
180 fn parse(input: &str) -> Option<Self> {
184 match input {
185 s if s.starts_with("keyset:") => Some(Self::Keyset(KeysetPermission::parse(
186 &s["keyset:".len()..],
187 )?)),
188 s if s.starts_with("access_key:") => Some(Self::AccessKey(AccessKeyPermission::parse(
189 &s["access_key:".len()..],
190 )?)),
191 s if s.starts_with("dataset:") => Some(Self::Keyset(KeysetPermission::parse(
193 &s["dataset:".len()..],
194 )?)),
195 s if s.starts_with("data_key:") => Some(Self::DataKey(DataKeyPermission::parse(
196 &s["data_key:".len()..],
197 )?)),
198 s if s.starts_with("client:") => Some(Self::Client(ClientPermission::parse(
199 &s["client:".len()..],
200 )?)),
201 s if s.starts_with("cs_support:") => Some(Self::Support(SupportPermission::parse(
202 &s["cs_support:".len()..],
203 )?)),
204 s if s.starts_with("logging:") => Some(Self::Logging(LoggingPermission::parse(
205 &s["logging:".len()..],
206 )?)),
207 s if s.starts_with("actor:") => {
208 Some(Self::Actor(ActorPermission::parse(&s["actor:".len()..])?))
209 }
210 _ => None,
211 }
212 }
213
214 const fn to_flags(self) -> PermissionFlags {
216 const _: () = assert!(size_of::<KeysetPermission>() == 1);
220 const _: () = assert!(size_of::<ClientPermission>() == 1);
221 const _: () = assert!(size_of::<DataKeyPermission>() == 1);
222 const _: () = assert!(size_of::<SupportPermission>() == 1);
223 const _: () = assert!(size_of::<LoggingPermission>() == 1);
224 const _: () = assert!(size_of::<AccessKeyPermission>() == 1);
225 const _: () = assert!(size_of::<ActorPermission>() == 1);
226
227 match self {
228 Permission::Keyset(permission) => PermissionFlags(permission as u64),
229 Permission::Client(permission) => PermissionFlags((permission as u64) << 8),
230 Permission::DataKey(permission) => PermissionFlags((permission as u64) << 16),
231 Permission::Support(permission) => PermissionFlags((permission as u64) << 24),
232 Permission::Logging(permission) => PermissionFlags((permission as u64) << 32),
233 Permission::AccessKey(permission) => PermissionFlags((permission as u64) << 40),
234 Permission::Actor(permission) => PermissionFlags((permission as u64) << 48),
235 }
236 }
237
238 const ALL: &[Permission] = &[
240 Self::Keyset(KeysetPermission::Create),
242 Self::Keyset(KeysetPermission::List),
243 Self::Keyset(KeysetPermission::Enable),
244 Self::Keyset(KeysetPermission::Disable),
245 Self::Keyset(KeysetPermission::Grant),
246 Self::Keyset(KeysetPermission::Modify),
247 Self::Keyset(KeysetPermission::Revoke),
248 Self::DataKey(DataKeyPermission::Generate),
250 Self::DataKey(DataKeyPermission::Retrieve),
251 Self::Client(ClientPermission::Create),
253 Self::Client(ClientPermission::List),
254 Self::Client(ClientPermission::Delete),
255 Self::AccessKey(AccessKeyPermission::Create),
257 Self::AccessKey(AccessKeyPermission::List),
258 Self::AccessKey(AccessKeyPermission::Delete),
259 Self::AccessKey(AccessKeyPermission::Update),
260 Self::Actor(ActorPermission::Create),
262 Self::Actor(ActorPermission::List),
263 Self::Actor(ActorPermission::Delete),
264 Self::Support(SupportPermission::Admin),
265 Self::Logging(LoggingPermission::Append),
266 ];
267}
268
269macro_rules! impl_from {
270 ($variant:ident, $ty:ty) => {
271 impl From<$ty> for Permission {
272 fn from(value: $ty) -> Self {
273 Self::$variant(value)
274 }
275 }
276 };
277}
278
279impl_from!(AccessKey, AccessKeyPermission);
280impl_from!(Keyset, KeysetPermission);
281impl_from!(DataKey, DataKeyPermission);
282impl_from!(Client, ClientPermission);
283impl_from!(Support, SupportPermission);
284impl_from!(Logging, LoggingPermission);
285impl_from!(Actor, ActorPermission);
286
287impl PermissionFlags {
288 pub const fn empty() -> Self {
290 Self(0)
291 }
292
293 pub const fn with_flag(flag: Permission) -> Self {
295 Self::empty().add(flag)
296 }
297
298 pub const fn add(self, permission: Permission) -> Self {
300 Self(self.0 | permission.to_flags().0)
301 }
302
303 pub const fn merge(self, other: Self) -> Self {
305 Self(self.0 | other.0)
306 }
307
308 fn count_permissions(&self) -> u32 {
310 self.0.count_ones()
311 }
312}
313
314impl IntoIterator for PermissionFlags {
315 type IntoIter = PermissionsIter;
316 type Item = Permission;
317
318 fn into_iter(self) -> Self::IntoIter {
319 PermissionsIter(self, Permission::ALL)
320 }
321}
322
323impl FromIterator<Permission> for PermissionFlags {
324 fn from_iter<T: IntoIterator<Item = Permission>>(iter: T) -> Self {
325 let iter = iter.into_iter();
326 let mut flags = Self(0);
327 for permission in iter {
328 flags = flags.add(permission);
329 }
330 flags
331 }
332}
333
334pub struct PermissionsIter(PermissionFlags, &'static [Permission]);
336
337impl Iterator for PermissionsIter {
338 type Item = Permission;
339
340 fn next(&mut self) -> Option<Self::Item> {
341 loop {
344 if let Some((first, rest)) = self.1.split_first() {
345 self.1 = rest;
347 if self.0 & first.to_flags() == first.to_flags() {
348 return Some(*first);
349 }
350 } else {
351 return None;
353 }
354 }
355 }
356}
357
358impl BitAnd for PermissionFlags {
359 type Output = Self;
360
361 fn bitand(self, rhs: Self) -> Self::Output {
362 Self(self.0 & rhs.0)
363 }
364}
365
366impl BitOr for PermissionFlags {
367 type Output = Self;
368
369 fn bitor(self, rhs: Self) -> Self::Output {
370 Self(self.0 | rhs.0)
371 }
372}
373
374impl fmt::Display for PermissionFlags {
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 let count = self.count_permissions() as usize;
377
378 for (idx, scope) in self.into_iter().enumerate() {
380 fmt::Display::fmt(&scope, f)?;
381 if idx < count - 1 {
382 fmt::Display::fmt(", ", f)?;
383 }
384 }
385
386 Ok(())
387 }
388}
389
390impl Debug for PermissionFlags {
391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392 let count = self.count_permissions() as usize;
393
394 f.write_fmt(format_args!("{}(", type_name::<Self>()))?;
395
396 for (idx, scope) in self.into_iter().enumerate() {
397 fmt::Display::fmt(&scope, f)?;
398 if idx < count - 1 {
399 fmt::Display::fmt("|", f)?;
400 }
401 }
402
403 f.write_str(")")?;
404
405 Ok(())
406 }
407}
408
409impl KeysetPermission {
410 fn parse(input: &str) -> Option<Self> {
411 match input {
412 "create" => Some(Self::Create),
413 "list" => Some(Self::List),
414 "disable" => Some(Self::Disable),
415 "enable" => Some(Self::Enable),
416 "grant" => Some(Self::Grant),
417 "modify" => Some(Self::Modify),
418 "revoke" => Some(Self::Revoke),
419 _ => None,
420 }
421 }
422}
423
424impl ClientPermission {
425 fn parse(input: &str) -> Option<Self> {
426 match input {
427 "create" => Some(Self::Create),
428 "list" => Some(Self::List),
429 "delete" => Some(Self::Delete),
430 _ => None,
431 }
432 }
433}
434
435impl DataKeyPermission {
436 fn parse(input: &str) -> Option<Self> {
437 match input {
438 "generate" => Some(Self::Generate),
439 "retrieve" => Some(Self::Retrieve),
440 _ => None,
441 }
442 }
443}
444
445impl SupportPermission {
446 fn parse(input: &str) -> Option<Self> {
447 match input {
448 "admin" => Some(Self::Admin),
449 _ => None,
450 }
451 }
452}
453
454impl LoggingPermission {
455 fn parse(input: &str) -> Option<Self> {
456 match input {
457 "append" => Some(Self::Append),
458 _ => None,
459 }
460 }
461}
462
463impl AccessKeyPermission {
464 fn parse(input: &str) -> Option<Self> {
465 match input {
466 "create" => Some(Self::Create),
467 "list" => Some(Self::List),
468 "delete" => Some(Self::Delete),
469 "update" => Some(Self::Update),
470 _ => None,
471 }
472 }
473}
474
475impl ActorPermission {
476 fn parse(input: &str) -> Option<Self> {
477 match input {
478 "create" => Some(Self::Create),
479 "list" => Some(Self::List),
480 "delete" => Some(Self::Delete),
481 _ => None,
482 }
483 }
484}
485
486impl Scope {
487 pub const fn with_permissions(permissions: PermissionFlags) -> Self {
489 Self(permissions)
490 }
491
492 pub const fn with_permission(permission: Permission) -> Self {
494 Self(PermissionFlags::empty().add(permission))
495 }
496
497 pub fn with_no_permissions() -> Self {
499 Self(PermissionFlags::empty())
500 }
501
502 pub fn merge(self, other: Self) -> Self {
504 Self(self.0 | other.0)
505 }
506
507 pub fn parse(input: &str) -> Self {
510 let permissions: PermissionFlags =
511 input
512 .split_whitespace()
513 .fold(PermissionFlags::empty(), |acc, s| {
514 if let Some(permission) = Permission::parse(s) {
515 acc.add(permission)
516 } else {
517 acc
518 }
519 });
520
521 Self(permissions)
522 }
523
524 pub fn has_permission(&self, permission: Permission) -> bool {
526 self.0 & permission.to_flags() == permission.to_flags()
527 }
528
529 pub fn has_all_permissions(&self, other: Self) -> bool {
531 self.0 & other.0 == other.0
532 }
533
534 pub fn count_permissions(&self) -> u32 {
536 self.0.count_permissions()
537 }
538
539 pub fn permissions(&self) -> impl Iterator<Item = Permission> {
541 self.0.into_iter()
542 }
543}
544
545pub const WORKSPACE_ADMIN_SCOPE: Scope = Scope(
548 PermissionFlags::empty()
549 .add(Permission::AccessKey(AccessKeyPermission::Create))
550 .add(Permission::AccessKey(AccessKeyPermission::List))
551 .add(Permission::AccessKey(AccessKeyPermission::Delete))
552 .add(Permission::AccessKey(AccessKeyPermission::Update))
553 .add(Permission::Keyset(KeysetPermission::Create))
554 .add(Permission::Keyset(KeysetPermission::List))
555 .add(Permission::Keyset(KeysetPermission::Disable))
556 .add(Permission::Keyset(KeysetPermission::Enable))
557 .add(Permission::Keyset(KeysetPermission::Grant))
558 .add(Permission::Keyset(KeysetPermission::Modify))
559 .add(Permission::Keyset(KeysetPermission::Revoke))
560 .add(Permission::Client(ClientPermission::Create))
561 .add(Permission::Client(ClientPermission::List))
562 .add(Permission::Client(ClientPermission::Delete))
563 .add(Permission::DataKey(DataKeyPermission::Generate))
564 .add(Permission::DataKey(DataKeyPermission::Retrieve))
565 .add(Permission::Actor(ActorPermission::Create))
566 .add(Permission::Actor(ActorPermission::List))
567 .add(Permission::Actor(ActorPermission::Delete)),
568);
569
570pub const WORKSPACE_CONTROL_SCOPE: Scope = Scope(
574 PermissionFlags::empty()
575 .add(Permission::Keyset(KeysetPermission::Create))
576 .add(Permission::Keyset(KeysetPermission::List))
577 .add(Permission::Keyset(KeysetPermission::Disable))
578 .add(Permission::Keyset(KeysetPermission::Enable))
579 .add(Permission::Keyset(KeysetPermission::Grant))
580 .add(Permission::Keyset(KeysetPermission::Modify))
581 .add(Permission::Keyset(KeysetPermission::Revoke))
582 .add(Permission::Client(ClientPermission::List)),
583);
584
585pub const WORKSPACE_MEMBER_SCOPE: Scope = Scope(
588 PermissionFlags::empty()
589 .add(Permission::Keyset(KeysetPermission::List))
590 .add(Permission::Client(ClientPermission::Create))
591 .add(Permission::DataKey(DataKeyPermission::Generate))
592 .add(Permission::DataKey(DataKeyPermission::Retrieve)),
593);
594
595pub const LOGGING_SCOPE: Scope =
596 Scope(PermissionFlags::empty().add(Permission::Logging(LoggingPermission::Append)));
597
598impl From<Option<Role>> for Scope {
599 fn from(role: Option<Role>) -> Self {
600 match role {
601 Some(role) => role.scope(),
602 None => Default::default(),
603 }
604 }
605}
606
607impl From<Vec<String>> for Scope {
608 fn from(scope_names: Vec<String>) -> Self {
609 Scope(
610 scope_names
611 .into_iter()
612 .fold(PermissionFlags::empty(), |acc, s| {
613 if let Some(permission) = Permission::parse(&s) {
614 acc.merge(permission.to_flags())
615 } else {
616 acc
617 }
618 }),
619 )
620 }
621}
622
623impl Serialize for Permission {
624 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
625 where
626 S: serde::Serializer,
627 {
628 self.to_string().serialize(serializer)
629 }
630}
631
632impl Serialize for Scope {
633 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
634 where
635 S: serde::Serializer,
636 {
637 let flags: Vec<Permission> = self.permissions().collect();
638
639 match &flags[..] {
641 &[] => serializer.serialize_none(),
642 &[permission] => Some(ScalarOrArray::Scalar(permission)).serialize(serializer),
643 flags => Some(ScalarOrArray::Array(flags.iter().collect())).serialize(serializer),
644 }
645 }
646}
647
648impl<'de> Deserialize<'de> for Scope {
650 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
651 where
652 D: serde::Deserializer<'de>,
653 {
654 let items: Option<ScalarOrArray<String>> = Deserialize::deserialize(deserializer)?;
655 match items {
656 Some(ScalarOrArray::Array(items)) => Ok(Scope::from(items)),
657 Some(ScalarOrArray::Scalar(item)) => Ok(Scope(
658 Permission::parse(&item)
659 .map(|p| p.to_flags())
660 .unwrap_or(PermissionFlags::empty()),
661 )),
662 None => Ok(Scope::with_no_permissions()),
663 }
664 }
665}
666
667impl From<String> for Scope {
668 fn from(value: String) -> Self {
669 Scope::parse(&value)
670 }
671}
672
673#[cfg(test)]
674mod tests {
675 use super::*;
676 use serde_json::{json, Value};
677
678 mod parse {
679 use super::*;
680
681 #[test]
682 fn empty_string_parses_to_empty_scope() {
683 let scope = Scope::parse("");
684 assert_eq!(scope, Scope::with_no_permissions());
685 }
686
687 #[test]
688 fn single_scope_parses_correctly() {
689 let scope = Scope::parse("dataset:create");
690 assert!(scope.has_permission(Permission::Keyset(KeysetPermission::Create)));
691 assert_eq!(scope.count_permissions(), 1);
692 }
693
694 #[test]
695 fn multiple_scopes_parse_correctly() {
696 let scope = Scope::parse("dataset:create client:list");
697 assert!(scope.has_permission(Permission::Keyset(KeysetPermission::Create)));
698 assert!(scope.has_permission(Permission::Client(ClientPermission::List)));
699 assert_eq!(scope.count_permissions(), 2);
700 }
701 }
702
703 mod serialize {
704 use super::*;
705
706 #[test]
707 fn empty_scope_serializes_as_null() {
708 let scope = Scope::default();
709 let serialized = serde_json::to_value(scope).unwrap();
710 assert_eq!(serialized, Value::Null);
711 }
712
713 #[test]
714 fn single_scope_serializes_as_string() {
715 let scope = Scope::parse("dataset:create");
716 let serialized = serde_json::to_value(scope).unwrap();
717 assert_eq!(serialized, json!("dataset:create"));
718 }
719
720 #[test]
721 fn multiple_scopes_serializes_as_array() {
722 let scope = Scope::parse("dataset:create client:list");
723 let serialized = serde_json::to_value(scope).unwrap();
724
725 assert!(
726 serialized == json!(["dataset:create", "client:list"])
727 || serialized == json!(["client:list", "dataset:create"]),
728 "Expected serialized scope to be an array of scopes, got: {serialized:?}"
729 );
730 }
731 }
732
733 mod deserialize {
734 use super::*;
735
736 #[test]
737 fn empty_scope_deserializes_from_null() {
738 let json = Value::Null;
739 let scope: Scope = serde_json::from_value(json).unwrap();
740 assert_eq!(scope, Scope::default());
741 }
742
743 #[test]
744 fn empty_string_deserializes_to_empty_scope() {
745 let json = json!("");
746 let scope: Scope = serde_json::from_value(json).unwrap();
747 assert_eq!(scope, Scope::default());
748 }
749
750 #[test]
751 fn single_scope_deserializes_from_string() {
752 let json = json!("dataset:create");
753 let scope: Scope = serde_json::from_value(json).unwrap();
754 assert_eq!(scope, Scope::parse("dataset:create"));
755 }
756
757 #[test]
758 fn multiple_scopes_deserialize_from_array() {
759 let json = json!(["dataset:create", "client:list"]);
760 let scope: Scope = serde_json::from_value(json).unwrap();
761 assert!(scope.has_permission(Permission::Keyset(KeysetPermission::Create)));
762 assert!(scope.has_permission(Permission::Client(ClientPermission::List)));
763 assert_eq!(
764 scope.count_permissions(),
765 2,
766 "Expected scope to contain 2 items"
767 );
768 }
769
770 #[test]
771 fn invalid_scope_deserializes_from_invalid_value() {
772 let json = json!(12345);
773 let result: Result<Scope, _> = serde_json::from_value(json);
774 assert!(
775 result.is_err(),
776 "Expected deserialization to fail for invalid scope"
777 );
778 }
779 }
780
781 mod merge {
782 use super::*;
783
784 #[test]
785 fn non_overlapping() {
786 let scope1 = Scope::parse("dataset:create");
787 let scope2 = Scope::parse("client:list");
788 let merged = scope1.merge(scope2);
789
790 assert!(merged.has_permission(Permission::Keyset(KeysetPermission::Create)));
791 assert!(merged.has_permission(Permission::Client(ClientPermission::List)));
792 assert_eq!(merged.count_permissions(), 2);
793 }
794
795 #[test]
796 fn overlapping() {
797 let scope1 = Scope::parse("dataset:create client:list");
798 let scope2 = Scope::parse("client:list data_key:generate");
799 let merged = scope1.merge(scope2);
800 assert!(merged.has_permission(Permission::Keyset(KeysetPermission::Create)));
801 assert!(merged.has_permission(Permission::Client(ClientPermission::List)));
802 assert!(merged.has_permission(Permission::DataKey(DataKeyPermission::Generate)));
803 assert_eq!(merged.count_permissions(), 3);
804 }
805 }
806
807 mod ensure_bitflag_representation_has_no_collisions {
808 use super::*;
809
810 mod scope_with_all_permissions {
811 use super::*;
812
813 #[test]
814 fn for_each_permission_has_permission_returns_true() {
815 let mut scope = Scope::with_no_permissions();
816 for permission in Permission::ALL {
817 scope = scope.merge(Scope::with_permission(*permission));
818 }
819
820 for permission in Permission::ALL {
821 assert!(scope.has_permission(*permission))
822 }
823 }
824 }
825
826 mod scope_with_all_but_one_permssion {
827 use super::*;
828
829 #[test]
830 fn has_permission_returns_true_for_all_except_one_permission() {
831 for without_permission in Permission::ALL {
832 let permissions: Vec<_> = Permission::ALL
833 .iter()
834 .filter(|p| *p != without_permission)
835 .copied()
836 .collect();
837 let scope = Scope::with_permissions(PermissionFlags::from_iter(
838 permissions.into_iter(),
839 ));
840
841 for permission in Permission::ALL {
842 if permission != without_permission {
843 assert!(scope.has_permission(*permission))
844 } else {
845 assert!(!scope.has_permission(*permission))
846 }
847 }
848 }
849 }
850 }
851 }
852}