Report oper tier by capability so a sub-floor grant isnt labelled a full operator
All checks were successful
CI / check (push) Successful in 4m13s
All checks were successful
CI / check (push) Successful in 4m13s
This commit is contained in:
parent
fc214ab0d3
commit
baab04203d
1 changed files with 20 additions and 5 deletions
|
|
@ -406,15 +406,21 @@ impl Privs {
|
||||||
pub fn contains(self, p: Priv) -> bool {
|
pub fn contains(self, p: Priv) -> bool {
|
||||||
self.0 & Self::bit(p) != 0
|
self.0 & Self::bit(p) != 0
|
||||||
}
|
}
|
||||||
// The named tier this set belongs to, by its highest granted privilege.
|
// The named tier this set belongs to: the highest tier gate it actually
|
||||||
|
// clears. Uses `has` (not `contains`) so the label never claims more than the
|
||||||
|
// set can do — a `suspend`- or `auspex`-only grant doesn't clear the operator
|
||||||
|
// floor, so it's reported as a limited operator, not a full one.
|
||||||
pub fn tier(self) -> &'static str {
|
pub fn tier(self) -> &'static str {
|
||||||
if self.contains(Priv::Root) {
|
if self.has(Priv::Root) {
|
||||||
"Services Root"
|
"Services Root"
|
||||||
} else if self.contains(Priv::Admin) {
|
} else if self.has(Priv::Admin) {
|
||||||
"Services Administrator"
|
"Services Administrator"
|
||||||
} else if self.any() {
|
} else if self.has(Priv::Oper) {
|
||||||
// oper, or an auspex/suspend-only grant — a (limited) operator.
|
|
||||||
"Services Operator"
|
"Services Operator"
|
||||||
|
} else if self.any() {
|
||||||
|
// Holds a privilege but not the operator floor: a view-only (auspex)
|
||||||
|
// or suspend-only grant. A real role, but narrower than a named tier.
|
||||||
|
"limited operator"
|
||||||
} else {
|
} else {
|
||||||
"not an operator"
|
"not an operator"
|
||||||
}
|
}
|
||||||
|
|
@ -2604,6 +2610,15 @@ mod tests {
|
||||||
assert!(root.has(Priv::Root) && root.has(Priv::Admin) && root.has(Priv::Oper) && root.has(Priv::Auspex));
|
assert!(root.has(Priv::Root) && root.has(Priv::Admin) && root.has(Priv::Oper) && root.has(Priv::Auspex));
|
||||||
assert_eq!(root.tier(), "Services Root");
|
assert_eq!(root.tier(), "Services Root");
|
||||||
|
|
||||||
|
// A grant below the operator floor is labelled honestly, never as a full
|
||||||
|
// operator: `tier` is the highest gate the set clears, not just any bit.
|
||||||
|
let auspex = Privs::default().with(Priv::Auspex);
|
||||||
|
assert!(auspex.has(Priv::Auspex) && !auspex.has(Priv::Oper), "auspex alone can view, not moderate");
|
||||||
|
assert_eq!(auspex.tier(), "limited operator");
|
||||||
|
let suspend = Privs::default().with(Priv::Suspend);
|
||||||
|
assert!(suspend.has(Priv::Suspend) && !suspend.has(Priv::Auspex) && !suspend.has(Priv::Oper), "suspend is a side power, not view/moderate");
|
||||||
|
assert_eq!(suspend.tier(), "limited operator");
|
||||||
|
|
||||||
assert!(!Privs::default().any(), "empty set is not an oper");
|
assert!(!Privs::default().any(), "empty set is not an oper");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue