use std::sync::Once;
use super::Role;
static EXTERNAL_SUPERUSER_WARNING: Once = Once::new();
pub fn roles_from_external_claims(role_names: &[String], asserted_superuser: bool) -> Vec<Role> {
let mut stripped_superuser = asserted_superuser;
let roles = role_names
.iter()
.filter_map(|name| {
let role = parse_role_infallible(name);
if matches!(role, Role::Superuser) {
stripped_superuser = true;
None
} else {
Some(role)
}
})
.collect();
if stripped_superuser {
EXTERNAL_SUPERUSER_WARNING.call_once(|| {
tracing::warn!(
"ignored superuser authority asserted by an external identity source; grant superuser through NodeDB credential administration"
);
});
}
roles
}
fn parse_role_infallible(name: &str) -> Role {
match name.parse::<Role>() {
Ok(role) => role,
Err(never) => match never {},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strips_both_superuser_representations_and_preserves_other_roles() {
let roles = roles_from_external_claims(
&["superuser".into(), "readwrite".into(), "custom".into()],
true,
);
assert!(!roles.contains(&Role::Superuser));
assert!(roles.contains(&Role::ReadWrite));
assert!(roles.contains(&Role::Custom("custom".into())));
}
}