1use std::collections::BTreeSet;
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
13pub enum Permission {
14 Read,
16 Write,
18 Ddl,
20 Admin,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct Role {
27 pub name: String,
29 pub permissions: BTreeSet<Permission>,
31}
32
33impl Role {
34 pub fn allows(&self, p: Permission) -> bool {
36 self.permissions.contains(&p)
37 }
38
39 pub fn admin() -> Role {
41 Role {
42 name: "admin".to_string(),
43 permissions: BTreeSet::from([
44 Permission::Read,
45 Permission::Write,
46 Permission::Ddl,
47 Permission::Admin,
48 ]),
49 }
50 }
51
52 pub fn readwrite() -> Role {
54 Role {
55 name: "readwrite".to_string(),
56 permissions: BTreeSet::from([Permission::Read, Permission::Write]),
57 }
58 }
59
60 pub fn readonly() -> Role {
62 Role {
63 name: "readonly".to_string(),
64 permissions: BTreeSet::from([Permission::Read]),
65 }
66 }
67
68 pub fn builtin(name: &str) -> Option<Role> {
70 match name {
71 "admin" => Some(Role::admin()),
72 "readwrite" => Some(Role::readwrite()),
73 "readonly" => Some(Role::readonly()),
74 _ => None,
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn admin_has_all_permissions() {
85 let r = Role::admin();
86 assert_eq!(
87 r.permissions,
88 BTreeSet::from([
89 Permission::Read,
90 Permission::Write,
91 Permission::Ddl,
92 Permission::Admin,
93 ])
94 );
95 }
96
97 #[test]
98 fn admin_allows_everything() {
99 let r = Role::admin();
100 for p in [
101 Permission::Read,
102 Permission::Write,
103 Permission::Ddl,
104 Permission::Admin,
105 ] {
106 assert!(r.allows(p));
107 }
108 }
109
110 #[test]
111 fn readwrite_has_read_and_write_only() {
112 let r = Role::readwrite();
113 assert_eq!(
114 r.permissions,
115 BTreeSet::from([Permission::Read, Permission::Write])
116 );
117 assert!(r.allows(Permission::Read));
118 assert!(r.allows(Permission::Write));
119 assert!(!r.allows(Permission::Ddl));
120 assert!(!r.allows(Permission::Admin));
121 }
122
123 #[test]
124 fn readonly_has_read_only() {
125 let r = Role::readonly();
126 assert_eq!(r.permissions, BTreeSet::from([Permission::Read]));
127 assert!(r.allows(Permission::Read));
128 assert!(!r.allows(Permission::Write));
129 assert!(!r.allows(Permission::Ddl));
130 assert!(!r.allows(Permission::Admin));
131 }
132
133 #[test]
134 fn builtin_resolves_known_roles() {
135 assert_eq!(Role::builtin("admin").unwrap().name, "admin");
136 assert_eq!(Role::builtin("readwrite").unwrap().name, "readwrite");
137 assert_eq!(Role::builtin("readonly").unwrap().name, "readonly");
138 }
139
140 #[test]
141 fn builtin_unknown_is_none() {
142 assert!(Role::builtin("nope").is_none());
143 }
144}