MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / check_inheritance_chain

Function check_inheritance_chain

nodedb/src/control/security/role.rs:336–376  ·  view source on GitHub ↗

Walk the inheritance chain starting from `start_name` upward through the given `roles` map. Returns the chain length (number of hops including `start_name` itself). If the chain is a cycle or exceeds `MAX_ROLE_INHERITANCE_DEPTH`, returns the corresponding error. This is the single authoritative write-time check — both `create_role` and `prepare_role` call it so the guarantee holds for every catal

(
    proposed_child: &str,
    proposed_parent: &str,
    roles: &HashMap<String, CustomRole>,
)

Source from the content-addressed store, hash-verified

334/// This is the single authoritative write-time check — both `create_role` and
335/// `prepare_role` call it so the guarantee holds for every catalog mutation path.
336fn check_inheritance_chain(
337 proposed_child: &str,
338 proposed_parent: &str,
339 roles: &HashMap<String, CustomRole>,
340) -> crate::Result<()> {
341 // Walk upward from the proposed parent. If we encounter `proposed_child`
342 // we have a cycle. If we exceed MAX_ROLE_INHERITANCE_DEPTH hops we stop.
343 let mut current = proposed_parent;
344 // depth counts the total chain: proposed_child (1) + proposed_parent (2) + ancestors.
345 let mut depth: usize = 2;
346
347 loop {
348 if current == proposed_child {
349 return Err(crate::Error::RoleInheritanceCycle {
350 child: proposed_child.to_string(),
351 parent: proposed_parent.to_string(),
352 });
353 }
354 if depth > MAX_ROLE_INHERITANCE_DEPTH {
355 return Err(crate::Error::RoleInheritanceDepthExceeded {
356 depth,
357 limit: MAX_ROLE_INHERITANCE_DEPTH,
358 });
359 }
360 // Built-in roles have no further parents; chain ends here.
361 if is_builtin(current) {
362 break;
363 }
364 match roles.get(current) {
365 Some(role) => match &role.parent {
366 Some(parent_name) => {
367 current = parent_name.as_str();
368 depth += 1;
369 }
370 None => break,
371 },
372 None => break,
373 }
374 }
375 Ok(())
376}
377
378/// Validate that `parent_name` refers to an existing role (built-in or
379/// custom) and that adopting it as `child_name`'s parent does not create a

Callers 3

validate_parentFunction · 0.85

Calls 4

is_builtinFunction · 0.85
to_stringMethod · 0.80
getMethod · 0.45
as_strMethod · 0.45

Tested by 1