pub const ROLE_HIERARCHY: &[&str] =
&["public", "follower", "supporter", "contributor", "moderator", "leader"];
pub fn expand_roles(highest_roles: &[Box<str>]) -> String {
if highest_roles.is_empty() {
return String::new();
}
let mut highest_idx: Option<usize> = None;
for role in highest_roles {
if let Some(idx) = ROLE_HIERARCHY.iter().position(|&r| r == role.as_ref()) {
highest_idx = Some(highest_idx.map_or(idx, |h| h.max(idx)));
}
}
match highest_idx {
Some(idx) => ROLE_HIERARCHY[..=idx].join(","),
None => String::new(),
}
}
pub fn role_level(role: &str) -> Option<usize> {
ROLE_HIERARCHY.iter().position(|&r| r == role)
}
pub fn highest_role_level(roles: &[Box<str>]) -> usize {
roles.iter().filter_map(|r| role_level(r)).max().unwrap_or(0)
}
pub const MODERATOR_LEVEL: usize = 4;
pub const LEADER_LEVEL: usize = 5;
pub fn can_manage_member(actor_level: usize, target_level: usize) -> bool {
actor_level >= MODERATOR_LEVEL && (actor_level > target_level || actor_level == LEADER_LEVEL)
}
pub fn can_manage_member_by_roles(actor_roles: &[Box<str>], target_roles: &[Box<str>]) -> bool {
can_manage_member(highest_role_level(actor_roles), highest_role_level(target_roles))
}
pub fn can_assign_role(role: &str, actor_level: usize) -> bool {
match role_level(role) {
Some(new_level) => actor_level >= LEADER_LEVEL || new_level < actor_level,
None => false,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_expand_roles_empty() {
assert_eq!(expand_roles(&[]), "");
}
#[test]
fn test_expand_roles_single() {
assert_eq!(expand_roles(&["public".into()]), "public");
assert_eq!(expand_roles(&["follower".into()]), "public,follower");
assert_eq!(
expand_roles(&["moderator".into()]),
"public,follower,supporter,contributor,moderator"
);
assert_eq!(
expand_roles(&["leader".into()]),
"public,follower,supporter,contributor,moderator,leader"
);
}
#[test]
fn test_expand_roles_multiple() {
assert_eq!(
expand_roles(&["contributor".into(), "moderator".into()]),
"public,follower,supporter,contributor,moderator"
);
assert_eq!(
expand_roles(&["public".into(), "leader".into()]),
"public,follower,supporter,contributor,moderator,leader"
);
}
#[test]
fn test_expand_roles_unknown() {
assert_eq!(expand_roles(&["unknown".into()]), "");
assert_eq!(
expand_roles(&["unknown".into(), "contributor".into()]),
"public,follower,supporter,contributor"
);
}
#[test]
fn test_role_level() {
assert_eq!(role_level("public"), Some(0));
assert_eq!(role_level("follower"), Some(1));
assert_eq!(role_level("moderator"), Some(4));
assert_eq!(role_level("leader"), Some(5));
assert_eq!(role_level("unknown"), None);
}
#[test]
fn test_level_consts_match_hierarchy() {
assert_eq!(role_level("moderator"), Some(MODERATOR_LEVEL));
assert_eq!(role_level("leader"), Some(LEADER_LEVEL));
}
#[test]
fn test_can_manage_member() {
assert!(can_manage_member(4, 3));
assert!(!can_manage_member(4, 4));
assert!(can_manage_member(5, 5));
assert!(!can_manage_member(3, 0));
}
#[test]
fn test_highest_role_level() {
assert_eq!(highest_role_level(&[]), 0);
assert_eq!(highest_role_level(&["unknown".into()]), 0);
assert_eq!(highest_role_level(&["follower".into()]), 1);
assert_eq!(highest_role_level(&["moderator".into()]), 4);
assert_eq!(highest_role_level(&["leader".into()]), 5);
assert_eq!(highest_role_level(&["contributor".into(), "moderator".into()]), 4);
assert_eq!(highest_role_level(&["unknown".into(), "leader".into()]), 5);
}
#[test]
fn test_can_manage_member_by_roles() {
assert!(can_manage_member_by_roles(&["moderator".into()], &["contributor".into()]));
assert!(!can_manage_member_by_roles(&["moderator".into()], &["moderator".into()]));
assert!(can_manage_member_by_roles(&["leader".into()], &["leader".into()]));
assert!(!can_manage_member_by_roles(&["contributor".into()], &["public".into()]));
assert!(!can_manage_member_by_roles(&[], &["public".into()]));
assert!(can_manage_member_by_roles(
&["unknown".into(), "moderator".into()],
&["contributor".into()]
));
}
#[test]
fn test_can_assign_role() {
assert!(can_assign_role("leader", LEADER_LEVEL));
assert!(can_assign_role("moderator", LEADER_LEVEL));
assert!(can_assign_role("contributor", LEADER_LEVEL));
assert!(can_assign_role("contributor", MODERATOR_LEVEL));
assert!(!can_assign_role("moderator", MODERATOR_LEVEL));
assert!(!can_assign_role("leader", MODERATOR_LEVEL));
assert!(!can_assign_role("unknown", LEADER_LEVEL));
}
}