From b6d7f154ad6566ccf68f883c97af35f159a4c060 Mon Sep 17 00:00:00 2001 From: wren <“porlong@qq.com”> Date: Thu, 30 Apr 2026 11:23:09 +0800 Subject: [PATCH] fix: enforce fine-grained read/write permissions on all rbac admin endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously only CreateRole/UpdateRole/DeleteRole checked specific permission keys. Now every endpoint enforces its corresponding permission: ListRoles/GetRoleRoutes/GetRolePermissions → rbac:roles:read ListUsers/ListRoleUsers/GetUserRoles → rbac:users:read AssignUserRoles/RevokeUserRole → rbac:user_roles:write UpdateRoleRoutes → rbac:role_routes:write SaveRolePermissions → rbac:role_permissions:write GetRoutePermissions → rbac:permissions:read --- .../services/impl/rbacAdminServiceImpl.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py index 7de5d72..b1c9703 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py @@ -152,6 +152,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def ListRoles(self, CurrentUserId: int, Page: int, PageSize: int, RoleKey: str | None, RoleName: str | None, IncludeSystem: bool) -> RoleListVO: """查询角色列表。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:roles:read") offset = max(Page - 1, 0) * PageSize filters = ["1=1"] params: dict[str, object] = {"limit": PageSize, "offset": offset} @@ -263,6 +264,8 @@ class RbacAdminServiceImpl(IRbacAdminService): async def ListUsers(self, CurrentUserId: int, Page: int, PageSize: int, Area: str | None, NickName: str | None) -> UserListVO: """查询用户列表。""" + await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:users:read") currentUser = await self._getCurrentUserContext(CurrentUserId) offset = max(Page - 1, 0) * PageSize filters = ["u.deleted_at IS NULL", "u.status = 0"] @@ -309,6 +312,8 @@ class RbacAdminServiceImpl(IRbacAdminService): async def ListRoleUsers(self, CurrentUserId: int, RoleId: int, Page: int, PageSize: int, Area: str | None, UserName: str | None) -> UserListVO: """查询指定角色下的用户列表。""" + await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:users:read") currentUser = await self._getCurrentUserContext(CurrentUserId) offset = max(Page - 1, 0) * PageSize filters = ["u.deleted_at IS NULL", "u.status = 0", "ur.role_id = :role_id"] @@ -371,6 +376,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def AssignUserRoles(self, CurrentUserId: int, UserId: int, RoleIds: list[int]) -> UserRolesVO: """为用户分配角色。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:user_roles:write") async with GetAsyncSession() as Session: await Session.execute(text("DELETE FROM user_role WHERE user_id = :user_id"), {"user_id": UserId}) for roleId in sorted(set(RoleIds)): @@ -386,6 +392,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def RevokeUserRole(self, CurrentUserId: int, UserId: int, RoleId: int) -> None: """移除用户角色。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:user_roles:write") async with GetAsyncSession() as Session: await Session.execute(text("DELETE FROM user_role WHERE user_id = :user_id AND role_id = :role_id"), {"user_id": UserId, "role_id": RoleId}) await Session.commit() @@ -393,6 +400,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def GetUserRoles(self, CurrentUserId: int, UserId: int) -> UserRolesVO: """查询用户角色。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:users:read") async with GetAsyncSession() as Session: userRow = ( await Session.execute(text("SELECT id, username FROM sso_users WHERE id = :user_id"), {"user_id": UserId}) @@ -439,6 +447,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def GetRoleRoutes(self, CurrentUserId: int, RoleId: int) -> RoleRoutesVO: """查询角色路由授权。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:roles:read") async with GetAsyncSession() as Session: routeMap = await self._ensureAdminSeeds(Session) rows = ( @@ -465,6 +474,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def UpdateRoleRoutes(self, CurrentUserId: int, RoleId: int, Body: RoleRoutesUpdateDTO) -> RoleRouteUpdateResultVO: """更新角色路由授权。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:role_routes:write") routeIds = sorted(set(Body.route_ids)) async with GetAsyncSession() as Session: await self._ensureAdminSeeds(Session) @@ -498,6 +508,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def GetRolePermissions(self, CurrentUserId: int, RoleId: int) -> RolePermissionsVO: """查询角色权限授权。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:roles:read") async with GetAsyncSession() as Session: await self._ensureAdminSeeds(Session) rows = ( @@ -519,6 +530,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def SaveRolePermissions(self, CurrentUserId: int, Body: RolePermissionsBatchDTO) -> RolePermissionsVO: """保存角色权限授权。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:role_permissions:write") async with GetAsyncSession() as Session: await self._ensureAdminSeeds(Session) permissionIds = [item.permission_id for item in Body.permissions] @@ -547,6 +559,7 @@ class RbacAdminServiceImpl(IRbacAdminService): async def GetRoutePermissions(self, CurrentUserId: int, RouteId: int) -> RoutePermissionsVO: """查询路由关联权限定义。""" await self._assertManagePermission(CurrentUserId) + await self._assertPermission(CurrentUserId, "rbac:permissions:read") async with GetAsyncSession() as Session: await self._ensureAdminSeeds(Session) routeRow = (