From 32e235d71b63d592f0907ae92888341700d738e6 Mon Sep 17 00:00:00 2001 From: aibot Date: Mon, 25 May 2026 15:31:50 +0800 Subject: [PATCH] fea: sec empUser saver --- .../sys/SysAutoConfiguration.java | 8 +- .../modules/sys/service/EmpUserService.java | 14 ++ .../support/EmpUserServiceSupport.java | 34 +++- .../support/SysDataScopeCheckHelper.java | 180 ++++++++++++++++++ .../sys/web/user/EmpUserController.java | 2 + 5 files changed, 235 insertions(+), 3 deletions(-) create mode 100644 modules/core/src/main/java/com/jeesite/modules/sys/service/support/SysDataScopeCheckHelper.java diff --git a/modules/core/src/main/java/com/jeesite/autoconfigure/sys/SysAutoConfiguration.java b/modules/core/src/main/java/com/jeesite/autoconfigure/sys/SysAutoConfiguration.java index c201fde71..8cfd21918 100644 --- a/modules/core/src/main/java/com/jeesite/autoconfigure/sys/SysAutoConfiguration.java +++ b/modules/core/src/main/java/com/jeesite/autoconfigure/sys/SysAutoConfiguration.java @@ -11,6 +11,7 @@ import com.jeesite.modules.sys.dao.PostRoleDao; import com.jeesite.modules.sys.service.*; import com.jeesite.modules.sys.service.support.*; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -47,8 +48,11 @@ public EmployeeService employeeService(EmployeePostDao employeePostDao, Employee @Bean @ConditionalOnMissingBean - public EmpUserService empUserService(UserService userService, EmployeeService employeeService, EmployeeOfficeDao employeeOfficeDao){ - return new EmpUserServiceSupport(userService, employeeService, employeeOfficeDao); + public EmpUserService empUserService(UserService userService, EmployeeService employeeService, + EmployeeOfficeDao employeeOfficeDao, ObjectProvider officeService, + ObjectProvider companyService, PostRoleDao postRoleDao, RoleService roleService){ + return new EmpUserServiceSupport(userService, employeeService, employeeOfficeDao, + officeService, companyService, postRoleDao, roleService); } @Bean diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/service/EmpUserService.java b/modules/core/src/main/java/com/jeesite/modules/sys/service/EmpUserService.java index 5f76aea85..4f9597b02 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/service/EmpUserService.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/service/EmpUserService.java @@ -39,6 +39,20 @@ public interface EmpUserService extends CrudServiceApi { @Override void addDataScopeFilter(EmpUser empUser, String ctrlPermi); + /** + * 校验用户是否在当前操作者的数据权限范围内 + * @param userCode 用户编码 + * @param ctrlPermi 控制权限类型 + */ + void checkUserDataScope(String userCode, String ctrlPermi); + + /** + * 校验员工用户提交的数据是否在当前操作者的数据权限范围内 + * @param empUser 员工用户 + * @param ctrlPermi 控制权限类型 + */ + void checkEmpUserDataScope(EmpUser empUser, String ctrlPermi); + /** * 分页查询数据 */ diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/service/support/EmpUserServiceSupport.java b/modules/core/src/main/java/com/jeesite/modules/sys/service/support/EmpUserServiceSupport.java index 1f6c0b6e5..453337d32 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/service/support/EmpUserServiceSupport.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/service/support/EmpUserServiceSupport.java @@ -15,17 +15,22 @@ import com.jeesite.common.validator.ValidatorUtils; import com.jeesite.modules.sys.dao.EmpUserDao; import com.jeesite.modules.sys.dao.EmployeeOfficeDao; +import com.jeesite.modules.sys.dao.PostRoleDao; import com.jeesite.modules.sys.entity.EmpUser; import com.jeesite.modules.sys.entity.Employee; import com.jeesite.modules.sys.entity.EmployeeOffice; import com.jeesite.modules.sys.entity.User; +import com.jeesite.modules.sys.service.CompanyService; import com.jeesite.modules.sys.service.EmpUserService; import com.jeesite.modules.sys.service.EmployeeService; +import com.jeesite.modules.sys.service.OfficeService; +import com.jeesite.modules.sys.service.RoleService; import com.jeesite.modules.sys.service.UserService; import com.jeesite.modules.sys.utils.EmpUtils; import com.jeesite.modules.sys.utils.UserUtils; import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -42,11 +47,21 @@ public class EmpUserServiceSupport extends CrudService protected final UserService userService; protected final EmployeeService employeeService; protected final EmployeeOfficeDao employeeOfficeDao; + protected final ObjectProvider officeService; + protected final ObjectProvider companyService; + protected final PostRoleDao postRoleDao; + protected final RoleService roleService; - public EmpUserServiceSupport(UserService userService, EmployeeService employeeService, EmployeeOfficeDao employeeOfficeDao) { + public EmpUserServiceSupport(UserService userService, EmployeeService employeeService, + EmployeeOfficeDao employeeOfficeDao, ObjectProvider officeService, + ObjectProvider companyService, PostRoleDao postRoleDao, RoleService roleService) { this.userService = userService; this.employeeService = employeeService; this.employeeOfficeDao = employeeOfficeDao; + this.officeService = officeService; + this.companyService = companyService; + this.postRoleDao = postRoleDao; + this.roleService = roleService; } /** @@ -93,6 +108,23 @@ public void addDataScopeFilter(EmpUser empUser, String ctrlPermi) { // "a.user_code", ctrlPermi); } + /** + * 校验用户是否在当前操作者的数据权限范围内 + */ + @Override + public void checkUserDataScope(String userCode, String ctrlPermi) { + SysDataScopeCheckHelper.checkUserDataScope(userCode, ctrlPermi, this); + } + + /** + * 校验员工用户提交的数据是否在当前操作者的数据权限范围内 + */ + @Override + public void checkEmpUserDataScope(EmpUser empUser, String ctrlPermi) { + SysDataScopeCheckHelper.checkEmpUserDataScope(empUser, ctrlPermi, + this, officeService.getObject(), companyService.getObject(), postRoleDao, roleService); + } + /** * 查询数据 */ diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/service/support/SysDataScopeCheckHelper.java b/modules/core/src/main/java/com/jeesite/modules/sys/service/support/SysDataScopeCheckHelper.java new file mode 100644 index 000000000..d6b8ffbea --- /dev/null +++ b/modules/core/src/main/java/com/jeesite/modules/sys/service/support/SysDataScopeCheckHelper.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2013-Now https://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.modules.sys.service.support; + +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.DataScope; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.common.service.ServiceException; +import com.jeesite.modules.sys.dao.PostRoleDao; +import com.jeesite.modules.sys.entity.Company; +import com.jeesite.modules.sys.entity.EmpUser; +import com.jeesite.modules.sys.entity.Employee; +import com.jeesite.modules.sys.entity.EmployeeOffice; +import com.jeesite.modules.sys.entity.EmployeePost; +import com.jeesite.modules.sys.entity.Office; +import com.jeesite.modules.sys.entity.PostRole; +import com.jeesite.modules.sys.entity.Role; +import com.jeesite.modules.sys.entity.User; +import com.jeesite.modules.sys.service.CompanyService; +import com.jeesite.modules.sys.service.EmpUserService; +import com.jeesite.modules.sys.service.OfficeService; +import com.jeesite.modules.sys.service.RoleService; +import com.jeesite.modules.sys.utils.UserUtils; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * 数据权限校验辅助类 + * @author ThinkGem + */ +public final class SysDataScopeCheckHelper { + + private SysDataScopeCheckHelper() { + } + + public static String defaultCtrlPermi(String ctrlPermi) { + return StringUtils.defaultIfBlank(ctrlPermi, + Global.getConfig("user.adminCtrlPermi", DataScope.CTRL_PERMI_MANAGE)); + } + + public static void checkUserDataScope(String userCode, String ctrlPermi, EmpUserService empUserService) { + if (StringUtils.isBlank(userCode) || isSuperAdmin()) { + return; + } + EmpUser where = new EmpUser(); + where.setUserCode(userCode); + where.setUserType(EmpUser.USER_TYPE_EMPLOYEE); + where.sqlMap().getWhere().disableAutoAddStatusWhere(); + empUserService.addDataScopeFilter(where, defaultCtrlPermi(ctrlPermi)); + if (empUserService.findCount(where) == 0) { + throw new ServiceException(Global.getText("没有权限访问用户数据!")); + } + } + + public static void checkEmpUserDataScope(EmpUser empUser, String ctrlPermi, + EmpUserService empUserService, OfficeService officeService, CompanyService companyService, + PostRoleDao postRoleDao, RoleService roleService) { + if (empUser == null || isSuperAdmin()) { + return; + } + String dataScopeCtrlPermi = defaultCtrlPermi(ctrlPermi); + checkUserDataScope(empUser.getUserCode(), dataScopeCtrlPermi, empUserService); + Employee employee = empUser.getEmployee(); + Set officeCodes = new HashSet<>(); + Set postCodes = new HashSet<>(); + checkOfficeDataScope(employee.getOffice().getOfficeCode(), dataScopeCtrlPermi, officeService, officeCodes); + checkCompanyDataScope(employee.getCompany().getCompanyCode(), dataScopeCtrlPermi, companyService); + checkEmployeePostList(employee.getEmployeePostList(), dataScopeCtrlPermi, postRoleDao, roleService, postCodes); + checkEmployeeOfficeList(employee.getEmployeeOfficeList(), dataScopeCtrlPermi, + officeService, postRoleDao, roleService, officeCodes, postCodes); + } + + public static void checkRoleDataScope(String roleCodes, String ctrlPermi, RoleService roleService) { + if (StringUtils.isBlank(roleCodes)) { + return; + } + Set codeSet = new HashSet<>(); + for (String roleCode : StringUtils.splitComma(roleCodes)) { + if (StringUtils.isNotBlank(roleCode)) { + codeSet.add(roleCode); + } + } + checkRoleDataScope(codeSet, ctrlPermi, roleService); + } + + public static void checkRoleDataScope(Collection roleCodes, String ctrlPermi, RoleService roleService) { + if (roleCodes == null || roleCodes.isEmpty() || isSuperAdmin()) { + return; + } + Role where = new Role(); + where.setStatus(Role.STATUS_NORMAL); + where.setUserType(User.USER_TYPE_EMPLOYEE); + where.sqlMap().getWhere().and("role_code", QueryType.IN, roleCodes.toArray(new String[0])); + roleService.addDataScopeFilter(where, defaultCtrlPermi(ctrlPermi)); + if (roleService.findCount(where) != roleCodes.size()) { + throw new ServiceException(Global.getText("没有权限使用该角色数据!")); + } + } + + private static void checkOfficeDataScope(String officeCode, String ctrlPermi, + OfficeService officeService, Set checkedOfficeCodes) { + if (StringUtils.isBlank(officeCode) || !checkedOfficeCodes.add(officeCode)) { + return; + } + Office office = new Office(); + office.setOfficeCode(officeCode); + office.setStatus(Office.STATUS_NORMAL); + officeService.addDataScopeFilter(office, ctrlPermi); + if (officeService.findCount(office) == 0) { + throw new ServiceException(Global.getText("没有权限使用该机构数据!")); + } + } + + private static void checkCompanyDataScope(String companyCode, String ctrlPermi, CompanyService companyService) { + if (StringUtils.isBlank(companyCode)) { + return; + } + Company company = new Company(); + company.setCompanyCode(companyCode); + company.setStatus(Company.STATUS_NORMAL); + companyService.addDataScopeFilter(company, ctrlPermi); + if (companyService.findCount(company) == 0) { + throw new ServiceException(Global.getText("没有权限使用该公司数据!")); + } + } + + private static void checkEmployeePostList(Collection employeePostList, + String ctrlPermi, PostRoleDao postRoleDao, RoleService roleService, Set checkedPostCodes) { + if (employeePostList == null) { + return; + } + for (EmployeePost employeePost : employeePostList) { + if (employeePost != null) { + checkPostRoleDataScope(employeePost.getPostCode(), ctrlPermi, postRoleDao, roleService, checkedPostCodes); + } + } + } + + private static void checkEmployeeOfficeList(Collection employeeOfficeList, String ctrlPermi, + OfficeService officeService, PostRoleDao postRoleDao, RoleService roleService, + Set checkedOfficeCodes, Set checkedPostCodes) { + if (employeeOfficeList == null) { + return; + } + for (EmployeeOffice employeeOffice : employeeOfficeList) { + if (employeeOffice == null) { + continue; + } + checkOfficeDataScope(employeeOffice.getOfficeCode(), ctrlPermi, officeService, checkedOfficeCodes); + checkPostRoleDataScope(employeeOffice.getPostCode(), ctrlPermi, postRoleDao, roleService, checkedPostCodes); + } + } + + private static void checkPostRoleDataScope(String postCode, String ctrlPermi, + PostRoleDao postRoleDao, RoleService roleService, Set checkedPostCodes) { + if (StringUtils.isBlank(postCode) || !checkedPostCodes.add(postCode)) { + return; + } + PostRole where = new PostRole(); + where.setPostCode(postCode); + where.sqlMap().loadJoinTableAlias("r"); + Set roleCodes = new HashSet<>(); + for (PostRole postRole : postRoleDao.findList(where)) { + if (postRole.getRole() != null && PostRole.STATUS_NORMAL.equals(postRole.getRole().getStatus())) { + roleCodes.add(postRole.getRoleCode()); + } + } + checkRoleDataScope(roleCodes, ctrlPermi, roleService); + } + + private static boolean isSuperAdmin() { + User user = UserUtils.getUser(); + return user != null && user.isSuperAdmin(); + } +} diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java index f89408647..1ebae8699 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java @@ -202,6 +202,7 @@ public String save(@Validated EmpUser empUser, @Parameter(description = "操作 } Subject subject = UserUtils.getSubject(); if (StringUtils.inString(op, Global.OP_ADD, Global.OP_EDIT) && subject.isPermitted("sys:empUser:edit")){ + empUserService.checkEmpUserDataScope(empUser, Global.getConfig("user.adminCtrlPermi", "2")); empUserService.addFieldScopeFilter(empUser); empUserService.save(empUser); } @@ -210,6 +211,7 @@ public String save(@Validated EmpUser empUser, @Parameter(description = "操作 return renderResult(Global.FALSE, text("启用岗位角色权限后,请在用户关联岗位中关联角色", empUser.getUserName())); } }else if (StringUtils.inString(op, Global.OP_ADD, Global.OP_AUTH) && subject.isPermitted("sys:empUser:authRole")){ + empUserService.checkUserDataScope(empUser.getUserCode(), Global.getConfig("user.adminCtrlPermi", "2")); userService.saveAuth(empUser); } return renderResult(Global.TRUE, text("保存用户''{0}''成功", empUser.getUserName()));