From 3a3809b6610885fae3a745eee2fa46c9cc25cb61 Mon Sep 17 00:00:00 2001 From: Timi Date: Fri, 21 Aug 2026 21:54:09 +0800 Subject: [PATCH] fix gao user invite --- .../implement/SmsServiceImplement.java | 3 +++ .../gao/controller/GaoUserController.java | 4 +--- .../gao/service/GaoUserInviteService.java | 4 +++- .../GaoUserInviteServiceImplement.java | 24 +++++++++++++++---- .../gao/vo/GaoUserInviteRegisterRequest.java | 21 ++++++++++++---- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/imyeyu/api/modules/common/service/implement/SmsServiceImplement.java b/src/main/java/com/imyeyu/api/modules/common/service/implement/SmsServiceImplement.java index 1f1f0d9..395d4ac 100644 --- a/src/main/java/com/imyeyu/api/modules/common/service/implement/SmsServiceImplement.java +++ b/src/main/java/com/imyeyu/api/modules/common/service/implement/SmsServiceImplement.java @@ -65,6 +65,9 @@ public class SmsServiceImplement implements SmsService { NotifyQueueConfig.Sms.Captcha captchaConf = config.getSms().getCaptcha(); NotifyDetail detail = notifyDetailService.get(detailId); + TimiException.required(detail, "短信验证码无效"); + TimiException.required(detail.getSendAt(), "短信验证码无效"); + TimiException.requiredTrue(NotifyDetail.MsgType.SMS == detail.getMsgType(), "短信验证码无效"); if (Time.M * captchaConf.getTtlMinute() < Time.now() - detail.getSendAt()) { throw new TimiException(TimiCode.ARG_EXPIRED, "验证码过期"); } diff --git a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoUserController.java b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoUserController.java index ced8d8b..8d44978 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoUserController.java +++ b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoUserController.java @@ -27,7 +27,6 @@ import com.imyeyu.api.modules.user.service.UserService; import com.imyeyu.api.modules.user.vo.LoginResponse; import com.imyeyu.java.TimiJava; import com.imyeyu.spring.annotation.AOPLog; -import com.imyeyu.spring.annotation.CaptchaValid; import com.imyeyu.spring.annotation.RequestRateLimit; import com.imyeyu.spring.bean.Page; import com.imyeyu.spring.bean.PageResult; @@ -80,12 +79,11 @@ public class GaoUserController { @AOPLog @JsonView(ResponseView.Public.class) - @CaptchaValid @RequestRateLimit(value = 5, inSeconds = 60) @PostMapping("/invite/register") public LoginResponse registerByInvite(@RequestBody @Valid GaoUserInviteRegisterRequest req) { GaoUserInviteRegisterData data = req.getData(); - String userId = inviteService.register(data); + String userId = inviteService.register(data, req.getDetailId(), req.getCaptcha()); return userLoginService.login(UUID.randomUUID().toString(), userId); } diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserInviteService.java b/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserInviteService.java index 51b466b..bedcac9 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserInviteService.java +++ b/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserInviteService.java @@ -26,6 +26,8 @@ public interface GaoUserInviteService { /// 使用邀请注册 GAO 用户 /// /// @param data 注册数据 + /// @param smsDetailId 短信通知详情 ID + /// @param smsCaptcha 短信验证码 /// @return 注册成功的用户 ID - String register(GaoUserInviteRegisterData data); + String register(GaoUserInviteRegisterData data, String smsDetailId, String smsCaptcha); } diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserInviteServiceImplement.java b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserInviteServiceImplement.java index ff94740..9b28eac 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserInviteServiceImplement.java +++ b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserInviteServiceImplement.java @@ -3,6 +3,8 @@ package com.imyeyu.api.modules.gao.service.implement; import com.imyeyu.api.bean.CoreRoleCode; import com.imyeyu.api.bean.ModuleCode; import com.imyeyu.api.config.dbsource.TimiServerDBConfig; +import com.imyeyu.api.modules.common.entity.NotifyDetail; +import com.imyeyu.api.modules.common.service.SmsService; import com.imyeyu.api.modules.gao.bean.GaoUserInviteCache; import com.imyeyu.api.modules.gao.bean.GaoPermissionCode; import com.imyeyu.api.modules.gao.bean.GaoRoleCode; @@ -69,6 +71,7 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { private final GaoStoreService gaoStoreService; private final GaoUserService gaoUserService; + private final SmsService smsService; private final UserLoginService userLoginService; private final UserRoleService userRoleService; private final UserService userService; @@ -98,9 +101,11 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { logger.setUserId(inviterUserId); permissionChecker.checkAny(ModuleCode.GAO, GaoPermissionCode.USER_CREATE.getValue()); Role requestedRole = roleService.get(req.getRoleId()); - boolean adminInviteGlobalManager = roleChecker.hasAny(ModuleCode.CORE, CoreRoleCode.ADMIN.name()) + boolean coreAdmin = isCoreAdmin(); + boolean adminInviteGlobalManager = coreAdmin && isGlobalManagerRole(requestedRole); boolean globalManager = authorizationScopeService.isSystemAdmin(inviterUserId) + || coreAdmin || roleChecker.hasAny(ModuleCode.GAO, GaoRoleCode.GLOBAL_MANAGER.name()); boolean storeManager = !globalManager; GaoStore loginStore = storeManager ? gaoStoreService.getByUserId(inviterUserId) : null; @@ -154,7 +159,7 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { @Transactional(TimiServerDBConfig.ROLLBACKER) @Override - public String register(GaoUserInviteRegisterData data) { + public String register(GaoUserInviteRegisterData data, String smsDetailId, String smsCaptcha) { TimiException.required(data, "not found register data"); String code = data.getCode(); TimiException.required(code, "not found code"); @@ -170,6 +175,9 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { cache = requireValidInvite(code); logger.setContent(buildLogContent(cache)); validateInviteTarget(cache); + NotifyDetail smsDetail = smsService.captchaVerify(smsDetailId, smsCaptcha); + TimiException.requiredTrue(NotifyDetail.MsgType.SMS == smsDetail.getMsgType() + && data.getPhoneNo().equals(smsDetail.getSendTo()), "短信验证码与手机号不匹配"); TimiException.requiredNull(userService.getByName(data.getName()), "existed user name"); TimiException.requiredNull(userService.getByPhoneNo(data.getPhoneNo()), "existed phone number"); if (!redisInvite.destroy(getInviteKey(code))) { @@ -264,10 +272,11 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { .stream() .map(Role::getId) .toList(); - boolean descendant = authorizationScopeService.listManageableRole(inviterUserId, ModuleCode.GAO) + boolean adminInviteGlobalManager = isCoreAdmin() && isGlobalManagerRole(role); + boolean descendant = adminInviteGlobalManager || (authorizationScopeService.listManageableRole(inviterUserId, ModuleCode.GAO) .stream() .anyMatch(item -> role.getId().equals(item.getId())) - && !directRoleIdList.contains(role.getId()); + && !directRoleIdList.contains(role.getId())); if (!descendant) { throw new TimiException(TimiCode.PERMISSION_ERROR, "角色不在可邀请范围内"); } @@ -302,7 +311,8 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { } private void checkStoreScope(String userId, String storeId) { - if (authorizationScopeService.isSystemAdmin(userId) || roleChecker.hasAny(ModuleCode.GAO, GaoRoleCode.GLOBAL_MANAGER.name())) { + if (authorizationScopeService.isSystemAdmin(userId) || isCoreAdmin() + || roleChecker.hasAny(ModuleCode.GAO, GaoRoleCode.GLOBAL_MANAGER.name())) { return; } GaoStore userStore = gaoStoreService.getByUserId(userId); @@ -346,4 +356,8 @@ public class GaoUserInviteServiceImplement implements GaoUserInviteService { private TimiException invalidInvite() { return new TimiException(TimiCode.ARG_BAD, "邀请码无效或已过期"); } + + private boolean isCoreAdmin() { + return roleChecker.hasAny(ModuleCode.CORE, CoreRoleCode.ADMIN.name()); + } } diff --git a/src/main/java/com/imyeyu/api/modules/gao/vo/GaoUserInviteRegisterRequest.java b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoUserInviteRegisterRequest.java index d13cce7..f4a9fa5 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/vo/GaoUserInviteRegisterRequest.java +++ b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoUserInviteRegisterRequest.java @@ -1,20 +1,33 @@ package com.imyeyu.api.modules.gao.vo; -import com.imyeyu.spring.bean.CaptchaData; import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.Data; /// GAO 用户邀请注册请求 /// /// @author Codex /// @since 2026-08-13 -public class GaoUserInviteRegisterRequest extends CaptchaData { +@Data +public class GaoUserInviteRegisterRequest { + + /// 短信通知详情 ID + @NotBlank + private String detailId; + + /// 短信验证码 + @NotBlank + @Pattern(regexp = "\\d{6}") + private String captcha; + + private GaoUserInviteRegisterData data; /// 级联校验注册数据 - @Override @NotNull @Valid public GaoUserInviteRegisterData getData() { - return super.getData(); + return data; } }