feat(mobile): align employee practice screens for release

This commit is contained in:
2026-07-15 11:23:08 +08:00
parent 3541aab3fe
commit eacf1a0aea
16 changed files with 307 additions and 191 deletions
@@ -62,11 +62,16 @@ public class CaptchaController {
/**
* 演示/开发兜底:配置后不真发短信,验证码固定为该值,把短信通道从演示关键路径摘掉。
* prod profile 代码级禁用固定验证码,不接受配置开关绕过。
*/
@Value("${aihr.sms.dev-fixed-code:}")
private String smsDevFixedCode;
/**
* 生产固定码必须显式开启,默认关闭,便于试点期按需启停。
*/
@Value("${aihr.sms.prod-fixed-code-enabled:false}")
private boolean smsProdFixedCodeEnabled;
private final Environment environment;
/**
@@ -80,15 +85,19 @@ public class CaptchaController {
@NotBlank(message = "{user.phonenumber.not.blank}")
@Pattern(regexp = RegexConstants.MOBILE, message = "{user.mobile.phone.number.not.valid}") String phonenumber) {
String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
boolean fixedCodeEnabled = StringUtils.isNotBlank(smsDevFixedCode)
&& !environment.acceptsProfiles(Profiles.of("prod"));
boolean prodProfile = environment.acceptsProfiles(Profiles.of("prod"));
boolean fixedCodeEnabled = shouldUseFixedSmsCode(
smsDevFixedCode,
prodProfile,
smsProdFixedCodeEnabled
);
if (fixedCodeEnabled) {
log.warn("aihr.sms.dev-fixed-code 已启用,短信验证码走固定码,未真实发送短信");
RedisUtils.setCacheObject(key, smsDevFixedCode, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
return R.ok();
}
if (StringUtils.isBlank(smsLoginTemplateId)) {
return R.fail("短信模板未配置:请设置 aihr.sms.login-template-id 或开发环境设置 aihr.sms.dev-fixed-code");
return R.fail("短信模板未配置:请设置 aihr.sms.login-template-id 或启用固定验证码配置");
}
String code = RandomUtil.randomNumbers(4);
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
@@ -103,6 +112,10 @@ public class CaptchaController {
return R.ok();
}
static boolean shouldUseFixedSmsCode(String fixedCode, boolean prodProfile, boolean prodFixedCodeEnabled) {
return StringUtils.isNotBlank(fixedCode) && (!prodProfile || prodFixedCodeEnabled);
}
/**
* 邮箱验证码
*
@@ -164,6 +164,9 @@ aihr:
store-display-fields: false
sms:
login-template-id: ${AIHR_SMS_LOGIN_TEMPLATE_ID:}
# 试点期固定验证码:生产默认关闭,需同时显式配置固定码与开关
dev-fixed-code: ${AIHR_SMS_DEV_FIXED_CODE:}
prod-fixed-code-enabled: ${AIHR_SMS_PROD_FIXED_CODE_ENABLED:false}
sms:
# 配置源类型用于标定配置来源(interface,yaml)
config-type: yaml
@@ -3,9 +3,6 @@ package org.dromara.web.controller;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -13,15 +10,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
class CaptchaControllerSecurityTest {
@Test
void fixedSmsCodeIsDisabledInProdWithoutOverride() throws Exception {
Path source = Path.of("src/main/java/org/dromara/web/controller/CaptchaController.java");
if (!Files.exists(source)) {
source = Path.of("ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java");
}
String code = Files.readString(source);
assertTrue(code.contains("!environment.acceptsProfiles(Profiles.of(\"prod\"))"));
assertFalse(code.contains("smsDemoFixedCodeEnabled"));
assertFalse(code.contains("demo-fixed-code-enabled"));
void fixedSmsCodeRequiresExplicitProductionOptIn() {
assertTrue(CaptchaController.shouldUseFixedSmsCode("123456", false, false));
assertFalse(CaptchaController.shouldUseFixedSmsCode("123456", true, false));
assertTrue(CaptchaController.shouldUseFixedSmsCode("123456", true, true));
assertFalse(CaptchaController.shouldUseFixedSmsCode("", true, true));
}
}