cloud-server-account/src/main/java/cn/mb/cloud/common/sentinel/fallback/DefaultFeignFallback.java
@@ -18,12 +18,11 @@ import java.util.Set; /** * Account-side replacement for the common Sentinel Feign fallback. * 账户服务对公共 Sentinel Feign 降级处理的替代实现。 * * <p>The dependency implementation casts {@link Method#getGenericReturnType()} * directly to {@link Class}. That fails for generic Feign methods such as * {@code List<IntegralCommodity>}; resolve the raw type first so a proper * empty fallback value can be returned.</p> * <p>依赖中的实现会将 {@link Method#getGenericReturnType()} 直接转换为 * {@link Class}。对于 {@code List<IntegralCommodity>} 等泛型 Feign 方法会转换失败; * 此处先解析原始类型,以便返回正确的空降级值。</p> */ public class DefaultFeignFallback<T> implements MethodInterceptor { private static final Logger log = LoggerFactory.getLogger(DefaultFeignFallback.class); cloud-server-account/src/main/java/com/dsh/privacy/SensitiveDataMaskingAdvice.java
@@ -18,14 +18,13 @@ import java.util.Map; /** * Response boundary protection for personal phone and identity-card data. * It is deliberately based on field names so it also covers ad-hoc Maps * produced by reporting APIs. * 手机号和身份证号等个人敏感数据的响应边界保护。 * 基于字段名进行识别,因此也可覆盖报表接口临时生成的 Map 数据。 */ @ControllerAdvice public class SensitiveDataMaskingAdvice implements ResponseBodyAdvice<Object> { private static final String INTERNAL_SENSITIVE_ACCESS = "X-Internal-Sensitive-Access"; /** APP endpoints whose clients receive original values and mask only when displaying them. */ /** 客户端接收原始数据、仅在展示时脱敏的 APP 接口。 */ private static final Set<String> APP_UNMASKED_PATHS = new HashSet<String>(Arrays.asList( "/base/exploreWP/storeDetail", "/base/exploreWP/customerList" @@ -40,9 +39,8 @@ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { String path = request.getRequestURI(); // Internal management calls require their sensitive-access header. The // two explicitly listed APP endpoints return original values for // client-side display masking; all other account responses are masked. // 内部管理调用必须携带敏感数据访问请求头。明确列出的两个 APP 接口返回原始数据, // 由客户端在展示时脱敏;其他账户服务响应均进行脱敏。 return !(APP_UNMASKED_PATHS.contains(path) || (path.startsWith("/internal/sensitive/") && "true".equalsIgnoreCase(request.getHeader(INTERNAL_SENSITIVE_ACCESS)))); cloud-server-competition/src/main/java/com/dsh/competition/enums/CompetitionStatusEnum.java
@@ -5,11 +5,19 @@ */ public enum CompetitionStatusEnum { /** 未开始。 */ NOT_STARTED(1), /** 进行中。 */ IN_PROGRESS(2), /** 已结束。 */ ENDED(3), /** 已取消。 */ CANCELED(4); /** 状态编码。 */ private final Integer code; CompetitionStatusEnum(Integer code) { cloud-server-gateway/src/main/java/cn/mb/cloud/gateway/filter/SensitiveDataMaskingGlobalFilter.java
@@ -21,15 +21,16 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** Final API boundary for APP traffic, including responses returned by every service. */ /** * APP 流量的最终接口边界,覆盖各服务返回的响应数据。 */ @Component public class SensitiveDataMaskingGlobalFilter implements GlobalFilter, Ordered { private static final Pattern FIELD = Pattern.compile("(?i)(\\\"(?:[a-z]*phone|[a-z]*mobile|telephone|tel)\\\"\\s*:\\s*\\\")([^\\\"]*)(\\\")"); private static final Pattern IDCARD = Pattern.compile("(?i)(\\\"(?:[a-z]*idcard|[a-z]*identitycard|identitynumber|idnumber)\\\"\\s*:\\s*\\\")([^\\\"]*)(\\\")"); /** * APP has to receive these values so it can apply its own display masking. * Keep this list exact: all other routes continue to be protected at the * gateway boundary. * APP 需要获取原始数据后自行进行展示脱敏。 * 请保持此列表精确,其他路由仍由网关边界进行脱敏保护。 */ private static final Set<String> APP_UNMASKED_PATHS = new HashSet<String>(Arrays.asList( "/other/api/site/queryMySiteById", @@ -44,9 +45,8 @@ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String path = exchange.getRequest().getURI().getPath(); // /system/sensitive enforces its own admin check and audit. The APP // paths below deliberately return their original fields for client-side // display masking; every other response remains gateway-masked. // /system/sensitive 会自行完成管理员校验和审计。以下 APP 路径有意返回原始字段, // 由客户端在展示时脱敏;其他所有响应仍由网关脱敏。 if (path.startsWith("/system/sensitive/") || APP_UNMASKED_PATHS.contains(path)) return chain.filter(exchange); ServerHttpResponseDecorator decorated = new ServerHttpResponseDecorator(exchange.getResponse()) { @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/model/UserCouponPayment.java
@@ -8,12 +8,26 @@ /** 优惠券现金购买成功订单的统计传输对象。 */ @Data public class UserCouponPayment { /** 主键。 */ private Long id; /** 优惠券 ID。 */ private Integer couponId; /** 用户 ID。 */ private Integer userId; /** 支付状态(1:待支付;2:已支付)。 */ private Integer status; /** 支付方式(1:积分兑换;2:积分加现金)。 */ private Integer payType; /** 现金支付金额。 */ private Double cash; /** 支付时间。 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date paymentTime; } cloud-server-management/src/main/java/com/dsh/course/mapper/AppGuideBannerMapper.java
@@ -1,4 +1,12 @@ package com.dsh.course.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dsh.course.entity.AppGuideBanner; public interface AppGuideBannerMapper extends BaseMapper<AppGuideBanner> {} /** * APP 下载引导宣传图数据访问层。 * * <p>继承 {@link BaseMapper},提供 {@link AppGuideBanner} 的基础增删改查能力。</p> */ public interface AppGuideBannerMapper extends BaseMapper<AppGuideBanner> { } cloud-server-management/src/main/java/com/dsh/course/mapper/AppGuideConfigMapper.java
@@ -1,4 +1,12 @@ package com.dsh.course.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dsh.course.entity.AppGuideConfig; public interface AppGuideConfigMapper extends BaseMapper<AppGuideConfig> {} /** * APP 下载引导配置数据访问层。 * * <p>继承 {@link BaseMapper},提供 {@link AppGuideConfig} 的基础增删改查能力。</p> */ public interface AppGuideConfigMapper extends BaseMapper<AppGuideConfig> { } cloud-server-management/src/main/java/com/dsh/course/mapper/QrLinkMapper.java
@@ -1,4 +1,12 @@ package com.dsh.course.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dsh.course.entity.QrLink; public interface QrLinkMapper extends BaseMapper<QrLink> {} /** * 二维码短链接数据访问层。 * * <p>继承 {@link BaseMapper},提供 {@link QrLink} 的基础增删改查能力。</p> */ public interface QrLinkMapper extends BaseMapper<QrLink> { } cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/SensitiveDataController.java
@@ -28,7 +28,11 @@ import java.util.Map; import java.util.UUID; /** Deliberately narrow, auditable unmasking capability for the admin account. */ /** * 超级管理员敏感信息查询接口。 * * <p>仅提供范围明确、可审计的敏感信息明文查询能力。</p> */ @RestController @RequestMapping("/system/sensitive") public class SensitiveDataController { @@ -40,6 +44,12 @@ @Resource private RefereeClient refereeClient; @Resource private TOperatorService operatorService; /** * 查询 APP 用户的敏感信息。 * * @param id APP 用户 ID * @return 用户基本信息及敏感字段;用户不存在时返回 {@code null} */ @GetMapping("/app-user/{id}") public Map<String, Object> appUser(@PathVariable Integer id) { assertAdmin(); @@ -48,6 +58,12 @@ return result; } /** * 查询后台员工的敏感信息。 * * @param id 员工用户 ID * @return 员工基本信息及敏感字段;员工不存在时返回 {@code null} */ @GetMapping("/employee/{id}") public Map<String, Object> employee(@PathVariable Integer id) { assertAdmin(); @@ -64,6 +80,12 @@ return result; } /** * 查询学员的敏感信息。 * * @param id 学员 ID * @return 学员基本信息及敏感字段;学员不存在时返回 {@code null} */ @GetMapping("/student/{id}") public Map<String, Object> student(@PathVariable Integer id) { assertAdmin(); @@ -73,10 +95,13 @@ } /** * 预约管理查看关联预约人的敏感信息。 * 根据预约记录查询关联预约人的敏感信息。 * * <p>仅通过预约记录定位用户,避免前端以任意用户 ID 查询;该接口保留在 * /system/sensitive 路径下,以使用全局的脱敏豁免和网关放行策略。</p> * * @param bookingId 预约记录 ID * @return 预约关联用户的基本信息及敏感字段;预约或用户不存在时返回 {@code null} */ @GetMapping("/booking/{bookingId}") public Map<String, Object> booking(@PathVariable Integer bookingId) { @@ -92,6 +117,12 @@ return result; } /** * 查询教练的敏感信息。 * * @param id 教练 ID * @return 教练基本信息及敏感字段;教练不存在时返回 {@code null} */ @GetMapping("/coach/{id}") public Map<String, Object> coach(@PathVariable Integer id) { assertAdmin(); @@ -112,6 +143,12 @@ return result; } /** * 查询裁判的敏感信息。 * * @param id 裁判 ID * @return 裁判基本信息及敏感字段;裁判不存在时返回 {@code null} */ @GetMapping("/referee/{id}") public Map<String, Object> referee(@PathVariable Integer id) { assertAdmin(); @@ -136,6 +173,12 @@ return result; } /** * 查询运营商关联员工的敏感信息。 * * @param id 运营商 ID * @return 关联员工的基本信息及敏感字段;运营商或员工不存在时返回 {@code null} */ @GetMapping("/operator/{id}") public Map<String, Object> operator(@PathVariable Integer id) { assertAdmin();