Design and implement a Role-Based Access Control (RBAC) system that manages user roles across a hierarchical account structure. The system must support organizations with nested workspaces, where roles can be inherited from parent accounts.
You are given two data structures:
Accounts: A list of accounts with hierarchical parent-child relationships
User Role Assignments: A list of role assignments mapping users to accounts with specific roles
` accounts = [ {"accountId": "org_1", "parent": None}, {"accountId": "wksp_1", "parent": "org_1"}, {"accountId": "wksp_2", "parent": "org_1"}, {"accountId": "team_1", "parent": "wksp_1"} ]
user_role_assignments = [ {"userId": "usr_1", "accountId": "org_1", "role": "admin"}, {"userId": "usr_2", "accountId": "wksp_1", "role": "editor"}, {"userId": "usr_3", "accountId": "wksp_1", "role": "viewer"}, {"userId": "usr_1", "accountId": "wksp_2", "role": "editor"} ] `
Each account can have at most one parent (tree structure)
There are no cycles in the hierarchy
The hierarchy is limited to at most 3 levels (e.g., org, workspace, team)
Roles assigned at a parent level are inherited by all descendant accounts
The problem is divided into four progressive parts:
Part 1: Basic role lookup (direct assignment only)
Part 2: Role inheritance from ancestor accounts
Part 3: Find all users who have access to an account
Part 4: Filter users by required roles
There are multiple parts to this problem -- ask the interviewer how many parts there are to better manage your time
Start with the simplest data structure and extend it as parts get more complex
Write your own test cases and ensure your code compiles and runs correctly
Implement a class RBACRoleResolver that can look up all roles directly assigned to a user for a specific account. Do not consider inheritance in this part.
rbac = RBACRoleResolver(accounts, user_role_assignments) rbac.getUserRoles("usr_1", "org_1") # Returns: ["admin"] rbac.getUserRoles("usr_1", "wksp_2") # Returns: ["editor"] rbac.getUserRoles("usr_2", "wksp_1") # Returns: ["editor"] rbac.getUserRoles("usr_3", "org_1") # Returns: []
Parse accounts and assignments in the constructor
Store role assignments in a structure that supports O(1) lookup by (userId, accountId)
Return an empty list for unknown user/account pairs
Should the returned roles be in any particular order?
Can a user have multiple roles on the same account?
Are role names case-sensitive?
Should we return an empty list or raise an error for unknown users/accounts?
A user inherits all roles from ancestor accounts. For example, if a user is an admin at the organization level, they are also an admin at all workspaces and teams under that organization.
` accounts = [ {"accountId": "org_1", "parent": None}, {"accountId": "wksp_1", "parent": "org_1"}, {"accountId": "team_1", "parent": "wksp_1"} ]
user_role_assignments = [ {"userId": "usr_1", "accountId": "org_1", "role": "admin"}, {"userId": "usr_1", "accountId": "wksp_1", "role": "editor"}, {"userId": "usr_2", "accountId": "wksp_1", "role": "viewer"} ]
rbac = RBACRoleResolver(accounts, user_role_assignments) rbac.getUserRoles("usr_1", "org_1") # Returns: ["admin"] rbac.getUserRoles("usr_1", "wksp_1") # Returns: ["admin", "editor"] rbac.getUserRoles("usr_1", "team_1") # Returns: ["admin", "editor"] (inherited) rbac.getUserRoles("usr_2", "team_1") # Returns: ["viewer"] (inherited from wksp_1) rbac.getUserRoles("usr_2", "org_1") # Returns: [] (no role at org level) `
Traverse from the given account up through its ancestors
Collect all roles assigned at each ancestor account
Return the combined set of direct and inherited roles
What is the time complexity of your getUserRoles function?
How would you optimize for repeated queries on the same user/account?
What data structures are you using and why?
Implement a method getUsersForAccount that returns all users who have access to a given account. This includes users with direct role assignments and users who have roles on any ancestor account (and thus inherit access).
Extend getUsersForAccount into a new method getUsersForAccountWithFilter that only returns users who have all the specified roles (either directly or through inheritance).