diff --git a/api/role.py b/api/role.py index 7bf961b..c5ef7fb 100644 --- a/api/role.py +++ b/api/role.py @@ -10,27 +10,32 @@ from typing import Optional from fastapi import APIRouter, Depends, Path, Query, Request from fastapi.responses import JSONResponse +from annotation.auth import Auth from annotation.log import Log from config.constant import BusinessType, RedisKeyConfig from controller.login import LoginController from models import Role, Permission, RolePermission, Department -from schemas.common import BaseResponse +from schemas.common import BaseResponse, DeleteListParams from schemas.role import AddRoleParams, AddRolePermissionParams, GetRolePermissionInfoResponse, \ GetRolePermissionListResponse from utils.common import filterKeyValues from utils.response import Response roleAPI = APIRouter( - prefix="/role", - dependencies=[Depends(LoginController.get_current_user)] + prefix="/role" ) @roleAPI.post("/add", response_model=BaseResponse, response_class=JSONResponse, summary="新增角色") @Log(title="新增角色", business_type=BusinessType.INSERT) -async def add_role(request: Request, params: AddRoleParams): +@Auth(permission_list=["role:btn:add"]) +async def add_role(request: Request, params: AddRoleParams, + current_user: dict = Depends(LoginController.get_current_user)): if await Role.get_or_none(code=params.role_code, department_id=params.department_id, del_flag=1): return Response.error(msg="角色编码已存在!") + sub_departments = current_user.get("sub_departments") + if params.department_id not in sub_departments: + return Response.error(msg="新增失败,无权限!") department = await Department.get_or_none(id=params.department_id, del_flag=1) if department: role = await Role.create( @@ -49,6 +54,14 @@ async def add_role(request: Request, params: AddRoleParams): department_id=None, ) if role: + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) return Response.success(msg="新增角色成功!") return Response.error(msg="新增角色失败!") @@ -56,19 +69,60 @@ async def add_role(request: Request, params: AddRoleParams): @roleAPI.delete("/delete/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="删除角色") @roleAPI.post("/delete/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="删除角色") @Log(title="删除角色", business_type=BusinessType.DELETE) -async def delete_role(request: Request, id: int = Path(..., description="角色ID")): - if role := await Role.get_or_none(id=id, del_flag=1): +@Auth(permission_list=["role:btn:delete"]) +async def delete_role(request: Request, id: int = Path(..., description="角色ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if role := await Role.get_or_none(id=id, department__id__in=sub_departments, del_flag=1): # 移除相应角色权限 - await RolePermission.filter(role_id=role.id).delete() - await role.delete() + await RolePermission.filter(role_id=role.id, del_flag=1).update(del_flag=0) + role.del_flag = 0 + await role.save() + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) return Response.success(msg="删除角色成功!") return Response.error(msg="删除角色失败!") +@roleAPI.delete("/deleteList", response_model=BaseResponse, response_class=JSONResponse, summary="批量删除角色") +@roleAPI.post("/deleteList", response_model=BaseResponse, response_class=JSONResponse, summary="批量删除角色") +@Log(title="批量删除角色", business_type=BusinessType.DELETE) +@Auth(permission_list=["role:btn:delete"]) +async def delete_role_list(request: Request, params: DeleteListParams, + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + for id in set(params.ids): + if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments): + # 移除相应角色权限 + await RolePermission.filter(role_id=role.id, del_flag=1).update(del_flag=0) + role.del_flag = 0 + await role.save() + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) + return Response.success(msg="批量删除角色成功!") + + @roleAPI.put("/update/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="修改角色") @roleAPI.post("/update/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="修改角色") @Log(title="修改角色", business_type=BusinessType.UPDATE) -async def update_role(request: Request, params: AddRoleParams, id: str = Path(..., description="角色ID")): +@Auth(permission_list=["role:btn:update"]) +async def update_role(request: Request, params: AddRoleParams, id: str = Path(..., description="角色ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if params.department_id not in sub_departments: + return Response.error(msg="修改失败,无权限!") if role := await Role.get_or_none(id=id, del_flag=1): role.code = params.code role.name = params.name @@ -80,14 +134,25 @@ async def update_role(request: Request, params: AddRoleParams, id: str = Path(.. else: role.department_id = None await role.save() + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) return Response.success(msg="修改角色成功!") return Response.error(msg="修改角色失败!") @roleAPI.get("/info/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="查询角色详情") @Log(title="查询角色详情", business_type=BusinessType.SELECT) -async def get_role_info(request: Request, id: int = Path(..., description="角色ID")): - if role := await Role.get_or_none(id=id, del_flag=1).values( +@Auth(permission_list=["role:btn:info"]) +async def get_role_info(request: Request, id: int = Path(..., description="角色ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments).values( id="id", create_by="create_by", create_time="create_time", @@ -109,6 +174,7 @@ async def get_role_info(request: Request, id: int = Path(..., description="角 @roleAPI.get("/list", response_model=BaseResponse, response_class=JSONResponse, summary="查询角色列表") @Log(title="查询角色列表", business_type=BusinessType.SELECT) +@Auth(permission_list=["role:btn:list"]) async def get_role_list( request: Request, page: int = Query(1, description="页码"), @@ -128,76 +194,12 @@ async def get_role_list( "status": status }.items() if v } - # 如果未提供 department_id,则使用当前用户的部门 ID if not department_id: - department_id = current_user.get("department_id") - - # 查询当前部门及其下属部门的角色 - all_roles = await get_role_and_subroles(department_id, filterArgs) - - # 分页处理 - total = len(all_roles) - paginated_roles = all_roles[(page - 1) * pageSize: page * pageSize] - - return Response.success(data={ - "result": paginated_roles, - "total": total, - "page": page - }) - - -async def get_department_and_subdepartments(department_id: str, visited: set = None): - """ - 递归查询当前部门及其所有下属部门的 ID。 - - :param department_id: 当前部门 ID - :param visited: 已访问的部门 ID 集合,用于避免循环依赖 - :return: 部门 ID 列表 - """ - if visited is None: - visited = set() # 初始化已访问的部门 ID 集合 - - # 如果当前部门 ID 已经访问过,直接返回空列表,避免死循环 - if department_id in visited: - return [] - - visited.add(department_id) # 标记当前部门 ID 为已访问 - - # 查询当前部门 - current_department = await Department.filter( - id=department_id - ).values_list("id", flat=True) - - # 查询直接子部门 - sub_departments = await Department.filter( - parent_id=department_id - ).values_list("id", flat=True) - - # 递归查询子部门的子部门 - for sub_department_id in sub_departments[:]: # 使用切片复制避免修改迭代中的列表 - sub_sub_departments = await get_department_and_subdepartments(sub_department_id, visited) - sub_departments.extend(sub_sub_departments) - - # 合并当前部门和所有下属部门的 ID - return current_department + sub_departments - - -async def get_role_and_subroles(department_id: str, filterArgs: dict): - """ - 查询当前部门及其下属部门的角色。 - - :param department_id: 当前部门 ID - :param filterArgs: 过滤条件 - :return: 角色列表 - """ - # 递归查询当前部门及其下属部门的 ID - department_ids = await get_department_and_subdepartments(department_id) - - # 查询这些部门的角色 - roles = await Role.filter( - department__id__in=department_ids, - **filterArgs - ).values( + filterArgs["department__id__in"] = current_user.get("sub_departments") + total = await Role.filter(**filterArgs, del_flag=1).count() + data = await Role.filter(**filterArgs, del_flag=1).offset( + (page - 1) * pageSize).limit( + pageSize).values( id="id", create_by="create_by", create_time="create_time", @@ -214,24 +216,24 @@ async def get_role_and_subroles(department_id: str, filterArgs: dict): department_email="department__email", ) - # 根据 id 去重 - unique_roles = [] - seen_ids = set() # 用于记录已经处理过的角色 ID - for role in roles: - if role["id"] not in seen_ids: - unique_roles.append(role) - seen_ids.add(role["id"]) - - return unique_roles + return Response.success(data={ + "result": data, + "total": total, + "page": page, + "pageSize": pageSize + }) @roleAPI.post("/addPermission", response_model=BaseResponse, response_class=JSONResponse, summary="新增角色权限") @Log(title="新增角色权限", business_type=BusinessType.INSERT) +@Auth(permission_list=["role:btn:addPermission"]) async def add_role_permission(request: Request, params: AddRolePermissionParams, - id: str = Path(..., description="角色ID")): - if role := await Role.get_or_none(id=id, del_flag=1): + id: str = Path(..., description="角色ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments): # 已有角色权限 - rolePermissions = await RolePermission.filter(role_id=id).all().values("permission_id") + rolePermissions = await RolePermission.filter(role_id=id, del_flag=1).values("permission_id") rolePermissions = await filterKeyValues(rolePermissions, "permission_id") # 利用集合筛选出角色权限中不存在的权限 add_list = set(params.permission_ids).difference(set(rolePermissions)) @@ -243,7 +245,14 @@ async def add_role_permission(request: Request, params: AddRolePermissionParams, role_id=role.id, permission_id=permission.id ) - await request.app.state.redis.delete(f'{RedisKeyConfig.USER_INFO.key}:*') + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) return Response.success(msg="新增角色权限成功!") return Response.error(msg="新增角色权限失败!") @@ -253,9 +262,21 @@ async def add_role_permission(request: Request, params: AddRolePermissionParams, @roleAPI.post("/deletePermission/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="删除角色权限") @Log(title="删除角色权限", business_type=BusinessType.DELETE) -async def delete_role_permission(request: Request, id: int = Path(..., description="角色权限ID")): - if rolePermission := await RolePermission.get_or_none(id=id, del_flag=1): - await rolePermission.delete() +@Auth(permission_list=["role:btn:deletePermission"]) +async def delete_role_permission(request: Request, id: int = Path(..., description="角色权限ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if rolePermission := await RolePermission.get_or_none(id=id, del_flag=1, role__department__id__in=sub_departments): + rolePermission.del_flag = 0 + await rolePermission.save() + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) return Response.success(msg="删除角色权限成功!") return Response.error(msg="删除角色权限失败!") @@ -264,11 +285,14 @@ async def delete_role_permission(request: Request, id: int = Path(..., descripti @roleAPI.post("/updatePermission/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="修改角色权限") @Log(title="修改角色权限", business_type=BusinessType.UPDATE) +@Auth(permission_list=["role:btn:updatePermission"]) async def update_role_permission(request: Request, params: AddRolePermissionParams, - id: str = Path(..., description="角色ID")): - if role := await Role.get_or_none(id=id, del_flag=1): + id: str = Path(..., description="角色ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if role := await Role.get_or_none(id=id, del_flag=1, department__id__in=sub_departments): # 已有角色权限 - rolePermissions = await RolePermission.filter(role_id=role.id).all().values("permission_id") + rolePermissions = await RolePermission.filter(role_id=role.id, del_flag=1).values("permission_id") rolePermissions = await filterKeyValues(rolePermissions, "permission_id") # 利用集合筛选出角色权限中不存在的权限 delete_list = set(rolePermissions).difference(set(params.permission_ids)) @@ -276,10 +300,18 @@ async def update_role_permission(request: Request, params: AddRolePermissionPara add_list = set(params.permission_ids).difference(set(rolePermissions)) # 循环删除角色权限 for item in delete_list: - await RolePermission.filter(role_id=id, permission_id=item).delete() + await RolePermission.filter(role_id=id, permission_id=item, del_flag=1).update(del_flag=0) # 循环添加角色权限 for item in add_list: await RolePermission.create(role_id=id, permission_id=item) + # 更新用户信息缓存 + userInfos = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_INFO.key}*') + if userInfos: + await request.app.state.redis.delete(*userInfos) + # 更新用户路由缓存 + userRoutes = await request.app.state.redis.keys(f'{RedisKeyConfig.USER_ROUTES.key}*') + if userRoutes: + await request.app.state.redis.delete(*userRoutes) return Response.success(msg="修改角色权限成功!") return Response.error(msg="修改角色权限失败!") @@ -287,8 +319,11 @@ async def update_role_permission(request: Request, params: AddRolePermissionPara @roleAPI.get("/permissionInfo/{id}", response_model=GetRolePermissionInfoResponse, response_class=JSONResponse, summary="获取角色权限信息") @Log(title="获取角色权限信息", business_type=BusinessType.SELECT) -async def get_role_permission_info(request: Request, id: int = Path(..., description="角色权限ID")): - if rolePermission := await RolePermission.get_or_none(id=id, del_flag=1): +@Auth(permission_list=["role:btn:permissionInfo"]) +async def get_role_permission_info(request: Request, id: int = Path(..., description="角色权限ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + if rolePermission := await RolePermission.get_or_none(id=id, del_flag=1, role__department__id__in=sub_departments): data = await rolePermission.first().values( id="id", create_by="create_by", @@ -310,9 +345,12 @@ async def get_role_permission_info(request: Request, id: int = Path(..., descrip @roleAPI.get("/permissionList/{id}", response_model=GetRolePermissionListResponse, response_class=JSONResponse, summary="获取角色权限列表") @Log(title="获取角色权限列表", business_type=BusinessType.SELECT) -async def get_role_permission_list(request: Request, id: str = Path(..., description="角色ID")): - total = await RolePermission.filter(role_id=id).count() - data = await RolePermission.filter(role_id=id).values( +@Auth(permission_list=["role:btn:permissionList"]) +async def get_role_permission_list(request: Request, id: str = Path(..., description="角色ID"), + current_user: dict = Depends(LoginController.get_current_user)): + sub_departments = current_user.get("sub_departments") + total = await RolePermission.filter(role_id=id, role__department__id__in=sub_departments, del_flag=1).count() + data = await RolePermission.filter(role_id=id, role__department__id__in=sub_departments, del_flag=1).values( id="id", create_by="create_by", create_time="create_time", @@ -330,5 +368,6 @@ async def get_role_permission_list(request: Request, id: str = Path(..., descrip return Response.success(data={ "result": data, "total": total, - "page": 1 + "page": 1, + "pageSize": 9999 }) diff --git a/api/user.py b/api/user.py index 78f7f41..c55f335 100644 --- a/api/user.py +++ b/api/user.py @@ -92,8 +92,8 @@ async def delete_user_list( ): sub_departments = current_user.get("sub_departments") for id in params.ids: - if user := await User.get_or_none(id=id, department__id__in=sub_departments,del_flag=1): - user.del_flag=0 + if user := await User.get_or_none(id=id, department__id__in=sub_departments, del_flag=1): + user.del_flag = 0 await user.save() return Response.success(msg="删除成功!") @@ -109,14 +109,14 @@ async def update_user( current_user: dict = Depends(LoginController.get_current_user) ): sub_departments = current_user.get("sub_departments") - if user := await User.get_or_none(id=id, department__id__in=sub_departments,del_flag=1): + if user := await User.get_or_none(id=id, department__id__in=sub_departments, del_flag=1): user.username = params.username user.nickname = params.nickname user.phone = params.phone user.email = params.email user.gender = params.gender user.status = params.status - if department := await Department.get_or_none(id=params.department_id,del_flag=1): + if department := await Department.get_or_none(id=params.department_id, del_flag=1): user.department = department else: user.department = None @@ -133,7 +133,7 @@ async def update_user( @Auth(["user:btn:Userinfo"]) async def get_user_info(request: Request, id: str = Path(..., description="用户ID"), current_user: dict = Depends(LoginController.get_current_user)): - if user := await User.get_or_none(id=id,del_flag=1): + if user := await User.get_or_none(id=id, del_flag=1): user = await user.first().values( id="id", create_time="create_time", @@ -182,8 +182,8 @@ async def get_user_list( } if not department_id: filterArgs['department_id__in'] = sub_departments - total = await User.filter(**filterArgs,del_flag=1).count() - result = await User.filter(**filterArgs,del_flag=1).offset((page - 1) * pageSize).limit(pageSize).values( + total = await User.filter(**filterArgs, del_flag=1).count() + result = await User.filter(**filterArgs, del_flag=1).offset((page - 1) * pageSize).limit(pageSize).values( id="id", create_time="create_time", update_time="update_time", @@ -238,7 +238,7 @@ async def delete_user_role(request: Request, id: str = Path(description="用户 current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") if userRole := await UserRole.get_or_none(id=id, del_flag=1, user__department__id__in=sub_departments): - userRole.del_flag=0 + userRole.del_flag = 0 await userRole.save() if await request.app.state.redis.get(f'{RedisKeyConfig.USER_INFO.key}:{current_user.get("id")}'): await request.app.state.redis.delete(f'{RedisKeyConfig.USER_INFO.key}:{current_user.get("id")}') @@ -271,7 +271,7 @@ async def update_user_role(request: Request, params: UpdateUserRoleParams, for role_id in deleteRoles: if userRole := await UserRole.get_or_none(user_id=params.user_id, role_id=role_id, del_flag=1, user__department__id__in=sub_departments): - userRole.del_flag=0 + userRole.del_flag = 0 await userRole.save() if await request.app.state.redis.get(f'{RedisKeyConfig.USER_INFO.key}:{params.user_id}'): await request.app.state.redis.delete(f'{RedisKeyConfig.USER_INFO.key}:{params.user_id}') @@ -339,7 +339,7 @@ async def get_user_role_list( async def get_user_permission_list(request: Request, id: str = Path(description="用户ID"), current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") - permissions = await QueryController.get_user_permissions(user_id=id,sub_departments=sub_departments) + permissions = await QueryController.get_user_permissions(user_id=id, sub_departments=sub_departments) permissions = await filterKeyValues(permissions, "id") # 获取用户角色 return Response.success(data=list(set(permissions))) @@ -353,7 +353,7 @@ async def upload_user_avatar( id: str = Path(description="用户ID"), file: UploadFile = File(...), current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") - if user := await User.get_or_none(id=id, del_flag=1,department__id__in=sub_departments): + if user := await User.get_or_none(id=id, del_flag=1, department__id__in=sub_departments): image_mimetypes = [ 'image/jpeg', 'image/png', @@ -417,7 +417,7 @@ async def upload_user_avatar( @Auth(permission_list=["user:btn:reset_password"]) async def reset_user_password(request: Request, params: ResetPasswordParams, id: str = Path(description="用户ID"), current_user: dict = Depends(LoginController.get_current_user)): - if user := await User.get_or_none(id=id,del_flag=1, department__id__in=current_user.get("sub_departments")): + if user := await User.get_or_none(id=id, del_flag=1, department__id__in=current_user.get("sub_departments")): user.password = await Password.get_password_hash(params.password) await user.save() return Response.success(msg="重置密码成功!")