From f7b995ed3ad77674b2d558d658fb9cde377b6440 Mon Sep 17 00:00:00 2001 From: zhouxiaofeng <2946471396@qq.com> Date: Thu, 9 Jul 2026 16:07:48 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E8=B6=B3=E7=94=A8=E6=88=B7=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/nbport/zgwl/auth/AuthManager.java | 30 +- .../com/nbport/zgwl/auth/SecurityManager.java | 14 +- .../service/ContractLaunchServiceImpl.java | 6 +- .../controller/MockUserSwitchController.java | 37 ++ .../service/ContractTemplateServiceImpl.java | 39 +- .../service/PartnerManageServiceImpl.java | 33 +- .../zgwl/utils/AdminSecurityManage.java | 119 +----- .../zgwl/utils/MockSecurityUserRegistry.java | 389 ++++++++++++++++++ 8 files changed, 504 insertions(+), 163 deletions(-) create mode 100644 src/main/java/com/nbport/zgwl/controller/MockUserSwitchController.java create mode 100644 src/main/java/com/nbport/zgwl/utils/MockSecurityUserRegistry.java diff --git a/src/main/java/com/nbport/zgwl/auth/AuthManager.java b/src/main/java/com/nbport/zgwl/auth/AuthManager.java index b07622d..8fd630d 100644 --- a/src/main/java/com/nbport/zgwl/auth/AuthManager.java +++ b/src/main/java/com/nbport/zgwl/auth/AuthManager.java @@ -1,12 +1,8 @@ package com.nbport.zgwl.auth; +import com.nbport.zgwl.utils.MockSecurityUserRegistry; import org.springframework.stereotype.Component; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - /** * 本地模拟 AuthManager。 * @@ -18,29 +14,13 @@ import java.util.Set; @Component public class AuthManager { - /** - * 写死几套本地用户可访问系统。 - * - * 约定: - * 1L -> 超管,可同时访问 manage / business - * 2L -> manage 侧管理员 - * 3L -> business 侧业务管理员 - * 4L -> business 侧普通用户 - */ - private static final Map> USER_SYS_ACCESS = new HashMap<>(); + private final MockSecurityUserRegistry mockSecurityUserRegistry; - 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 AuthManager(MockSecurityUserRegistry mockSecurityUserRegistry) { + this.mockSecurityUserRegistry = mockSecurityUserRegistry; } 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); + return mockSecurityUserRegistry.canAccessSystem(userId, sysEnum); } } diff --git a/src/main/java/com/nbport/zgwl/auth/SecurityManager.java b/src/main/java/com/nbport/zgwl/auth/SecurityManager.java index cd0611d..5978a6d 100644 --- a/src/main/java/com/nbport/zgwl/auth/SecurityManager.java +++ b/src/main/java/com/nbport/zgwl/auth/SecurityManager.java @@ -2,10 +2,9 @@ package com.nbport.zgwl.auth; import com.nbport.zgwl.entity.SysUserEntity; import com.nbport.zgwl.utils.AdminSecurityManage; +import com.nbport.zgwl.utils.MockSecurityUserRegistry; import org.springframework.stereotype.Component; -import java.util.Set; - /** * 本地模拟 SecurityManager。 * @@ -15,18 +14,17 @@ import java.util.Set; @Component public class SecurityManager { - private static final Set SUPER_ADMIN_IDS = Set.of(1L); - private final AdminSecurityManage adminSecurityManage; + private final MockSecurityUserRegistry mockSecurityUserRegistry; - public SecurityManager(AdminSecurityManage adminSecurityManage) { + public SecurityManager(AdminSecurityManage adminSecurityManage, + MockSecurityUserRegistry mockSecurityUserRegistry) { this.adminSecurityManage = adminSecurityManage; + this.mockSecurityUserRegistry = mockSecurityUserRegistry; } public boolean isSuperAdmin() { SysUserEntity currentUser = adminSecurityManage.getUser(); - return currentUser != null - && currentUser.getId() != null - && SUPER_ADMIN_IDS.contains(currentUser.getId()); + return currentUser != null && mockSecurityUserRegistry.isSuperAdmin(currentUser.getId()); } } 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 ae2e8e3..18c735b 100644 --- a/src/main/java/com/nbport/zgwl/contractlaunch/service/ContractLaunchServiceImpl.java +++ b/src/main/java/com/nbport/zgwl/contractlaunch/service/ContractLaunchServiceImpl.java @@ -131,13 +131,17 @@ public class ContractLaunchServiceImpl implements ContractLaunchService { if (securityManager.isSuperAdmin()) { return "admin"; } + String scopeByPermission = resolveScopeByDataPermission(currentUser.getDataPermission()); + if (scopeByPermission != null) { + return scopeByPermission; + } if (authManager.isUserCanAccessSys(currentUser.getId(), SysEnum.MANAGE)) { return "company"; } if (authManager.isUserCanAccessSys(currentUser.getId(), SysEnum.BUSINESS)) { return "company"; } - return "personal"; + return isAdminUser(currentUser) ? "company" : "personal"; } /** 查询详情,含日志 */ diff --git a/src/main/java/com/nbport/zgwl/controller/MockUserSwitchController.java b/src/main/java/com/nbport/zgwl/controller/MockUserSwitchController.java new file mode 100644 index 0000000..ed3e0a9 --- /dev/null +++ b/src/main/java/com/nbport/zgwl/controller/MockUserSwitchController.java @@ -0,0 +1,37 @@ +package com.nbport.zgwl.controller; + +import com.nbport.zgwl.common.R; +import com.nbport.zgwl.utils.AdminSecurityManage; +import com.nbport.zgwl.utils.MockSecurityUserRegistry; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 本地测试用的 mock 用户切换辅助接口。 + * + * 仅返回用户列表和当前用户摘要, + * 真正的切换仍由前端通过请求头 X-Mock-User 控制, + * 这样不会引入新的登录态或会话依赖。 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/mock/security") +public class MockUserSwitchController { + + private final AdminSecurityManage adminSecurityManage; + private final MockSecurityUserRegistry mockSecurityUserRegistry; + + @GetMapping("/users") + public R> listUsers() { + return R.success(mockSecurityUserRegistry.listUserOptions()); + } + + @GetMapping("/current") + public R getCurrentUser() { + return R.success(mockSecurityUserRegistry.buildCurrentUserDto(adminSecurityManage.resolveMockUserKey())); + } +} diff --git a/src/main/java/com/nbport/zgwl/manifest/service/ContractTemplateServiceImpl.java b/src/main/java/com/nbport/zgwl/manifest/service/ContractTemplateServiceImpl.java index 75723cf..638b43b 100644 --- a/src/main/java/com/nbport/zgwl/manifest/service/ContractTemplateServiceImpl.java +++ b/src/main/java/com/nbport/zgwl/manifest/service/ContractTemplateServiceImpl.java @@ -1,6 +1,7 @@ package com.nbport.zgwl.manifest.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.nbport.zgwl.entity.SysUserEntity; import com.nbport.zgwl.common.PageResult; import com.nbport.zgwl.exception.ServiceException; import com.nbport.zgwl.manifest.dto.ContractTemplateDto; @@ -12,6 +13,7 @@ import com.nbport.zgwl.manifest.utils.ManifestCodeUtils; import com.nbport.zgwl.manifest.utils.ManifestJsonUtils; import com.nbport.zgwl.manifest.utils.ManifestManageConstants; import com.nbport.zgwl.utils.AdminSecurityManage; +import com.nbport.zgwl.utils.MockSecurityUserRegistry; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -41,6 +43,8 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { private final AdminSecurityManage adminSecurityManage; + private final MockSecurityUserRegistry mockSecurityUserRegistry; + /** * 内存中的组织树(扁平化节点列表),懒加载 */ @@ -94,9 +98,9 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { LocalDateTime now = LocalDateTime.now(); template.setId(contractTemplateMapper.selectTemplateSeqNextVal()); template.setTemplateCode(ManifestCodeUtils.buildTemplateCode(template.getContractType())); - template.setCreateBy(ManifestManageConstants.DEFAULT_OPERATOR); + template.setCreateBy(resolveOperatorName()); template.setCreatedTime(now); - template.setUpdatedBy(ManifestManageConstants.DEFAULT_OPERATOR); + template.setUpdatedBy(resolveOperatorName()); template.setUpdatedTime(now); template.setDelFlag(ManifestManageConstants.DEL_FLAG_NORMAL); saveJsonFields(template); @@ -125,7 +129,7 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { template.setTemplateCode(dbTemplate.getTemplateCode()); template.setCreateBy(dbTemplate.getCreateBy()); template.setCreatedTime(dbTemplate.getCreatedTime()); - template.setUpdatedBy(ManifestManageConstants.DEFAULT_OPERATOR); + template.setUpdatedBy(resolveOperatorName()); template.setUpdatedTime(LocalDateTime.now()); template.setDelFlag(dbTemplate.getDelFlag()); saveJsonFields(template); @@ -152,7 +156,7 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { contractTemplateMapper.updateTemplateStatus( id, status, - ManifestManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), LocalDateTime.now() ); return getTemplateDetail(id); @@ -168,7 +172,7 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { } contractTemplateMapper.deleteTemplateById( id, - ManifestManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), LocalDateTime.now(), ManifestManageConstants.DEL_FLAG_DELETED ); @@ -195,7 +199,10 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { * 所以对于用户来说,能看到的模板是「发布范围包含用户所属组织或其任一祖先」的模板。 */ private List computeVisibleOrgIds() { - String userOrgId = adminSecurityManage.getUser().getSysOrgEntity().getId(); + SysUserEntity currentUser = adminSecurityManage.getUser(); + String userOrgId = currentUser == null || currentUser.getSysOrgEntity() == null + ? null + : currentUser.getSysOrgEntity().getId(); if (userOrgId == null) { return Collections.emptyList(); } @@ -216,6 +223,14 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { } List result = new ArrayList<>(visible); + if (result.isEmpty()) { + result.add(userOrgId); + MockSecurityUserRegistry.MockUserProfile profile = + mockSecurityUserRegistry.getProfileByUserId(currentUser == null ? null : currentUser.getId()); + if (profile != null && "business".equalsIgnoreCase(profile.systemType())) { + result.add("1"); + } + } log.debug("当前用户 orgId={}, 可见组织列表={}", userOrgId, result); return result; } @@ -300,6 +315,11 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { nodes.add(new OrgNode(73L, "浙港物流西部大区", 1L)); nodes.add(new OrgNode(74L, "宁波港铁路有限公司---重庆/城厢/白银市/西安/宜兴", 73L)); + // 业务端 mock 组织,保证切到业务用户时模板发布范围和可见范围能一起联动。 + nodes.add(new OrgNode(384L, "江苏远洋新世纪2供应链有限公司", 1L)); + nodes.add(new OrgNode(15L, "嘉兴兴港", 1L)); + nodes.add(new OrgNode(79L, "货代测试", 1L)); + return nodes; } @@ -313,6 +333,13 @@ public class ContractTemplateServiceImpl implements ContractTemplateService { /** * 内部组织节点 */ + private String resolveOperatorName() { + SysUserEntity currentUser = adminSecurityManage.getUser(); + return currentUser == null || currentUser.getUsername() == null || currentUser.getUsername().isBlank() + ? ManifestManageConstants.DEFAULT_OPERATOR + : currentUser.getUsername(); + } + private static class OrgNode { private final Long id; private final String orgName; diff --git a/src/main/java/com/nbport/zgwl/partner/service/PartnerManageServiceImpl.java b/src/main/java/com/nbport/zgwl/partner/service/PartnerManageServiceImpl.java index c3d52bf..9a40203 100644 --- a/src/main/java/com/nbport/zgwl/partner/service/PartnerManageServiceImpl.java +++ b/src/main/java/com/nbport/zgwl/partner/service/PartnerManageServiceImpl.java @@ -3,6 +3,7 @@ package com.nbport.zgwl.partner.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.nbport.zgwl.common.PageResult; import com.nbport.zgwl.contractlaunch.utils.JsonUtils; +import com.nbport.zgwl.entity.SysUserEntity; import com.nbport.zgwl.contractpush.dto.PushPayloadDTO; import com.nbport.zgwl.contractpush.service.DataCollectionPushService; import com.nbport.zgwl.exception.ServiceException; @@ -81,9 +82,9 @@ public class PartnerManageServiceImpl implements PartnerManageService { partner.setSyncTime(null); partner.setSyncMessage("新增后尚未同步"); partner.setOppositeStatus(PartnerManageConstants.OPPOSITE_STATUS_EFFECTUAL); - partner.setCreateBy(PartnerManageConstants.DEFAULT_OPERATOR); + partner.setCreateBy(resolveOperatorName()); partner.setCreateTime(now); - partner.setUpdateBy(PartnerManageConstants.DEFAULT_OPERATOR); + partner.setUpdateBy(resolveOperatorName()); partner.setUpdateTime(now); partner.setOrgId(resolveCurrentOrgId()); partner.setIsDeleted(PartnerManageConstants.PARTNER_IS_DELETED_NORMAL); @@ -117,14 +118,14 @@ public class PartnerManageServiceImpl implements PartnerManageService { partner.setSyncStatus(PartnerManageConstants.SYNC_STATUS_UNSYNCED); partner.setSyncTime(null); partner.setSyncMessage("信息已修改,待重新同步"); - partner.setUpdateBy(PartnerManageConstants.DEFAULT_OPERATOR); + partner.setUpdateBy(resolveOperatorName()); partner.setUpdateTime(now); partner.setOrgId(dbPartner.getOrgId() != null ? dbPartner.getOrgId() : resolveCurrentOrgId()); partner.setIsDeleted(PartnerManageConstants.PARTNER_IS_DELETED_NORMAL); partnerManageMapper.updatePartner(partner); partnerManageMapper.markPartnerContactsDeletedByPartnerId( partner.getCustomerSysid(), - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now, PartnerManageConstants.CONTACT_DEL_FLAG_DELETED); saveContacts(partner.getCustomerSysid(), partner.getContacts(), now); @@ -140,12 +141,12 @@ public class PartnerManageServiceImpl implements PartnerManageService { LocalDateTime now = LocalDateTime.now(); partnerManageMapper.markPartnerContactsDeletedByPartnerIds( customerSysids, - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now, PartnerManageConstants.CONTACT_DEL_FLAG_DELETED); partnerManageMapper.deletePartnerByIds( customerSysids, - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now, PartnerManageConstants.PARTNER_IS_DELETED_DELETED); } @@ -218,7 +219,7 @@ public class PartnerManageServiceImpl implements PartnerManageService { PartnerManageConstants.SYNC_STATUS_SYNCED, now, syncMessage, - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now); return selectPartnerById(customerSysid); @@ -286,7 +287,7 @@ public class PartnerManageServiceImpl implements PartnerManageService { PartnerManageConstants.SYNC_STATUS_SYNCED, now, syncMessage, - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now); successCount++; } @@ -338,9 +339,9 @@ public class PartnerManageServiceImpl implements PartnerManageService { partnerManageMapper.batchInsertPartnerContacts( contacts, - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now, - PartnerManageConstants.DEFAULT_OPERATOR, + resolveOperatorName(), now, PartnerManageConstants.CONTACT_DEL_FLAG_NORMAL); } @@ -370,10 +371,11 @@ public class PartnerManageServiceImpl implements PartnerManageService { } private Long resolveCurrentOrgId() { - if (adminSecurityManage.getUser() == null || adminSecurityManage.getUser().getSysOrgEntity() == null) { + SysUserEntity currentUser = adminSecurityManage.getUser(); + if (currentUser == null || currentUser.getSysOrgEntity() == null) { return null; } - String orgId = adminSecurityManage.getUser().getSysOrgEntity().getId(); + String orgId = currentUser.getSysOrgEntity().getId(); if (!StrUtilHelper.hasText(orgId)) { return null; } @@ -388,6 +390,13 @@ public class PartnerManageServiceImpl implements PartnerManageService { /** * 避免为了一个判空再引入新依赖,这里保留一个最小工具。 */ + private String resolveOperatorName() { + SysUserEntity currentUser = adminSecurityManage.getUser(); + return currentUser == null || !StrUtilHelper.hasText(currentUser.getUsername()) + ? PartnerManageConstants.DEFAULT_OPERATOR + : currentUser.getUsername(); + } + private static final class StrUtilHelper { private StrUtilHelper() { diff --git a/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java b/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java index 04640be..762ff6c 100644 --- a/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java +++ b/src/main/java/com/nbport/zgwl/utils/AdminSecurityManage.java @@ -1,13 +1,10 @@ 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; - /** * 登录用户获取组件 * @@ -18,125 +15,25 @@ import java.util.List; @Component public class AdminSecurityManage { - private static final String HEADER_MOCK_USER = "X-Mock-User"; - private final HttpServletRequest request; + private final MockSecurityUserRegistry mockSecurityUserRegistry; private final String defaultMockUser; public AdminSecurityManage(HttpServletRequest request, + MockSecurityUserRegistry mockSecurityUserRegistry, @Value("${mock.security.current-user:admin}") String defaultMockUser) { this.request = request; + this.mockSecurityUserRegistry = mockSecurityUserRegistry; 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(); + return mockSecurityUserRegistry.buildUser(resolveMockUserKey()); } - 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(orgId); - orgEntity.setOrgName(orgName); - orgEntity.setContactPhone("13800000000"); - orgEntity.setContactEmail("admin@test.com"); - orgEntity.setContactAddress("宁波市北仑区明州路288号"); - orgEntity.setRegisteredAddress("宁波市北仑区明州路288号"); - orgEntity.setBankName("中国工商银行宁波分行"); - orgEntity.setBankAccount("330201000000000001"); - orgEntity.setLegalRepresentative("张三"); - orgEntity.setCreditCode("91330200MAZGWL0001"); - orgEntity.setInvoiceTitleOptions(List.of("浙港物流平台有限公司")); - return orgEntity; + public String resolveMockUserKey() { + String headerValue = request == null ? null : request.getHeader(MockSecurityUserRegistry.HEADER_MOCK_USER); + String candidate = (headerValue == null || headerValue.isBlank()) ? defaultMockUser : headerValue; + return mockSecurityUserRegistry.normalizeUserKey(candidate); } } diff --git a/src/main/java/com/nbport/zgwl/utils/MockSecurityUserRegistry.java b/src/main/java/com/nbport/zgwl/utils/MockSecurityUserRegistry.java new file mode 100644 index 0000000..c8a609b --- /dev/null +++ b/src/main/java/com/nbport/zgwl/utils/MockSecurityUserRegistry.java @@ -0,0 +1,389 @@ +package com.nbport.zgwl.utils; + +import com.nbport.zgwl.auth.SysEnum; +import com.nbport.zgwl.entity.SysOrgEntity; +import com.nbport.zgwl.entity.SysUserEntity; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * 本地测试环境的 mock 用户注册表。 + * + * 统一管理: + * 1. 前端可切换的测试用户列表 + * 2. AdminSecurityManage 返回的当前登录用户 + * 3. AuthManager / SecurityManager 需要识别的系统访问能力 + * + * 正式环境接入真实登录态后,可整体替换掉这里的实现, + * 不影响业务代码里对 AdminSecurityManage / AuthManager 的调用方式。 + */ +@Component +public class MockSecurityUserRegistry { + + public static final String HEADER_MOCK_USER = "X-Mock-User"; + public static final String DEFAULT_USER_KEY = "admin"; + + private static final String ROOT_ORG_ID = "1"; + private static final String ROOT_ORG_NAME = "浙江海港物流集团有限公司X"; + private static final String DEFAULT_ADDRESS = "宁波市北仑区明州路288号"; + private static final String DEFAULT_BANK = "中国工商银行宁波分行"; + private static final String DEFAULT_BANK_ACCOUNT = "330201000000000001"; + private static final String DEFAULT_LEGAL_REPRESENTATIVE = "张三"; + private static final String DEFAULT_PHONE = "13800000000"; + private static final String DEFAULT_EMAIL_DOMAIN = "@test.com"; + + private final Map profilesByKey; + private final Map profilesByUserId; + + public MockSecurityUserRegistry() { + LinkedHashMap profiles = new LinkedHashMap<>(); + + register(profiles, new MockUserProfile( + DEFAULT_USER_KEY, + 1L, + "admin", + "平台超管", + "platform", + ROOT_ORG_ID, + ROOT_ORG_NAME, + "平台管理部", + 1L, + "ALL", + true, + EnumSet.of(SysEnum.MANAGE, SysEnum.BUSINESS), + List.of("SUPER_ADMIN", "MANAGE_ADMIN", "BUSINESS_ADMIN") + )); + + register(profiles, new MockUserProfile( + "manage_yongkang", + 101L, + "manage_yongkang", + "管理端-永康陆港", + "manage", + "47", + "永康陆港国际物流有限公司", + "永康业务管理部", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.MANAGE), + List.of("MANAGE_ADMIN") + )); + register(profiles, new MockUserProfile( + "manage_zhuji", + 102L, + "manage_zhuji", + "管理端-诸暨业务点", + "manage", + "48", + "宁波港国际物流有限公司诸暨业务点", + "诸暨业务管理部", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.MANAGE), + List.of("MANAGE_ADMIN") + )); + register(profiles, new MockUserProfile( + "manage_zhongbei", + 103L, + "manage_zhongbei", + "管理端-浙中北大区", + "manage", + "58", + "浙港物流浙中北大区", + "浙中北区域管理部", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.MANAGE), + List.of("MANAGE_ADMIN") + )); + register(profiles, new MockUserProfile( + "manage_jiaxing_branch", + 104L, + "manage_jiaxing_branch", + "管理端-嘉兴分公司", + "manage", + "59", + "浙江兴港国际货运代理有限公司嘉兴分公司", + "嘉兴分公司", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.MANAGE), + List.of("MANAGE_ADMIN") + )); + register(profiles, new MockUserProfile( + "manage_shaoxing_branch", + 105L, + "manage_shaoxing_branch", + "管理端-绍兴分公司", + "manage", + "60", + "宁波港铁路有限公司绍兴分公司", + "绍兴分公司", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.MANAGE), + List.of("MANAGE_ADMIN") + )); + + register(profiles, new MockUserProfile( + "business_jsys", + 201L, + "business_jsys", + "业务端-江苏远洋", + "business", + "384", + "江苏远洋新世纪2供应链有限公司", + "业务一部", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.BUSINESS), + List.of("BUSINESS_ADMIN") + )); + register(profiles, new MockUserProfile( + "business_jxxg", + 202L, + "business_jxxg", + "业务端-嘉兴兴港", + "business", + "15", + "嘉兴兴港", + "业务二部", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.BUSINESS), + List.of("BUSINESS_ADMIN") + )); + register(profiles, new MockUserProfile( + "business_hdcs", + 203L, + "business_hdcs", + "业务端-货代测试", + "business", + "79", + "货代测试", + "测试业务组", + 1L, + "COMPANY", + false, + EnumSet.of(SysEnum.BUSINESS), + List.of("BUSINESS_ADMIN") + )); + register(profiles, new MockUserProfile( + "business_jsys_user", + 204L, + "business_jsys_user", + "业务端-江苏远洋普通用户", + "business", + "384", + "江苏远洋新世纪2供应链有限公司", + "业务一部", + 0L, + "SELF", + false, + EnumSet.of(SysEnum.BUSINESS), + List.of("BUSINESS_USER") + )); + + this.profilesByKey = Collections.unmodifiableMap(profiles); + + LinkedHashMap byUserId = new LinkedHashMap<>(); + for (MockUserProfile profile : profiles.values()) { + byUserId.put(profile.userId(), profile); + } + this.profilesByUserId = Collections.unmodifiableMap(byUserId); + } + + private void register(Map profiles, MockUserProfile profile) { + profiles.put(profile.key(), profile); + } + + public String normalizeUserKey(String candidate) { + if (candidate == null || candidate.isBlank()) { + return DEFAULT_USER_KEY; + } + String normalized = candidate.trim().toLowerCase(Locale.ROOT); + return profilesByKey.containsKey(normalized) ? normalized : DEFAULT_USER_KEY; + } + + public SysUserEntity buildUser(String candidate) { + MockUserProfile profile = profilesByKey.get(normalizeUserKey(candidate)); + return toUserEntity(profile); + } + + public MockUserProfile getProfile(String candidate) { + return profilesByKey.get(normalizeUserKey(candidate)); + } + + public MockUserProfile getProfileByUserId(Long userId) { + return userId == null ? null : profilesByUserId.get(userId); + } + + public boolean isSuperAdmin(Long userId) { + MockUserProfile profile = getProfileByUserId(userId); + return profile != null && profile.superAdmin(); + } + + public boolean canAccessSystem(Long userId, SysEnum sysEnum) { + if (userId == null || sysEnum == null) { + return false; + } + MockUserProfile profile = getProfileByUserId(userId); + return profile != null && profile.accessSystems().contains(sysEnum); + } + + public List listUserOptions() { + List options = new ArrayList<>(); + for (MockUserProfile profile : profilesByKey.values()) { + options.add(new MockUserOptionDto( + profile.key(), + profile.displayName(), + profile.systemType(), + profile.username(), + profile.userId(), + profile.orgId(), + profile.orgName(), + profile.deptName(), + profile.superAdmin(), + new ArrayList<>(profile.accessSystems()), + profile.dataPermission() + )); + } + return options; + } + + public MockCurrentUserDto buildCurrentUserDto(String candidate) { + MockUserProfile profile = getProfile(candidate); + return new MockCurrentUserDto( + profile.key(), + profile.displayName(), + profile.systemType(), + profile.username(), + profile.userId(), + profile.orgId(), + profile.orgName(), + profile.deptName(), + profile.superAdmin(), + new ArrayList<>(profile.accessSystems()), + profile.dataPermission() + ); + } + + private SysUserEntity toUserEntity(MockUserProfile profile) { + SysUserEntity user = new SysUserEntity(); + user.setId(profile.userId()); + user.setUsername(profile.username()); + user.setMobilePhone(buildMobile(profile.userId())); + user.setEmail(profile.username() + DEFAULT_EMAIL_DOMAIN); + user.setSysOrgEntity(buildOrg(profile.orgId(), profile.orgName(), profile.systemType())); + user.setDeptName(profile.deptName()); + user.setAdminFlag(profile.adminFlag()); + user.setDataPermission(profile.dataPermission()); + user.setRoleCodes(new ArrayList<>(profile.roleCodes())); + return user; + } + + private SysOrgEntity buildOrg(String orgId, String orgName, String systemType) { + SysOrgEntity orgEntity = new SysOrgEntity(); + orgEntity.setId(orgId); + orgEntity.setOrgName(orgName); + orgEntity.setContactPhone(DEFAULT_PHONE); + orgEntity.setContactEmail(buildOrgEmail(orgId, systemType)); + orgEntity.setContactAddress(DEFAULT_ADDRESS); + orgEntity.setRegisteredAddress(DEFAULT_ADDRESS); + orgEntity.setBankName(DEFAULT_BANK); + orgEntity.setBankAccount(DEFAULT_BANK_ACCOUNT); + orgEntity.setLegalRepresentative(DEFAULT_LEGAL_REPRESENTATIVE); + orgEntity.setCreditCode(buildCreditCode(orgId, systemType)); + orgEntity.setInvoiceTitleOptions(List.of(orgName, ROOT_ORG_NAME)); + return orgEntity; + } + + private String buildCreditCode(String orgId, String systemType) { + String prefix = "manage".equalsIgnoreCase(systemType) ? "91330200MANAGE" : "91330200BUSIN"; + String suffix = String.format(Locale.ROOT, "%04d", parseNumericId(orgId)); + return prefix + suffix; + } + + private String buildOrgEmail(String orgId, String systemType) { + String prefix = "manage".equalsIgnoreCase(systemType) ? "manage" : "business"; + return prefix + "." + orgId + DEFAULT_EMAIL_DOMAIN; + } + + private String buildMobile(Long userId) { + long numeric = userId == null ? 0L : userId; + return String.format(Locale.ROOT, "138%08d", numeric % 100000000L); + } + + private int parseNumericId(String orgId) { + if (orgId == null) { + return 0; + } + try { + return Integer.parseInt(orgId); + } catch (NumberFormatException ex) { + return 0; + } + } + + public record MockUserProfile( + String key, + Long userId, + String username, + String displayName, + String systemType, + String orgId, + String orgName, + String deptName, + Long adminFlag, + String dataPermission, + boolean superAdmin, + Set accessSystems, + List roleCodes + ) { + } + + public record MockUserOptionDto( + String key, + String displayName, + String systemType, + String username, + Long userId, + String orgId, + String orgName, + String deptName, + boolean superAdmin, + List accessSystems, + String dataPermission + ) { + } + + public record MockCurrentUserDto( + String key, + String displayName, + String systemType, + String username, + Long userId, + String orgId, + String orgName, + String deptName, + boolean superAdmin, + List accessSystems, + String dataPermission + ) { + } +}