Practice/Stripe/RBAC Role Resolver
CodingMust
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 = [ {"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"} ] `
The problem is divided into four progressive parts:
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: []
Extend your implementation so that getUserRoles also includes roles the user has been assigned at any ancestor account (parent, grandparent, etc.).
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) `
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).
` accounts = [ {"accountId": "org_1", "parent": None}, {"accountId": "wksp_1", "parent": "org_1"}, {"accountId": "wksp_2", "parent": "org_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"} ]
rbac = RBACRoleResolver(accounts, user_role_assignments) rbac.getUsersForAccount("org_1") # Returns: ["usr_1"] rbac.getUsersForAccount("wksp_1") # Returns: ["usr_1", "usr_2", "usr_3"] rbac.getUsersForAccount("wksp_2") # Returns: ["usr_1"] `
Extend getUsersForAccount into a new method getUsersForAccountWithFilter that only returns users who have all the specified roles (either directly or through inheritance).
` accounts = [ {"accountId": "org_1", "parent": None}, {"accountId": "wksp_1", "parent": "org_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": "editor"}, {"userId": "usr_3", "accountId": "wksp_1", "role": "viewer"} ]
rbac = RBACRoleResolver(accounts, user_role_assignments)
rbac.getUsersForAccountWithFilter("wksp_1", [])
rbac.getUsersForAccountWithFilter("wksp_1", ["admin"])
rbac.getUsersForAccountWithFilter("wksp_1", ["admin", "editor"])
rbac.getUsersForAccountWithFilter("wksp_1", ["superadmin"])
`
getUsersForAccount to get all candidate usersgetUserRoles