From 1bd4bba2f5c90b4f7d314ccd84ba44bce11a1a2d Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Wed, 10 Jul 2024 17:11:03 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97service=E5=B1=82=E5=8F=8A?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/role_controller.py | 274 ++++++++---------- .../controller/user_controller.py | 4 +- .../module_admin/dao/dept_dao.py | 2 +- .../module_admin/dao/role_dao.py | 53 +++- .../module_admin/dao/user_dao.py | 32 +- .../module_admin/entity/vo/role_vo.py | 2 +- .../module_admin/service/role_service.py | 147 ++++++---- 7 files changed, 275 insertions(+), 239 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index a27eb91..1dd4d16 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -21,216 +21,170 @@ roleController = APIRouter(prefix='/system/role', dependencies=[Depends(LoginSer @roleController.get("/deptTree/{role_id}", dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))]) async def get_system_role_dept_tree(request: Request, role_id: int, query_db: AsyncSession = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('SysDept'))): - try: - dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(**{}), data_scope_sql) - role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id) - role_dept_query_result.depts = dept_query_result - logger.info('获取成功') - return ResponseUtil.success(model_content=role_dept_query_result) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) + dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(**{}), data_scope_sql) + role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id) + role_dept_query_result.depts = dept_query_result + logger.info('获取成功') + + return ResponseUtil.success(model_content=role_dept_query_result) @roleController.get("/list", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))]) -async def get_system_role_list(request: Request, role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_query), query_db: AsyncSession = Depends(get_db)): - try: - role_page_query_result = await RoleService.get_role_list_services(query_db, role_page_query, is_page=True) - logger.info('获取成功') - return ResponseUtil.success(model_content=role_page_query_result) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def get_system_role_list(request: Request, role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_query), query_db: AsyncSession = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('role_query.columns'))): + role_page_query_result = await RoleService.get_role_list_services(query_db, role_page_query, data_scope_sql, is_page=True) + logger.info('获取成功') + + return ResponseUtil.success(model_content=role_page_query_result) @roleController.post("", dependencies=[Depends(CheckUserInterfaceAuth('system:role:add'))]) @ValidateFields(validate_model='add_role') @log_decorator(title='角色管理', business_type=BusinessType.INSERT) async def add_system_role(request: Request, add_role: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)): - try: - add_role.create_by = current_user.user.user_name - add_role.create_time = datetime.now() - add_role.update_by = current_user.user.user_name - add_role.update_time = datetime.now() - add_role_result = await RoleService.add_role_services(query_db, add_role) - if add_role_result.is_success: - logger.info(add_role_result.message) - return ResponseUtil.success(msg=add_role_result.message) - else: - logger.warning(add_role_result.message) - return ResponseUtil.failure(msg=add_role_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) + add_role.create_by = current_user.user.user_name + add_role.create_time = datetime.now() + add_role.update_by = current_user.user.user_name + add_role.update_time = datetime.now() + add_role_result = await RoleService.add_role_services(query_db, add_role) + logger.info(add_role_result.message) + + return ResponseUtil.success(msg=add_role_result.message) @roleController.put("", dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @ValidateFields(validate_model='edit_role') @log_decorator(title='角色管理', business_type=BusinessType.UPDATE) -async def edit_system_role(request: Request, edit_role: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)): - try: - edit_role.update_by = current_user.user.user_name - edit_role.update_time = datetime.now() - edit_role_result = await RoleService.edit_role_services(query_db, edit_role) - if edit_role_result.is_success: - logger.info(edit_role_result.message) - return ResponseUtil.success(msg=edit_role_result.message) - else: - logger.warning(edit_role_result.message) - return ResponseUtil.failure(msg=edit_role_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def edit_system_role(request: Request, edit_role: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), data_scope_sql: str = Depends(GetDataScope('role_query'))): + await RoleService.check_role_allowed_services(edit_role) + if not current_user.user.admin: + await RoleService.check_role_data_scope_services(query_db, edit_role.role_id, data_scope_sql) + edit_role.update_by = current_user.user.user_name + edit_role.update_time = datetime.now() + edit_role_result = await RoleService.edit_role_services(query_db, edit_role) + logger.info(edit_role_result.message) + + return ResponseUtil.success(msg=edit_role_result.message) @roleController.put("/dataScope", dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @log_decorator(title='角色管理', business_type=BusinessType.GRANT) -async def edit_system_role_datascope(request: Request, role_data_scope: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)): - try: - role_data_scope.update_by = current_user.user.user_name - role_data_scope.update_time = datetime.now() - role_data_scope_result = await RoleService.role_datascope_services(query_db, role_data_scope) - if role_data_scope_result.is_success: - logger.info(role_data_scope_result.message) - return ResponseUtil.success(msg=role_data_scope_result.message) - else: - logger.warning(role_data_scope_result.message) - return ResponseUtil.failure(msg=role_data_scope_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def edit_system_role_datascope(request: Request, role_data_scope: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), data_scope_sql: str = Depends(GetDataScope('role_query'))): + await RoleService.check_role_allowed_services(role_data_scope) + if not current_user.user.admin: + await RoleService.check_role_data_scope_services(query_db, role_data_scope.role_id, data_scope_sql) + edit_role = AddRoleModel( + roleId=role_data_scope.role_id, + dataScope=role_data_scope.data_scope, + deptIds=role_data_scope.dept_ids, + deptCheckStrictly=role_data_scope.dept_check_strictly, + updateBy=current_user.user.user_name, + updateTime=datetime.now() + ) + role_data_scope_result = await RoleService.role_datascope_services(query_db, edit_role) + logger.info(role_data_scope_result.message) + + return ResponseUtil.success(msg=role_data_scope_result.message) @roleController.delete("/{role_ids}", dependencies=[Depends(CheckUserInterfaceAuth('system:role:remove'))]) @log_decorator(title='角色管理', business_type=BusinessType.DELETE) -async def delete_system_role(request: Request, role_ids: str, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)): - try: - delete_role = DeleteRoleModel( - roleIds=role_ids, - updateBy=current_user.user.user_name, - updateTime=datetime.now() - ) - delete_role_result = await RoleService.delete_role_services(query_db, delete_role) - if delete_role_result.is_success: - logger.info(delete_role_result.message) - return ResponseUtil.success(msg=delete_role_result.message) - else: - logger.warning(delete_role_result.message) - return ResponseUtil.failure(msg=delete_role_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def delete_system_role(request: Request, role_ids: str, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), data_scope_sql: str = Depends(GetDataScope('role_query'))): + role_id_list = role_ids.split(',') + for role_id in role_id_list: + await RoleService.check_role_allowed_services(RoleModel(roleId=int(role_id))) + if not current_user.user.admin: + await RoleService.check_role_data_scope_services(query_db, int(role_id), data_scope_sql) + delete_role = DeleteRoleModel( + roleIds=role_ids, + updateBy=current_user.user.user_name, + updateTime=datetime.now() + ) + delete_role_result = await RoleService.delete_role_services(query_db, delete_role) + logger.info(delete_role_result.message) + + return ResponseUtil.success(msg=delete_role_result.message) @roleController.get("/{role_id}", response_model=RoleModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))]) -async def query_detail_system_role(request: Request, role_id: int, query_db: AsyncSession = Depends(get_db)): - try: - role_detail_result = await RoleService.role_detail_services(query_db, role_id) - logger.info(f'获取role_id为{role_id}的信息成功') - return ResponseUtil.success(data=role_detail_result.model_dump(by_alias=True)) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def query_detail_system_role(request: Request, role_id: int, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), data_scope_sql: str = Depends(GetDataScope('role_query'))): + if not current_user.user.admin: + await RoleService.check_role_data_scope_services(query_db, role_id, data_scope_sql) + role_detail_result = await RoleService.role_detail_services(query_db, role_id) + logger.info(f'获取role_id为{role_id}的信息成功') + + return ResponseUtil.success(data=role_detail_result.model_dump(by_alias=True)) @roleController.post("/export", dependencies=[Depends(CheckUserInterfaceAuth('system:role:export'))]) @log_decorator(title='角色管理', business_type=BusinessType.EXPORT) -async def export_system_role_list(request: Request, role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_form), query_db: AsyncSession = Depends(get_db)): - try: - # 获取全量数据 - role_query_result = await RoleService.get_role_list_services(query_db, role_page_query, is_page=False) - role_export_result = await RoleService.export_role_list_services(role_query_result) - logger.info('导出成功') - return ResponseUtil.streaming(data=bytes2file_response(role_export_result)) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def export_system_role_list(request: Request, role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_form), query_db: AsyncSession = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('role_query'))): + # 获取全量数据 + role_query_result = await RoleService.get_role_list_services(query_db, role_page_query, data_scope_sql, is_page=False) + role_export_result = await RoleService.export_role_list_services(role_query_result) + logger.info('导出成功') + + return ResponseUtil.streaming(data=bytes2file_response(role_export_result)) @roleController.put("/changeStatus", dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @log_decorator(title='角色管理', business_type=BusinessType.UPDATE) -async def reset_system_role_status(request: Request, edit_role: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)): - try: - edit_role.update_by = current_user.user.user_name - edit_role.update_time = datetime.now() - edit_role.type = 'status' - edit_role_result = await RoleService.edit_role_services(query_db, edit_role) - if edit_role_result.is_success: - logger.info(edit_role_result.message) - return ResponseUtil.success(msg=edit_role_result.message) - else: - logger.warning(edit_role_result.message) - return ResponseUtil.failure(msg=edit_role_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def reset_system_role_status(request: Request, change_role: AddRoleModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), data_scope_sql: str = Depends(GetDataScope('role_query'))): + await RoleService.check_role_allowed_services(change_role) + if not current_user.user.admin: + await RoleService.check_role_data_scope_services(query_db, change_role.role_id, data_scope_sql) + edit_role = AddRoleModel( + roleId=change_role.role_id, + status=change_role.status, + updateBy=current_user.user.user_name, + updateTime=datetime.now(), + type='status' + ) + edit_role_result = await RoleService.edit_role_services(query_db, edit_role) + logger.info(edit_role_result.message) + + return ResponseUtil.success(msg=edit_role_result.message) @roleController.get("/authUser/allocatedList", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))]) -async def get_system_allocated_user_list(request: Request, user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), query_db: AsyncSession = Depends(get_db)): - try: - role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services(query_db, user_role, is_page=True) - logger.info('获取成功') - return ResponseUtil.success(model_content=role_user_allocated_page_query_result) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def get_system_allocated_user_list(request: Request, user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), query_db: AsyncSession = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('SysUser'))): + role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services(query_db, user_role, data_scope_sql, is_page=True) + logger.info('获取成功') + + return ResponseUtil.success(model_content=role_user_allocated_page_query_result) @roleController.get("/authUser/unallocatedList", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))]) -async def get_system_unallocated_user_list(request: Request, user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), query_db: AsyncSession = Depends(get_db)): - try: - role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services(query_db, user_role, is_page=True) - logger.info('获取成功') - return ResponseUtil.success(model_content=role_user_unallocated_page_query_result) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def get_system_unallocated_user_list(request: Request, user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), query_db: AsyncSession = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('SysUser'))): + role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services(query_db, user_role, data_scope_sql, is_page=True) + logger.info('获取成功') + + return ResponseUtil.success(model_content=role_user_unallocated_page_query_result) @roleController.put("/authUser/selectAll", dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @log_decorator(title='角色管理', business_type=BusinessType.GRANT) -async def add_system_role_user(request: Request, add_role_user: CrudUserRoleModel = Depends(CrudUserRoleModel.as_query), query_db: AsyncSession = Depends(get_db)): - try: - add_role_user_result = await UserService.add_user_role_services(query_db, add_role_user) - if add_role_user_result.is_success: - logger.info(add_role_user_result.message) - return ResponseUtil.success(msg=add_role_user_result.message) - else: - logger.warning(add_role_user_result.message) - return ResponseUtil.failure(msg=add_role_user_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) +async def add_system_role_user(request: Request, add_role_user: CrudUserRoleModel = Depends(CrudUserRoleModel.as_query), query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), data_scope_sql: str = Depends(GetDataScope('role_query'))): + if not current_user.user.admin: + await RoleService.check_role_data_scope_services(query_db, add_role_user.role_id, data_scope_sql) + add_role_user_result = await UserService.add_user_role_services(query_db, add_role_user) + logger.info(add_role_user_result.message) + + return ResponseUtil.success(msg=add_role_user_result.message) @roleController.put("/authUser/cancel", dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @log_decorator(title='角色管理', business_type=BusinessType.GRANT) async def cancel_system_role_user(request: Request, cancel_user_role: CrudUserRoleModel, query_db: AsyncSession = Depends(get_db)): - try: - cancel_user_role_result = await UserService.delete_user_role_services(query_db, cancel_user_role) - if cancel_user_role_result.is_success: - logger.info(cancel_user_role_result.message) - return ResponseUtil.success(msg=cancel_user_role_result.message) - else: - logger.warning(cancel_user_role_result.message) - return ResponseUtil.failure(msg=cancel_user_role_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) + cancel_user_role_result = await UserService.delete_user_role_services(query_db, cancel_user_role) + logger.info(cancel_user_role_result.message) + + return ResponseUtil.success(msg=cancel_user_role_result.message) @roleController.put("/authUser/cancelAll", dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @log_decorator(title='角色管理', business_type=BusinessType.GRANT) async def batch_cancel_system_role_user(request: Request, batch_cancel_user_role: CrudUserRoleModel = Depends(CrudUserRoleModel.as_query), query_db: AsyncSession = Depends(get_db)): - try: - batch_cancel_user_role_result = await UserService.delete_user_role_services(query_db, batch_cancel_user_role) - if batch_cancel_user_role_result.is_success: - logger.info(batch_cancel_user_role_result.message) - return ResponseUtil.success(msg=batch_cancel_user_role_result.message) - else: - logger.warning(batch_cancel_user_role_result.message) - return ResponseUtil.failure(msg=batch_cancel_user_role_result.message) - except Exception as e: - logger.exception(e) - return ResponseUtil.error(msg=str(e)) + batch_cancel_user_role_result = await UserService.delete_user_role_services(query_db, batch_cancel_user_role) + logger.info(batch_cancel_user_role_result.message) + + return ResponseUtil.success(msg=batch_cancel_user_role_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index cbe510c..c79c1cb 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -76,9 +76,9 @@ async def delete_system_user(request: Request, user_ids: str, query_db: AsyncSes return ResponseUtil.failure(msg='当前登录用户不能删除') for user_id in user_id_list: + await UserService.check_user_allowed_services(UserModel(userId=int(user_id))) if not current_user.user.admin: - await UserService.check_user_allowed_services(UserModel(userId=int(user_id))) - await UserService.check_user_data_scope_services(query_db, int(user_id), data_scope_sql) + await UserService.check_user_data_scope_services(query_db, int(user_id), data_scope_sql) delete_user = DeleteUserModel( userIds=user_ids, updateBy=current_user.user.user_name, diff --git a/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py b/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py index e15278b..44a2f20 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py @@ -1,4 +1,4 @@ -from sqlalchemy import select, update, delete +from sqlalchemy import select, update, delete, or_, func from sqlalchemy.ext.asyncio import AsyncSession from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.role_do import SysRoleDept diff --git a/ruoyi-fastapi-backend/module_admin/dao/role_dao.py b/ruoyi-fastapi-backend/module_admin/dao/role_dao.py index 1d5a1fa..b65b4a1 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/role_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/role_dao.py @@ -1,5 +1,6 @@ -from sqlalchemy import select, update, delete, desc, func +from sqlalchemy import select, update, delete, desc, and_, or_, func from sqlalchemy.ext.asyncio import AsyncSession +from module_admin.entity.do.user_do import SysUser, SysUserRole from module_admin.entity.do.role_do import SysRole, SysRoleMenu, SysRoleDept from module_admin.entity.do.dept_do import SysDept from module_admin.entity.vo.role_vo import * @@ -96,15 +97,19 @@ class RoleDao: return role_info @classmethod - async def get_role_list(cls, db: AsyncSession, query_object: RolePageQueryModel, is_page: bool = False): + async def get_role_list(cls, db: AsyncSession, query_object: RolePageQueryModel, data_scope_sql: str, is_page: bool = False): """ 根据查询参数获取角色列表信息 :param db: orm对象 :param query_object: 查询参数对象 + :param data_scope_sql: 数据权限对应的查询sql语句 :param is_page: 是否开启分页 :return: 角色列表信息对象 """ - query = select(SysRole) \ + role_query = (select(SysRole, SysUser.user_id, SysDept.dept_id) + .join(SysUserRole, SysUserRole.role_id == SysRole.role_id, isouter=True) + .join(SysUser, SysUser.user_id == SysUserRole.user_id, isouter=True) + .join(SysDept, SysDept.dept_id == SysUser.dept_id, isouter=True) .where(SysRole.del_flag == '0', SysRole.role_name.like(f'%{query_object.role_name}%') if query_object.role_name else True, SysRole.role_key.like(f'%{query_object.role_key}%') if query_object.role_key else True, @@ -112,9 +117,12 @@ class RoleDao: SysRole.create_time.between( datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(00, 00, 00)), datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59))) - if query_object.begin_time and query_object.end_time else True) \ - .order_by(SysRole.role_sort) \ - .distinct() + if query_object.begin_time and query_object.end_time else True) + .order_by(SysRole.role_sort)).subquery() + query = select(SysRole) \ + .select_from(role_query) \ + .join(SysRole, SysRole.role_id == role_query.columns.role_id) \ + .where(eval(data_scope_sql)).distinct() role_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) return role_list @@ -201,18 +209,23 @@ class RoleDao: ) @classmethod - async def get_role_dept_dao(cls, db: AsyncSession, role_id: int): + async def get_role_dept_dao(cls, db: AsyncSession, role: RoleModel): """ 根据角色id获取角色部门关联列表信息 :param db: orm对象 - :param role_id: 角色id + :param role: 角色对象 :return: 角色部门关联列表信息 """ role_dept_query_all = (await db.execute( - select(SysRoleDept) - .where(SysRoleDept.role_id == role_id, - ~select(SysDept).where(func.find_in_set(SysRoleDept.dept_id, SysDept.ancestors)).exists()) - .distinct() + select(SysDept) + .join(SysRoleDept, SysRoleDept.dept_id == SysDept.dept_id) + .where(SysRoleDept.role_id == role.role_id, + ~SysDept.dept_id.in_( + select(SysDept.parent_id) + .select_from(SysDept) + .join(SysRoleDept, and_(SysRoleDept.dept_id == SysDept.dept_id, SysRoleDept.role_id == role.role_id)) + ) if role.dept_check_strictly else True) + .order_by(SysDept.parent_id, SysDept.order_num) )).scalars().all() return role_dept_query_all @@ -240,3 +253,19 @@ class RoleDao: delete(SysRoleDept) .where(SysRoleDept.role_id.in_([role_dept.role_id])) ) + + @classmethod + async def count_user_role_dao(cls, db: AsyncSession, role_id: int): + """ + 根据角色id查询角色关联用户数量 + :param db: orm对象 + :param role_id: 角色id + :return: 角色关联用户数量 + """ + user_count = (await db.execute( + select(func.count('*')) + .select_from(SysUserRole) + .where(SysUserRole.role_id == role_id) + )).scalar() + + return user_count diff --git a/ruoyi-fastapi-backend/module_admin/dao/user_dao.py b/ruoyi-fastapi-backend/module_admin/dao/user_dao.py index 76e23a4..f75deac 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/user_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/user_dao.py @@ -277,46 +277,56 @@ class UserDao: return allocated_role_list @classmethod - async def get_user_role_allocated_list_by_role_id(cls, db: AsyncSession, query_object: UserRolePageQueryModel, - is_page: bool = False): + async def get_user_role_allocated_list_by_role_id(cls, db: AsyncSession, query_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False): """ 根据角色id获取已分配的用户列表信息 :param db: orm对象 :param query_object: 用户角色查询对象 + :param data_scope_sql: 数据权限对应的查询sql语句 :param is_page: 是否开启分页 :return: 角色已分配的用户列表信息 """ query = select(SysUser) \ + .join(SysDept, SysDept.dept_id == SysUser.dept_id, isouter=True) \ + .join(SysUserRole, SysUserRole.user_id == SysUser.user_id, isouter=True) \ + .join(SysRole, SysRole.role_id == SysUserRole.role_id, isouter=True) \ .where(SysUser.del_flag == '0', - SysUser.user_id != 1, SysUser.user_name == query_object.user_name if query_object.user_name else True, SysUser.phonenumber == query_object.phonenumber if query_object.phonenumber else True, - SysUser.user_id.in_( - select(SysUserRole.user_id).where(SysUserRole.role_id == query_object.role_id) - )) \ + SysRole.role_id == query_object.role_id, + eval(data_scope_sql)) \ .distinct() allocated_user_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) return allocated_user_list @classmethod - async def get_user_role_unallocated_list_by_role_id(cls, db: AsyncSession, query_object: UserRolePageQueryModel, - is_page: bool = False): + async def get_user_role_unallocated_list_by_role_id(cls, db: AsyncSession, query_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False): """ 根据角色id获取未分配的用户列表信息 :param db: orm对象 :param query_object: 用户角色查询对象 + :param data_scope_sql: 数据权限对应的查询sql语句 :param is_page: 是否开启分页 :return: 角色未分配的用户列表信息 """ query = select(SysUser) \ + .join(SysDept, SysDept.dept_id == SysUser.dept_id, isouter=True) \ + .join(SysUserRole, SysUserRole.user_id == SysUser.user_id, isouter=True) \ + .join(SysRole, SysRole.role_id == SysUserRole.role_id, isouter=True) \ .where(SysUser.del_flag == '0', - SysUser.user_id != 1, SysUser.user_name == query_object.user_name if query_object.user_name else True, SysUser.phonenumber == query_object.phonenumber if query_object.phonenumber else True, + or_(SysRole.role_id != query_object.role_id, SysRole.role_id is None), ~SysUser.user_id.in_( - select(SysUserRole.user_id).where(SysUserRole.role_id == query_object.role_id) - )) \ + select(SysUser.user_id) + .select_from(SysUser) + .join(SysUserRole, + and_(SysUserRole.user_id == SysUser.user_id, + SysUserRole.role_id == query_object.role_id) + ) + ), + eval(data_scope_sql)) \ .distinct() unallocated_user_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py index ab809bc..aa69c3f 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py @@ -16,7 +16,7 @@ class RoleModel(BaseModel): role_name: Optional[str] = Field(default=None, description='角色名称') role_key: Optional[str] = Field(default=None, description='角色权限字符串') role_sort: Optional[int] = Field(default=None, description='显示顺序') - data_scope: Optional[Literal['1', '2', '3', '4']] = Field(default=None, description='数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)') + data_scope: Optional[Literal['1', '2', '3', '4', '5']] = Field(default=None, description='数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限)') menu_check_strictly: Optional[Union[int, bool]] = Field(default=None, description='菜单树选择项是否关联显示') dept_check_strictly: Optional[Union[int, bool]] = Field(default=None, description='部门树选择项是否关联显示') status: Optional[Literal['0', '1']] = Field(default=None, description='角色状态(0正常 1停用)') diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index 745d3db..aa0a54d 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -2,6 +2,8 @@ from module_admin.entity.vo.user_vo import UserInfoModel, UserRolePageQueryModel from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.dao.user_dao import UserDao from module_admin.dao.role_dao import * +from config.constant import CommonConstant +from exceptions.exception import ServiceException from utils.page_util import PageResponseModel from utils.common_util import export_list2excel, CamelCaseUtil @@ -30,7 +32,8 @@ class RoleService: :param role_id: 角色id :return: 当前角色id的部门树信息对象 """ - role_dept_list = await RoleDao.get_role_dept_dao(query_db, role_id) + role = await cls.role_detail_services(query_db, role_id) + role_dept_list = await RoleDao.get_role_dept_dao(query_db, role) checked_keys = [row.dept_id for row in role_dept_list] result = RoleDeptQueryModel( checkedKeys=checked_keys @@ -39,18 +42,74 @@ class RoleService: return result @classmethod - async def get_role_list_services(cls, query_db: AsyncSession, query_object: RolePageQueryModel, is_page: bool = False): + async def get_role_list_services(cls, query_db: AsyncSession, query_object: RolePageQueryModel, data_scope_sql: str, is_page: bool = False): """ 获取角色列表信息service :param query_db: orm对象 :param query_object: 查询参数对象 + :param data_scope_sql: 数据权限对应的查询sql语句 :param is_page: 是否开启分页 :return: 角色列表信息对象 """ - role_list_result = await RoleDao.get_role_list(query_db, query_object, is_page) + role_list_result = await RoleDao.get_role_list(query_db, query_object, data_scope_sql, is_page) return role_list_result + @classmethod + async def check_role_allowed_services(cls, check_role: RoleModel): + """ + 校验角色是否允许操作service + :param check_role: 角色信息 + :return: 校验结果 + """ + if check_role.admin: + raise ServiceException(message='不允许操作超级管理员角色') + else: + return CrudResponseModel(is_success=True, message='校验通过') + + @classmethod + async def check_role_data_scope_services(cls, query_db: AsyncSession, role_id: int, data_scope_sql: str): + """ + 校验角色是否有数据权限service + :param query_db: orm对象 + :param role_id: 角色id + :param data_scope_sql: 数据权限对应的查询sql语句 + :return: 校验结果 + """ + roles = await RoleDao.get_role_list(query_db, RolePageQueryModel(roleId=role_id), data_scope_sql, is_page=False) + if roles: + return CrudResponseModel(is_success=True, message='校验通过') + else: + raise ServiceException(message='没有权限访问角色数据') + + @classmethod + async def check_role_name_unique_services(cls, query_db: AsyncSession, page_object: RoleModel): + """ + 校验角色名称是否唯一service + :param query_db: orm对象 + :param page_object: 角色对象 + :return: 校验结果 + """ + role_id = -1 if page_object.role_id is None else page_object.role_id + role = await RoleDao.get_role_by_info(query_db, RoleModel(roleName=page_object.role_name)) + if role and role.role_id != role_id: + return CommonConstant.NOT_UNIQUE + return CommonConstant.UNIQUE + + @classmethod + async def check_role_key_unique_services(cls, query_db: AsyncSession, page_object: RoleModel): + """ + 校验角色权限字符是否唯一service + :param query_db: orm对象 + :param page_object: 角色对象 + :return: 校验结果 + """ + role_id = -1 if page_object.role_id is None else page_object.role_id + role = await RoleDao.get_role_by_info(query_db, RoleModel(roleKey=page_object.role_key)) + if role and role.role_id != role_id: + return CommonConstant.NOT_UNIQUE + return CommonConstant.UNIQUE + @classmethod async def add_role_services(cls, query_db: AsyncSession, page_object: AddRoleModel): """ @@ -60,12 +119,10 @@ class RoleService: :return: 新增角色校验结果 """ add_role = RoleModel(**page_object.model_dump(by_alias=True)) - role_name = await RoleDao.get_role_by_info(query_db, RoleModel(roleName=page_object.role_name)) - role_key = await RoleDao.get_role_by_info(query_db, RoleModel(roleKey=page_object.role_key)) - if role_name: - result = dict(is_success=False, message='角色名称已存在') - elif role_key: - result = dict(is_success=False, message='权限字符已存在') + if not await cls.check_role_name_unique_services(query_db, page_object): + raise ServiceException(message=f'新增角色{page_object.post_name}失败,角色名称已存在') + elif not await cls.check_role_key_unique_services(query_db, page_object): + raise ServiceException(message=f'新增角色{page_object.post_name}失败,角色权限已存在') else: try: add_result = await RoleDao.add_role_dao(query_db, add_role) @@ -74,13 +131,11 @@ class RoleService: for menu in page_object.menu_ids: await RoleDao.add_role_menu_dao(query_db, RoleMenuModel(roleId=role_id, menuId=menu)) await query_db.commit() - result = dict(is_success=True, message='新增成功') + return CrudResponseModel(is_success=True, message='新增成功') except Exception as e: await query_db.rollback() raise e - return CrudResponseModel(**result) - @classmethod async def edit_role_services(cls, query_db: AsyncSession, page_object: AddRoleModel): """ @@ -96,16 +151,11 @@ class RoleService: del edit_role['type'] role_info = await cls.role_detail_services(query_db, edit_role.get('role_id')) if role_info: - if page_object.type != 'status' and role_info.role_name != page_object.role_name: - role_name = await RoleDao.get_role_by_info(query_db, RoleModel(roleName=page_object.role_name)) - if role_name: - result = dict(is_success=False, message='角色名称已存在') - return CrudResponseModel(**result) - elif page_object.type != 'status' and role_info.role_key != page_object.role_key: - role_key = await RoleDao.get_role_by_info(query_db, RoleModel(roleKey=page_object.role_key)) - if role_key: - result = dict(is_success=False, message='权限字符已存在') - return CrudResponseModel(**result) + if page_object.type != 'status': + if not await cls.check_role_name_unique_services(query_db, page_object): + raise ServiceException(message=f'修改角色{page_object.post_name}失败,角色名称已存在') + elif not await cls.check_role_key_unique_services(query_db, page_object): + raise ServiceException(message=f'修改角色{page_object.post_name}失败,角色权限已存在') try: await RoleDao.edit_role_dao(query_db, edit_role) if page_object.type != 'status': @@ -114,14 +164,12 @@ class RoleService: for menu in page_object.menu_ids: await RoleDao.add_role_menu_dao(query_db, RoleMenuModel(roleId=page_object.role_id, menuId=menu)) await query_db.commit() - result = dict(is_success=True, message='更新成功') + return CrudResponseModel(is_success=True, message='更新成功') except Exception as e: await query_db.rollback() raise e else: - result = dict(is_success=False, message='角色不存在') - - return CrudResponseModel(**result) + raise ServiceException(message='角色不存在') @classmethod async def role_datascope_services(cls, query_db: AsyncSession, page_object: AddRoleModel): @@ -131,20 +179,9 @@ class RoleService: :param page_object: 角色数据权限对象 :return: 分配角色数据权限结果 """ - edit_role = page_object.model_dump(exclude_unset=True, exclude={'admin'}) - del edit_role['dept_ids'] - role_info = await cls.role_detail_services(query_db, edit_role.get('role_id')) - if role_info: - if role_info.role_name != page_object.role_name: - role_name = await RoleDao.get_role_by_info(query_db, RoleModel(roleName=page_object.role_name)) - if role_name: - result = dict(is_success=False, message='角色名称已存在') - return CrudResponseModel(**result) - elif role_info.role_key != page_object.role_key: - role_key = await RoleDao.get_role_by_info(query_db, RoleModel(roleKey=page_object.role_key)) - if role_key: - result = dict(is_success=False, message='权限字符已存在') - return CrudResponseModel(**result) + edit_role = page_object.model_dump(exclude_unset=True, exclude={'admin', 'dept_ids'}) + role_info = await cls.role_detail_services(query_db, page_object.role_id) + if role_info.role_id: try: await RoleDao.edit_role_dao(query_db, edit_role) await RoleDao.delete_role_dept_dao(query_db, RoleDeptModel(roleId=page_object.role_id)) @@ -152,14 +189,12 @@ class RoleService: for dept in page_object.dept_ids: await RoleDao.add_role_dept_dao(query_db, RoleDeptModel(roleId=page_object.role_id, deptId=dept)) await query_db.commit() - result = dict(is_success=True, message='分配成功') + return CrudResponseModel(is_success=True, message='分配成功') except Exception as e: await query_db.rollback() raise e else: - result = dict(is_success=False, message='角色不存在') - - return CrudResponseModel(**result) + raise ServiceException(message='角色不存在') @classmethod async def delete_role_services(cls, query_db: AsyncSession, page_object: DeleteRoleModel): @@ -173,17 +208,20 @@ class RoleService: role_id_list = page_object.role_ids.split(',') try: for role_id in role_id_list: + role = await cls.role_detail_services(query_db, int(role_id)) + if (await RoleDao.count_user_role_dao(query_db, int(role_id))) > 0: + raise ServiceException(message=f'角色{role.role_name}已分配,不能删除') role_id_dict = dict(roleId=role_id, updateBy=page_object.update_by, updateTime=page_object.update_time) await RoleDao.delete_role_menu_dao(query_db, RoleMenuModel(**role_id_dict)) + await RoleDao.delete_role_dept_dao(query_db, RoleDeptModel(**role_id_dict)) await RoleDao.delete_role_dao(query_db, RoleModel(**role_id_dict)) await query_db.commit() - result = dict(is_success=True, message='删除成功') + return CrudResponseModel(is_success=True, message='删除成功') except Exception as e: await query_db.rollback() raise e else: - result = dict(is_success=False, message='传入角色id为空') - return CrudResponseModel(**result) + raise ServiceException(message='传入角色id为空') @classmethod async def role_detail_services(cls, query_db: AsyncSession, role_id: int): @@ -194,7 +232,10 @@ class RoleService: :return: 角色id对应的信息 """ role = await RoleDao.get_role_detail_by_id(query_db, role_id=role_id) - result = RoleModel(**CamelCaseUtil.transform_result(role)) + if role: + result = RoleModel(**CamelCaseUtil.transform_result(role)) + else: + result = RoleModel(**dict()) return result @@ -232,15 +273,16 @@ class RoleService: return binary_data @classmethod - async def get_role_user_allocated_list_services(cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, is_page: bool = False): + async def get_role_user_allocated_list_services(cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False): """ 根据角色id获取已分配用户列表 :param query_db: orm对象 :param page_object: 用户关联角色对象 + :param data_scope_sql: 数据权限对应的查询sql语句 :param is_page: 是否开启分页 :return: 已分配用户列表 """ - query_user_list = await UserDao.get_user_role_allocated_list_by_role_id(query_db, page_object, is_page) + query_user_list = await UserDao.get_user_role_allocated_list_by_role_id(query_db, page_object, data_scope_sql, is_page) allocated_list = PageResponseModel( **{ **query_user_list.model_dump(by_alias=True), @@ -251,15 +293,16 @@ class RoleService: return allocated_list @classmethod - async def get_role_user_unallocated_list_services(cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, is_page: bool = False): + async def get_role_user_unallocated_list_services(cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False): """ 根据角色id获取未分配用户列表 :param query_db: orm对象 :param page_object: 用户关联角色对象 + :param data_scope_sql: 数据权限对应的查询sql语句 :param is_page: 是否开启分页 :return: 未分配用户列表 """ - query_user_list = await UserDao.get_user_role_unallocated_list_by_role_id(query_db, page_object, is_page) + query_user_list = await UserDao.get_user_role_unallocated_list_by_role_id(query_db, page_object, data_scope_sql, is_page) unallocated_list = PageResponseModel( **{ **query_user_list.model_dump(by_alias=True),