package com.dsh.guns.modular.system.controller.system; import com.dsh.course.feignClient.account.AppUserClient; import com.dsh.course.feignClient.account.CoachClient; import com.dsh.course.feignClient.account.RefereeClient; import com.dsh.course.feignClient.account.model.CoachSerchVO; import com.dsh.course.feignClient.account.model.RefereeList; import com.dsh.guns.config.UserExt; import com.dsh.guns.core.common.exception.BizExceptionEnum; import com.dsh.guns.core.exception.GunsException; import com.dsh.guns.modular.system.audit.ManagementAuditWriter; import com.dsh.guns.modular.system.model.SiteBooking; import com.dsh.guns.modular.system.model.TOperator; import com.dsh.guns.modular.system.model.CoachQuery; import com.dsh.guns.modular.system.service.ISiteBookingService; import com.dsh.guns.modular.system.service.TOperatorService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.dsh.guns.modular.system.model.User; import com.dsh.guns.modular.system.service.IUserService; import javax.annotation.Resource; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; /** * 超级管理员敏感信息查询接口。 * *

仅提供范围明确、可审计的敏感信息明文查询能力。

*/ @RestController @RequestMapping("/system/sensitive") public class SensitiveDataController { @Resource private AppUserClient appUserClient; @Resource private ManagementAuditWriter auditWriter; @Resource private IUserService userService; @Resource private ISiteBookingService siteBookingService; @Resource private CoachClient coachClient; @Resource private RefereeClient refereeClient; @Resource private TOperatorService operatorService; /** * 查询 APP 用户的敏感信息。 * * @param id APP 用户 ID * @return 用户基本信息及敏感字段;用户不存在时返回 {@code null} */ @GetMapping("/app-user/{id}") public Map appUser(@PathVariable Integer id) { assertAdmin(); Map result = appUserClient.sensitiveAppUser(id); writeAudit("app-user", id, userName(result), result == null ? "NOT_FOUND" : "SUCCESS"); return result; } /** * 查询后台员工的敏感信息。 * * @param id 员工用户 ID * @return 员工基本信息及敏感字段;员工不存在时返回 {@code null} */ @GetMapping("/employee/{id}") public Map employee(@PathVariable Integer id) { assertAdmin(); User employee = userService.getById(id); Map result = null; if (employee != null) { result = new HashMap(); result.put("id", employee.getId()); result.put("name", employee.getName()); result.put("phone", employee.getPhone()); result.put("idCard", employee.getIdCard()); } writeAudit("employee", id, employee == null ? null : employee.getName(), result == null ? "NOT_FOUND" : "SUCCESS"); return result; } /** * 查询学员的敏感信息。 * * @param id 学员 ID * @return 学员基本信息及敏感字段;学员不存在时返回 {@code null} */ @GetMapping("/student/{id}") public Map student(@PathVariable Integer id) { assertAdmin(); Map result = appUserClient.sensitiveStudent(id); writeAudit("student", id, userName(result), result == null ? "NOT_FOUND" : "SUCCESS"); return result; } /** * 根据预约记录查询关联预约人的敏感信息。 * *

仅通过预约记录定位用户,避免前端以任意用户 ID 查询;该接口保留在 * /system/sensitive 路径下,以使用全局的脱敏豁免和网关放行策略。

* * @param bookingId 预约记录 ID * @return 预约关联用户的基本信息及敏感字段;预约或用户不存在时返回 {@code null} */ @GetMapping("/booking/{bookingId}") public Map booking(@PathVariable Integer bookingId) { assertAdmin(); SiteBooking booking = siteBookingService.getById(bookingId); if (booking == null || booking.getAppUserId() == null) { writeBookingAudit(bookingId, booking, null, "NOT_FOUND"); return null; } Map result = appUserClient.sensitiveAppUser(booking.getAppUserId()); writeBookingAudit(bookingId, booking, result, result == null ? "NOT_FOUND" : "SUCCESS"); return result; } /** * 查询教练的敏感信息。 * * @param id 教练 ID * @return 教练基本信息及敏感字段;教练不存在时返回 {@code null} */ @GetMapping("/coach/{id}") public Map coach(@PathVariable Integer id) { assertAdmin(); // 与教练管理页 /tCoach/list 使用同一个查询入口,确保返回字段和数据权限一致。 CoachQuery query = new CoachQuery(); query.setId(id); List coaches = coachClient.listAll(query); CoachSerchVO coach = coaches == null || coaches.isEmpty() ? null : coaches.get(0); Map result = null; if (coach != null) { result = new HashMap(); result.put("id", coach.getId()); result.put("name", coach.getName()); result.put("phone", coach.getPhone()); result.put("idCard", coach.getIdcard()); } writeAudit("coach", id, coach == null ? null : coach.getName(), result == null ? "NOT_FOUND" : "SUCCESS"); return result; } /** * 查询裁判的敏感信息。 * * @param id 裁判 ID * @return 裁判基本信息及敏感字段;裁判不存在时返回 {@code null} */ @GetMapping("/referee/{id}") public Map referee(@PathVariable Integer id) { assertAdmin(); // 使用裁判管理页 /referee/listAll 对应的列表查询接口精确查询该裁判。 RefereeList query = new RefereeList(); query.setId(id); query.setOffset(0); query.setLimit(1); Map listResult = refereeClient.getRefereeList(query); List> referees = listResult == null ? null : (List>) listResult.get("rows"); Map referee = referees == null || referees.isEmpty() ? null : referees.get(0); Map result = null; if (referee != null) { result = new HashMap(); result.put("id", referee.get("id")); result.put("name", referee.get("name")); result.put("phone", referee.get("phone")); } writeAudit("referee", id, referee == null ? null : String.valueOf(referee.get("name")), result == null ? "NOT_FOUND" : "SUCCESS"); return result; } /** * 查询运营商关联员工的敏感信息。 * * @param id 运营商 ID * @return 关联员工的基本信息及敏感字段;运营商或员工不存在时返回 {@code null} */ @GetMapping("/operator/{id}") public Map operator(@PathVariable Integer id) { assertAdmin(); TOperator operator = operatorService.getById(id); User employee = operator == null ? null : userService.getById(operator.getUserId()); Map result = null; if (employee != null) { result = new HashMap(); result.put("id", employee.getId()); result.put("name", employee.getName()); result.put("phone", employee.getPhone()); result.put("idCard", employee.getIdCard()); } writeAudit("operator", id, operator == null ? null : operator.getName(), result == null ? "NOT_FOUND" : "SUCCESS"); return result; } private void assertAdmin() { if (UserExt.getUser() == null || !"admin".equalsIgnoreCase(UserExt.getUser().getAccount())) { throw new GunsException(BizExceptionEnum.NO_PERMITION); } } private void writeAudit(String resource, Integer targetUserId, String targetUserName, String result) { Map audit = new HashMap(); audit.put("traceId", UUID.randomUUID().toString().replace("-", "")); audit.put("sourceService", "mb-cloud-management"); audit.put("sourceType", "HTTP"); audit.put("operationType", "VIEW_SENSITIVE"); audit.put("riskLevel", "SENSITIVE"); audit.put("operationName", "超级管理员查看敏感信息"); audit.put("requestMethod", "GET"); audit.put("requestUri", "/system/sensitive/" + resource + "/" + targetUserId); // 敏感信息访问需同时记录对象名称,避免日志中只有无法识别的 ID。 audit.put("requestParams", "targetUserId=" + targetUserId + ", targetUserName=" + (targetUserName == null ? "-" : targetUserName)); audit.put("userId", UserExt.getUser().getId()); audit.put("userAccount", "admin"); audit.put("result", result); audit.put("createdAt", new Date()); auditWriter.append(audit); } private void writeBookingAudit(Integer bookingId, SiteBooking booking, Map user, String result) { Map audit = new HashMap(); audit.put("traceId", UUID.randomUUID().toString().replace("-", "")); audit.put("sourceService", "mb-cloud-management"); audit.put("sourceType", "HTTP"); audit.put("operationType", "VIEW_SENSITIVE"); audit.put("riskLevel", "SENSITIVE"); audit.put("operationName", "超级管理员从预约管理查看敏感信息"); audit.put("requestMethod", "GET"); audit.put("requestUri", "/system/sensitive/booking/" + bookingId); // 审计记录只存预约、用户标识和查询结果,绝不写入手机号、身份证号等明文。 audit.put("requestParams", "bookingId=" + bookingId + ", appUserId=" + (booking == null || booking.getAppUserId() == null ? "-" : booking.getAppUserId()) + ", targetUserName=" + (userName(user) == null ? "-" : userName(user))); audit.put("userId", UserExt.getUser().getId()); audit.put("userAccount", "admin"); audit.put("result", result); audit.put("createdAt", new Date()); auditWriter.append(audit); } private String userName(Map user) { if (user == null || user.get("name") == null) return null; return String.valueOf(user.get("name")); } }