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