Conversation
…g changes When a role is assigned to or unassigned from a user, create/delete the corresponding association_scopes_entities record so the role becomes visible to the user through RBAC scope chain traversal. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements synchronization between user_roles mutations and association_scopes_entities records. When a role is assigned to a user, a corresponding AssociationScopesEntitiesRow (USER scope → ROLE entity) is now created so the role becomes visible through the RBAC scope chain. When a role is revoked, the association record is deleted. Tests are added to verify the create/delete behaviour.
Changes:
assign_roleinPermissionDBSourcenow inserts anAssociationScopesEntitiesRowatomically alongside theUserRoleRowrevoke_roleinPermissionDBSourcenow deletes the correspondingAssociationScopesEntitiesRowwhen removing a rolemap_user_to_roleinRoleManageris updated to also create theAssociationScopesEntitiesRow, mirroring the newassign_rolebehaviour
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/ai/backend/manager/repositories/permission_controller/db_source/db_source.py |
Adds AssociationScopesEntitiesRow creation in assign_role and deletion in revoke_role |
src/ai/backend/manager/repositories/permission_controller/role_manager.py |
Updates map_user_to_role to create the AssociationScopesEntitiesRow after the UserRoleRow |
tests/unit/manager/repositories/permission_controller/test_user_role_association.py |
New test file verifying association creation on assign, deletion on revoke, correct types, and user isolation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| relation_type=RelationType.AUTO, | ||
| ), | ||
| ) | ||
|
|
There was a problem hiding this comment.
The updated map_user_to_role method now creates an AssociationScopesEntitiesRow, but this method is never called anywhere in the codebase. The user creation paths in user/db_source/db_source.py (which are the primary paths for creating user-role mappings) call execute_creator directly instead of _role_manager.map_user_to_role, meaning newly created users will not get the AssociationScopesEntitiesRow record that makes the role visible through RBAC. The change to this method will have no effect until its callers are updated to invoke it instead of execute_creator.
| await db_session.flush() |
| ) -> int: | ||
| async with db.begin_readonly_session_read_committed() as db_sess: | ||
| result = await db_sess.scalar( | ||
| sa.select(sa.func.count()).where( |
There was a problem hiding this comment.
The _count_associations helper uses sa.select(sa.func.count()).where(...) without an explicit .select_from() call. Throughout the codebase, the established convention is to always pair sa.select(sa.func.count()) with .select_from(TableRow) when counting rows (e.g., sa.select(sa.func.count()).select_from(AssociationScopesEntitiesRow).where(...)). The query happens to work because SQLAlchemy infers the table from the ORM column references in the WHERE clause, but adding .select_from(AssociationScopesEntitiesRow) explicitly before .where(...) would align with the rest of the codebase.
| sa.select(sa.func.count()).where( | |
| sa.select(sa.func.count()) | |
| .select_from(AssociationScopesEntitiesRow) | |
| .where( |
|
Closing this PR. Currently, roles are not managed as RBAC entities, and only superadmins are allowed to CRUD roles other than their own. Therefore, scope chain traversal for role-user mappings is unnecessary, and there is no need to add association_scopes_entities records for this case. |
Summary
assign_role,map_user_to_role), create anassociation_scopes_entitiesrecord (USER scope → ROLE entity) so the role becomes visible to the user through RBACrevoke_role), delete the correspondingassociation_scopes_entitiesrecordTest plan
test_assign_role_creates_association— verifies association record is createdtest_revoke_role_deletes_association— verifies association record is deletedtest_assign_role_association_has_correct_types— verifies USER scope and ROLE entity typestest_revoke_preserves_other_associations— verifies revoking one user's role doesn't affect anotherResolves BA-4811