1pub const ROLE_HIERARCHY: &[&str] =
12 &["public", "follower", "supporter", "contributor", "moderator", "leader"];
13
14pub fn expand_roles(highest_roles: &[Box<str>]) -> String {
28 if highest_roles.is_empty() {
29 return String::new();
30 }
31
32 let mut highest_idx: Option<usize> = None;
33 for role in highest_roles {
34 if let Some(idx) = ROLE_HIERARCHY.iter().position(|&r| r == role.as_ref()) {
35 highest_idx = Some(highest_idx.map_or(idx, |h| h.max(idx)));
36 }
37 }
38
39 match highest_idx {
41 Some(idx) => ROLE_HIERARCHY[..=idx].join(","),
42 None => String::new(),
43 }
44}
45
46pub fn role_level(role: &str) -> Option<usize> {
48 ROLE_HIERARCHY.iter().position(|&r| r == role)
49}
50
51pub fn highest_role_level(roles: &[Box<str>]) -> usize {
54 roles.iter().filter_map(|r| role_level(r)).max().unwrap_or(0)
55}
56
57pub const MODERATOR_LEVEL: usize = 4;
59pub const LEADER_LEVEL: usize = 5;
61
62pub fn can_manage_member(actor_level: usize, target_level: usize) -> bool {
66 actor_level >= MODERATOR_LEVEL && (actor_level > target_level || actor_level == LEADER_LEVEL)
67}
68
69pub fn can_manage_member_by_roles(actor_roles: &[Box<str>], target_roles: &[Box<str>]) -> bool {
72 can_manage_member(highest_role_level(actor_roles), highest_role_level(target_roles))
73}
74
75pub fn can_assign_role(role: &str, actor_level: usize) -> bool {
79 match role_level(role) {
80 Some(new_level) => actor_level >= LEADER_LEVEL || new_level < actor_level,
81 None => false,
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
93
94 #[test]
95 fn test_expand_roles_empty() {
96 assert_eq!(expand_roles(&[]), "");
97 }
98
99 #[test]
100 fn test_expand_roles_single() {
101 assert_eq!(expand_roles(&["public".into()]), "public");
102 assert_eq!(expand_roles(&["follower".into()]), "public,follower");
103 assert_eq!(
104 expand_roles(&["moderator".into()]),
105 "public,follower,supporter,contributor,moderator"
106 );
107 assert_eq!(
108 expand_roles(&["leader".into()]),
109 "public,follower,supporter,contributor,moderator,leader"
110 );
111 }
112
113 #[test]
114 fn test_expand_roles_multiple() {
115 assert_eq!(
117 expand_roles(&["contributor".into(), "moderator".into()]),
118 "public,follower,supporter,contributor,moderator"
119 );
120 assert_eq!(
121 expand_roles(&["public".into(), "leader".into()]),
122 "public,follower,supporter,contributor,moderator,leader"
123 );
124 }
125
126 #[test]
127 fn test_expand_roles_unknown() {
128 assert_eq!(expand_roles(&["unknown".into()]), "");
130 assert_eq!(
131 expand_roles(&["unknown".into(), "contributor".into()]),
132 "public,follower,supporter,contributor"
133 );
134 }
135
136 #[test]
137 fn test_role_level() {
138 assert_eq!(role_level("public"), Some(0));
139 assert_eq!(role_level("follower"), Some(1));
140 assert_eq!(role_level("moderator"), Some(4));
141 assert_eq!(role_level("leader"), Some(5));
142 assert_eq!(role_level("unknown"), None);
143 }
144
145 #[test]
146 fn test_level_consts_match_hierarchy() {
147 assert_eq!(role_level("moderator"), Some(MODERATOR_LEVEL));
148 assert_eq!(role_level("leader"), Some(LEADER_LEVEL));
149 }
150
151 #[test]
152 fn test_can_manage_member() {
153 assert!(can_manage_member(4, 3));
155 assert!(!can_manage_member(4, 4));
157 assert!(can_manage_member(5, 5));
159 assert!(!can_manage_member(3, 0));
161 }
162
163 #[test]
164 fn test_highest_role_level() {
165 assert_eq!(highest_role_level(&[]), 0);
167 assert_eq!(highest_role_level(&["unknown".into()]), 0);
168 assert_eq!(highest_role_level(&["follower".into()]), 1);
170 assert_eq!(highest_role_level(&["moderator".into()]), 4);
171 assert_eq!(highest_role_level(&["leader".into()]), 5);
172 assert_eq!(highest_role_level(&["contributor".into(), "moderator".into()]), 4);
173 assert_eq!(highest_role_level(&["unknown".into(), "leader".into()]), 5);
174 }
175
176 #[test]
177 fn test_can_manage_member_by_roles() {
178 assert!(can_manage_member_by_roles(&["moderator".into()], &["contributor".into()]));
180 assert!(!can_manage_member_by_roles(&["moderator".into()], &["moderator".into()]));
182 assert!(can_manage_member_by_roles(&["leader".into()], &["leader".into()]));
184 assert!(!can_manage_member_by_roles(&["contributor".into()], &["public".into()]));
186 assert!(!can_manage_member_by_roles(&[], &["public".into()]));
188 assert!(can_manage_member_by_roles(
190 &["unknown".into(), "moderator".into()],
191 &["contributor".into()]
192 ));
193 }
194
195 #[test]
196 fn test_can_assign_role() {
197 assert!(can_assign_role("leader", LEADER_LEVEL));
199 assert!(can_assign_role("moderator", LEADER_LEVEL));
200 assert!(can_assign_role("contributor", LEADER_LEVEL));
201 assert!(can_assign_role("contributor", MODERATOR_LEVEL));
203 assert!(!can_assign_role("moderator", MODERATOR_LEVEL));
204 assert!(!can_assign_role("leader", MODERATOR_LEVEL));
205 assert!(!can_assign_role("unknown", LEADER_LEVEL));
207 }
208}
209
210