Design a permission system that models a role hierarchy with inheritance and explicit deny rules. You must implement two query functions:
check_assigned_role(relations, assigned_roles, query_role): Determines if a user holds a given query_role, either directly or through the inheritance chain defined by relations. The user initially possesses the roles listed in assigned_roles. Each directed pair [x, y] in relations means that possessing role x also grants role y (and transitively any role y inherits).
is_denied(relations, deny_rules, user_role, target_role): Returns whether the target_role — along with any roles it inherits — denies the user_role or any role the user_role inherits. A deny entry [a, b] in deny_rules indicates that role a blocks role b. The check must propagate through the full inheritance graph for both the target and the user.
The inheritance graph may contain cycles; your implementation should handle them correctly (e.g., by tracking visited nodes).
Example 1:
Input: check_assigned_role(relations = [[1, 3], [3, 5]], assigned_roles = [1], query_role = 5)
Output: true
Explanation: Role 1 inherits 3, which inherits 5, so possessing role 1 gives role 5.
Example 2:
Input: check_assigned_role(relations = [[1, 3], [3, 5]], assigned_roles = [5], query_role = 1)
Output: false
Explanation: Inheritance only flows from an assigned role toward the roles it inherits; role 5 does not inherit anything, so the user does not have role 1.
Example 3:
Input: is_denied(relations = [[10, 20], [20, 30]], deny_rules = [[20, 30]], user_role = 30, target_role = 10)
Output: true
Explanation: Target role 10 inherits role 20, which has a deny rule against role 30. Since the user holds role 30, the target role 10 effectively denies the user.
Constraints:
relations and in deny_rules is each between 1 and 600 inclusive.[0, 600].assigned_roles list is non-empty.