fix(aihr): sanitize mobile review responses

This commit is contained in:
2026-07-15 01:45:57 +08:00
parent 78600ff509
commit 03a691c770
5 changed files with 13 additions and 10 deletions
@@ -26,6 +26,7 @@ import org.dromara.aihr.domain.vo.AihrMobileDto.HomeResponse;
import org.dromara.aihr.domain.vo.AihrMobileDto.IdentityResponse;
import org.dromara.aihr.service.AihrOrgSyncService;
import org.dromara.aihr.service.AihrMobileSeedService;
import org.dromara.aihr.service.AihrSensitiveText;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.enums.UserType;
@@ -300,10 +301,10 @@ public class AihrMobileController {
data.put("scene", detail.scene());
data.put("score", detail.score());
data.put("status", detail.status());
data.put("summary", detail.summary());
data.put("mentorRewrite", detail.mentorRewrite());
data.put("aiComment", detail.aiComment());
data.put("reviewAdvice", detail.reviewAdvice());
data.put("summary", maskSensitiveText(detail.summary()));
data.put("mentorRewrite", maskSensitiveText(detail.mentorRewrite()));
data.put("aiComment", maskSensitiveText(detail.aiComment()));
data.put("reviewAdvice", maskSensitiveText(detail.reviewAdvice()));
data.put("incentivePoint", detail.incentivePoint());
data.put("scoreItems", detail.scoreItems().stream().map(item -> Map.of(
"label", item.label(),
@@ -334,9 +335,6 @@ public class AihrMobileController {
}
private static String maskSensitiveText(String value) {
if (value == null || value.isBlank()) {
return value;
}
return value.replaceAll("(1\\d{2})\\d{4}(\\d{4})", "$1****$2");
return AihrSensitiveText.forModel(value);
}
}
@@ -8,7 +8,7 @@ import java.util.regex.Pattern;
* <p>这不是正式的数据分类引擎;它只负责拦截当前一期已知的手机号、邮箱、房号和带称谓姓名,
* 避免“入库已脱敏、出境仍是原文”的边界漏洞。正式试点仍需配套供应商留存、审计和删除合同。</p>
*/
final class AihrSensitiveText {
public final class AihrSensitiveText {
// 保持案例服务既有展示口径:手机号保留前 4 位和后 4 位,中间统一遮蔽。
private static final Pattern PHONE = Pattern.compile("(?<!\\d)(1[3-9]\\d{2})\\d{3}(\\d{4})(?!\\d)");
@@ -20,7 +20,7 @@ final class AihrSensitiveText {
private AihrSensitiveText() {
}
static String forModel(String text) {
public static String forModel(String text) {
if (text == null || text.isBlank()) {
return text;
}
@@ -46,6 +46,7 @@ class AihrSensitiveTextTest {
String caseSource = Files.readString(source("AihrCaseService.java"));
String practiceLlmSource = Files.readString(source("AihrPracticeLlmService.java"));
String speechControllerSource = Files.readString(controllerSource("AihrSpeechController.java"));
String mobileControllerSource = Files.readString(controllerSource("AihrMobileController.java"));
assertTrue(modelSource.contains("AihrSensitiveText.forModel(prompt)"));
assertTrue(modelSource.contains("prompt_tokens"));
@@ -69,6 +70,7 @@ class AihrSensitiveTextTest {
assertTrue(videoSource.contains("处理输出已隐藏"));
assertTrue(caseSource.contains("case audio upload failed(处理错误已隐藏)"));
assertTrue(practiceLlmSource.contains("practice score parse failed, falls back to seed(处理错误已隐藏)"));
assertTrue(mobileControllerSource.contains("return AihrSensitiveText.forModel(value)"));
}
@Test