diff --git a/src/main/java/com/nbport/zgwl/auth/AuthManager.java b/src/main/java/com/nbport/zgwl/auth/AuthManager.java new file mode 100644 index 0000000..b07622d --- /dev/null +++ b/src/main/java/com/nbport/zgwl/auth/AuthManager.java @@ -0,0 +1,46 @@ +package com.nbport.zgwl.auth; + +import org.springframework.stereotype.Component; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 本地模拟 AuthManager。 + * + * 目的不是还原正式权限中心,而是把调用方式先固定住: + * authManager.isUserCanAccessSys(userId, SysEnum.BUSINESS/MANAGE) + * + * 后续复制到正式环境时,保留方法签名,替换内部实现即可。 + */ +@Component +public class AuthManager { + + /** + * 写死几套本地用户可访问系统。 + * + * 约定: + * 1L -> 超管,可同时访问 manage / business + * 2L -> manage 侧管理员 + * 3L -> business 侧业务管理员 + * 4L -> business 侧普通用户 + */ + private static final Map> USER_SYS_ACCESS = new HashMap<>(); + + static { + USER_SYS_ACCESS.put(1L, EnumSet.of(SysEnum.MANAGE, SysEnum.BUSINESS)); + USER_SYS_ACCESS.put(2L, EnumSet.of(SysEnum.MANAGE)); + USER_SYS_ACCESS.put(3L, EnumSet.of(SysEnum.BUSINESS)); + USER_SYS_ACCESS.put(4L, EnumSet.of(SysEnum.BUSINESS)); + } + + public boolean isUserCanAccessSys(Long userId, SysEnum sysEnum) { + if (userId == null || sysEnum == null) { + return false; + } + Set accessSet = USER_SYS_ACCESS.get(userId); + return accessSet != null && accessSet.contains(sysEnum); + } +} diff --git a/src/main/java/com/nbport/zgwl/auth/SecurityManager.java b/src/main/java/com/nbport/zgwl/auth/SecurityManager.java new file mode 100644 index 0000000..cd0611d --- /dev/null +++ b/src/main/java/com/nbport/zgwl/auth/SecurityManager.java @@ -0,0 +1,32 @@ +package com.nbport.zgwl.auth; + +import com.nbport.zgwl.entity.SysUserEntity; +import com.nbport.zgwl.utils.AdminSecurityManage; +import org.springframework.stereotype.Component; + +import java.util.Set; + +/** + * 本地模拟 SecurityManager。 + * + * 保持与正式环境接近的方法形态: + * securityManager.isSuperAdmin() + */ +@Component +public class SecurityManager { + + private static final Set SUPER_ADMIN_IDS = Set.of(1L); + + private final AdminSecurityManage adminSecurityManage; + + public SecurityManager(AdminSecurityManage adminSecurityManage) { + this.adminSecurityManage = adminSecurityManage; + } + + public boolean isSuperAdmin() { + SysUserEntity currentUser = adminSecurityManage.getUser(); + return currentUser != null + && currentUser.getId() != null + && SUPER_ADMIN_IDS.contains(currentUser.getId()); + } +} diff --git a/src/main/java/com/nbport/zgwl/auth/SysEnum.java b/src/main/java/com/nbport/zgwl/auth/SysEnum.java new file mode 100644 index 0000000..77472e9 --- /dev/null +++ b/src/main/java/com/nbport/zgwl/auth/SysEnum.java @@ -0,0 +1,13 @@ +package com.nbport.zgwl.auth; + +/** + * 本地模拟系统枚举。 + * + * 正式环境里你已有同名/同义枚举时, + * 这里的调用方式可以直接平移过去。 + */ +public enum SysEnum { + + MANAGE, + BUSINESS +} diff --git a/src/main/java/com/nbport/zgwl/contractlaunch/mapper/ContractLaunchMapper.java b/src/main/java/com/nbport/zgwl/contractlaunch/mapper/ContractLaunchMapper.java index f24dfa3..f72c5df 100644 --- a/src/main/java/com/nbport/zgwl/contractlaunch/mapper/ContractLaunchMapper.java +++ b/src/main/java/com/nbport/zgwl/contractlaunch/mapper/ContractLaunchMapper.java @@ -43,6 +43,9 @@ public interface ContractLaunchMapper { /** 根据主键查询合同 */ ContractLaunchDto selectContractById(@Param("id") Long id); + /** 根据主键并带权限条件查询合同 */ + ContractLaunchDto selectContractByIdWithScope(@Param("id") Long id, @Param("query") ContractLaunchQueryDto queryDto); + /** 根据 contractSysId 查询合同(法务回调时用于定位) */ ContractLaunchDto selectContractByContractSysId(@Param("contractSysId") String contractSysId); diff --git a/src/main/java/com/nbport/zgwl/contractlaunch/service/ContractLaunchServiceImpl.java b/src/main/java/com/nbport/zgwl/contractlaunch/service/ContractLaunchServiceImpl.java index 3046434..458a0ff 100644 --- a/src/main/java/com/nbport/zgwl/contractlaunch/service/ContractLaunchServiceImpl.java +++ b/src/main/java/com/nbport/zgwl/contractlaunch/service/ContractLaunchServiceImpl.java @@ -2,6 +2,9 @@ package com.nbport.zgwl.contractlaunch.service; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.nbport.zgwl.auth.AuthManager; +import com.nbport.zgwl.auth.SecurityManager; +import com.nbport.zgwl.auth.SysEnum; import com.fasterxml.jackson.databind.ObjectMapper; import com.nbport.zgwl.common.PageResult; import com.nbport.zgwl.contractlaunch.dto.ContractLaunchApproveDto; @@ -49,6 +52,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Locale; import java.util.UUID; import java.util.stream.Collectors; @@ -68,6 +72,8 @@ public class ContractLaunchServiceImpl implements ContractLaunchService { private final ContractLaunchMapper contractLaunchMapper; private final AdminSecurityManage adminSecurityManage; + private final AuthManager authManager; + private final SecurityManager securityManager; private final SettlementPushService settlementPushService; private final DataCollectionPushService dataCollectionPushService; private final ContractLaunchLegalFileBridgeService legalFileBridgeService; @@ -94,11 +100,7 @@ public class ContractLaunchServiceImpl implements ContractLaunchService { @Override public PageResult queryPage(ContractLaunchQueryDto queryDto) { SysUserEntity currentUser = adminSecurityManage.getUser(); - String scope = resolveQueryScope(currentUser); - queryDto.setQueryScope(scope); - queryDto.setCurrentUserId(currentUser.getUsername()); - queryDto.setCurrentOrgId(currentUser.getSysOrgEntity() == null ? null : currentUser.getSysOrgEntity().getId()); - queryDto.setCurrentDeptName(currentUser.getSysOrgEntity() == null ? null : currentUser.getSysOrgEntity().getOrgName()); + applyQueryScope(queryDto, currentUser); Page page = new Page<>(queryDto.getPageNo(), queryDto.getPageSize()); Page resultPage = (Page) contractLaunchMapper.selectContractPage(page, queryDto); PageResult pageResult = new PageResult<>(resultPage); @@ -117,13 +119,31 @@ public class ContractLaunchServiceImpl implements ContractLaunchService { * 当前无角色体系,暂统一返回 admin(即不过滤),保证流程可跑通。 */ private String resolveQueryScope(SysUserEntity currentUser) { - return "admin"; + if (currentUser == null || currentUser.getId() == null) { + return "personal"; + } + if (securityManager.isSuperAdmin()) { + return "admin"; + } + String permissionScope = resolveScopeByDataPermission(currentUser.getDataPermission()); + if (permissionScope != null) { + return permissionScope; + } + if (authManager.isUserCanAccessSys(currentUser.getId(), SysEnum.MANAGE)) { + return isAdminUser(currentUser) ? "company" : "personal"; + } + if (authManager.isUserCanAccessSys(currentUser.getId(), SysEnum.BUSINESS)) { + return isAdminUser(currentUser) ? "company" : "personal"; + } + return "personal"; } /** 查询详情,含日志 */ @Override public ContractLaunchDto getDetail(Long id) { - ContractLaunchDto contract = contractLaunchMapper.selectContractById(id); + SysUserEntity currentUser = adminSecurityManage.getUser(); + ContractLaunchQueryDto queryDto = buildScopeQuery(currentUser); + ContractLaunchDto contract = contractLaunchMapper.selectContractByIdWithScope(id, queryDto); if (contract == null) { throw new ServiceException("合同不存在"); } @@ -1973,4 +1993,52 @@ public class ContractLaunchServiceImpl implements ContractLaunchService { private String trim(String value) { return value == null ? null : value.trim(); } + + private void applyQueryScope(ContractLaunchQueryDto queryDto, SysUserEntity currentUser) { + ContractLaunchQueryDto scopeQuery = buildScopeQuery(currentUser); + queryDto.setQueryScope(scopeQuery.getQueryScope()); + queryDto.setCurrentUserId(scopeQuery.getCurrentUserId()); + queryDto.setCurrentOrgId(scopeQuery.getCurrentOrgId()); + queryDto.setCurrentDeptName(scopeQuery.getCurrentDeptName()); + } + + private ContractLaunchQueryDto buildScopeQuery(SysUserEntity currentUser) { + ContractLaunchQueryDto queryDto = new ContractLaunchQueryDto(); + queryDto.setQueryScope(resolveQueryScope(currentUser)); + queryDto.setCurrentUserId(currentUser == null ? null : currentUser.getUsername()); + queryDto.setCurrentOrgId(currentUser == null || currentUser.getSysOrgEntity() == null + ? null + : currentUser.getSysOrgEntity().getId()); + queryDto.setCurrentDeptName(currentUser == null + ? null + : (currentUser.getDeptName() == null || currentUser.getDeptName().isBlank() + ? (currentUser.getSysOrgEntity() == null ? null : currentUser.getSysOrgEntity().getOrgName()) + : currentUser.getDeptName())); + return queryDto; + } + + private boolean isAdminUser(SysUserEntity currentUser) { + return currentUser != null && Objects.equals(currentUser.getAdminFlag(), 1L); + } + + private String resolveScopeByDataPermission(String dataPermission) { + String value = trim(dataPermission); + if (value == null || value.isBlank()) { + return null; + } + String normalized = value.toUpperCase(Locale.ROOT); + if (normalized.contains("ALL") || normalized.contains("ADMIN") || normalized.contains("全部")) { + return "admin"; + } + if (normalized.contains("COMPANY") || normalized.contains("ORG") || normalized.contains("公司")) { + return "company"; + } + if (normalized.contains("DEPT") || normalized.contains("DEPARTMENT") || normalized.contains("部门")) { + return "department"; + } + if (normalized.contains("SELF") || normalized.contains("PERSONAL") || normalized.contains("个人")) { + return "personal"; + } + return null; + } } diff --git a/src/main/java/com/nbport/zgwl/entity/SysUserEntity.java b/src/main/java/com/nbport/zgwl/entity/SysUserEntity.java index 6e11b6e..0645a9f 100644 --- a/src/main/java/com/nbport/zgwl/entity/SysUserEntity.java +++ b/src/main/java/com/nbport/zgwl/entity/SysUserEntity.java @@ -8,6 +8,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serial; +import java.util.ArrayList; +import java.util.List; @Data @TableName(value = "sys_user") @@ -29,6 +31,36 @@ public class SysUserEntity extends BaseEntity { @TableField("email") private String email; + /** + * 本地模拟正式环境字段:是否管理员。 + * 约定:1-管理员,0-普通用户 + */ + @TableField(exist = false) + private Long adminFlag; + + /** + * 本地模拟正式环境字段:部门名称。 + */ + @TableField(exist = false) + private String deptName; + + /** + * 本地模拟正式环境字段:数据权限。 + * + * 可取: + * ALL / COMPANY / DEPARTMENT / SELF + */ + @TableField(exist = false) + private String dataPermission; + + /** + * 当前用户手机号/账号之外的本地模拟角色编码。 + * + * 保留这个字段仅用于本地调试扩展,正式环境可忽略。 + */ + @TableField(exist = false) + private List roleCodes = new ArrayList<>(); + /** * 当前登录人的所属组织 * diff --git a/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java b/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java index 81aa341..04640be 100644 --- a/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java +++ b/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java @@ -2,8 +2,12 @@ package com.nbport.zgwl.utils; import com.nbport.zgwl.entity.SysOrgEntity; import com.nbport.zgwl.entity.SysUserEntity; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.util.List; + /** * 登录用户获取组件 * @@ -14,10 +18,116 @@ import org.springframework.stereotype.Component; @Component public class AdminSecurityManage { + private static final String HEADER_MOCK_USER = "X-Mock-User"; + + private final HttpServletRequest request; + private final String defaultMockUser; + + public AdminSecurityManage(HttpServletRequest request, + @Value("${mock.security.current-user:admin}") String defaultMockUser) { + this.request = request; + this.defaultMockUser = defaultMockUser; + } + public SysUserEntity getUser() { + String mockUser = request == null ? null : request.getHeader(HEADER_MOCK_USER); + if (mockUser == null || mockUser.isBlank()) { + mockUser = defaultMockUser; + } + if ("manage_admin".equalsIgnoreCase(mockUser)) { + return buildManageAdmin(); + } + if ("business_admin".equalsIgnoreCase(mockUser)) { + return buildBusinessAdmin(); + } + if ("business_user".equalsIgnoreCase(mockUser)) { + return buildBusinessUser(); + } + return buildSuperAdmin(); + } + + private SysUserEntity buildSuperAdmin() { + return buildUser( + 1L, + "admin", + "13800000000", + "admin@test.com", + buildOrg("1", "浙江海港物流集团有限公司X"), + "平台管理部", + 1L, + "ALL", + List.of("SUPER_ADMIN", "MANAGE_ADMIN", "BUSINESS_ADMIN") + ); + } + + private SysUserEntity buildManageAdmin() { + return buildUser( + 2L, + "manage_admin", + "13800000001", + "manage_admin@test.com", + buildOrg("1", "浙江海港物流集团有限公司X"), + "财务部", + 1L, + "COMPANY", + List.of("MANAGE_ADMIN") + ); + } + + private SysUserEntity buildBusinessAdmin() { + return buildUser( + 3L, + "business_admin", + "13800000002", + "business_admin@test.com", + buildOrg("384", "江苏远洋新世纪2供应链有限公司"), + "业务一部", + 1L, + "COMPANY", + List.of("BUSINESS_ADMIN") + ); + } + + private SysUserEntity buildBusinessUser() { + return buildUser( + 4L, + "business_user", + "13800000003", + "business_user@test.com", + buildOrg("384", "江苏远洋新世纪2供应链有限公司"), + "业务一部", + 0L, + "SELF", + List.of("BUSINESS_USER") + ); + } + + private SysUserEntity buildUser(Long id, + String username, + String mobilePhone, + String email, + SysOrgEntity orgEntity, + String deptName, + Long adminFlag, + String dataPermission, + List roleCodes) { + SysUserEntity user = new SysUserEntity(); + user.setId(id); + user.setUsername(username); + user.setMobilePhone(mobilePhone); + user.setEmail(email); + user.setSysOrgEntity(orgEntity); + user.setDeptName(deptName); + user.setAdminFlag(adminFlag); + user.setDataPermission(dataPermission); + user.setRoleCodes(roleCodes); + return user; + } + + private SysOrgEntity buildOrg(String orgId, String orgName) { SysOrgEntity orgEntity = new SysOrgEntity(); - orgEntity.setId("1"); - orgEntity.setOrgName("浙江海港物流集团有限公司X"); + orgEntity.setId(orgId); + orgEntity.setOrgName(orgName); orgEntity.setContactPhone("13800000000"); orgEntity.setContactEmail("admin@test.com"); orgEntity.setContactAddress("宁波市北仑区明州路288号"); @@ -26,14 +136,7 @@ public class AdminSecurityManage { orgEntity.setBankAccount("330201000000000001"); orgEntity.setLegalRepresentative("张三"); orgEntity.setCreditCode("91330200MAZGWL0001"); - orgEntity.setInvoiceTitleOptions(java.util.List.of("浙港物流平台有限公司")); - - SysUserEntity user = new SysUserEntity(); - user.setId(1L); - user.setUsername("admin"); - user.setMobilePhone("13800000000"); - user.setEmail("admin@test.com"); - user.setSysOrgEntity(orgEntity); - return user; + orgEntity.setInvoiceTitleOptions(List.of("浙港物流平台有限公司")); + return orgEntity; } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index a396f36..bc87f13 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -11,6 +11,11 @@ spring: hikari: connection-test-query: SELECT 1 FROM DUAL +mock: + security: + # 可选:admin / manage_admin / business_admin / business_user + current-user: admin + # 合同推送 —— 测试环境地址 contract-push: settlement: diff --git a/src/main/resources/mapper/contractlaunch/ContractLaunchMapper.xml b/src/main/resources/mapper/contractlaunch/ContractLaunchMapper.xml index 0f3b3ec..95fbe20 100644 --- a/src/main/resources/mapper/contractlaunch/ContractLaunchMapper.xml +++ b/src/main/resources/mapper/contractlaunch/ContractLaunchMapper.xml @@ -318,6 +318,43 @@ and IS_DELETED = 'N' + +