diff --git a/src/main/java/plus/maa/backend/common/bo/EmailBusinessObject.java b/src/main/java/plus/maa/backend/common/bo/EmailBusinessObject.java index 57a9f51a..53094885 100644 --- a/src/main/java/plus/maa/backend/common/bo/EmailBusinessObject.java +++ b/src/main/java/plus/maa/backend/common/bo/EmailBusinessObject.java @@ -133,22 +133,6 @@ public void sendVerificationCodeMessage(String code) { } } - - public void sendActivateUrlMessage(String url) { - - try { - send(this.mailAccount, this.emailList - , this.title + " 账户激活" - , defaultMailIncludeHtmlTemplates( - "mail-activateUrl.ftlh", url - ) - , this.isHtml - ); - } catch (Exception ex) { - throw new RuntimeException("邮件发送失败", ex); - } - } - public void sendCommentNotification(Map map) { try { send(this.mailAccount, diff --git a/src/main/java/plus/maa/backend/controller/UserController.java b/src/main/java/plus/maa/backend/controller/UserController.java index c605bab7..0c91e9f8 100644 --- a/src/main/java/plus/maa/backend/controller/UserController.java +++ b/src/main/java/plus/maa/backend/controller/UserController.java @@ -5,25 +5,25 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import plus.maa.backend.config.SpringDocConfig; import plus.maa.backend.config.external.MaaCopilotProperties; import plus.maa.backend.config.security.AuthenticationHelper; import plus.maa.backend.controller.request.user.*; -import plus.maa.backend.controller.response.user.MaaLoginRsp; import plus.maa.backend.controller.response.MaaResult; +import plus.maa.backend.controller.response.user.MaaLoginRsp; import plus.maa.backend.controller.response.user.MaaUserInfo; import plus.maa.backend.service.EmailService; import plus.maa.backend.service.UserService; -import java.io.IOException; - /** * 用户相关接口 * activate( - @Parameter(description = "激活用户请求") @Valid @RequestBody ActivateDTO activateDTO - ) { - // FIXME 应改为从 body 中获取, 解决激活——登录悖论,待讨论 - var userId = helper.requireUserId(); - userService.activateUser(userId, activateDTO); - return MaaResult.success(); - } - - /** - * 注册完成后发送邮箱激活码 - * - * @return null - */ - @Operation(summary = "完成注册后发送邮箱激活码") - @ApiResponse(description = "激活码发送结果") - @SecurityRequirement(name = SpringDocConfig.SECURITY_SCHEME_NAME) - @PostMapping("/activate/request") - public MaaResult activateRequest() { - // FIXME 完成注册后发送激活码不应该由客户端请求 - userService.sendActiveCodeByEmail(helper.requireUserId()); - return MaaResult.success(); - } - /** * 更新当前用户的密码(根据原密码) * @@ -177,9 +143,8 @@ public MaaResult register(@Parameter(description = "用户注册请 @PostMapping("/sendRegistrationToken") @Operation(summary = "注册时发送验证码") @ApiResponse(description = "发送验证码结果", responseCode = "204") - public MaaResult sendRegistrationToken(@Parameter(description = "发送注册验证码请求") @RequestBody SendRegistrationTokenDTO regDTO) { - //FIXME: 增加频率限制或者 captcha - emailService.sendVCode(regDTO.getEmail()); + public MaaResult sendRegistrationToken(@Parameter(description = "发送注册验证码请求") @RequestBody @Valid SendRegistrationTokenDTO regDTO) { + userService.sendRegistrationToken(regDTO); return new MaaResult<>(204, null, null); } @@ -195,19 +160,4 @@ public MaaResult sendRegistrationToken(@Parameter(description = "发送注 public MaaResult login(@Parameter(description = "登录请求") @RequestBody @Valid LoginDTO user) { return MaaResult.success("登陆成功", userService.login(user)); } - - @GetMapping("/activateAccount") - @Operation(summary = "激活账号") - @ApiResponse(description = "激活账号结果") - public MaaResult activateAccount(@Parameter(description = "激活请求") EmailActivateReq activateDTO, - @Parameter(description = "页面跳转参数") HttpServletResponse response) { - userService.activateAccount(activateDTO); - // 激活成功 跳转页面 - try { - response.sendRedirect(properties.getInfo().getFrontendDomain()); - } catch (IOException e) { - throw new RuntimeException(e); - } - return MaaResult.success(); - } } diff --git a/src/main/java/plus/maa/backend/controller/request/user/ActivateDTO.java b/src/main/java/plus/maa/backend/controller/request/user/ActivateDTO.java deleted file mode 100644 index 14baea77..00000000 --- a/src/main/java/plus/maa/backend/controller/request/user/ActivateDTO.java +++ /dev/null @@ -1,19 +0,0 @@ -package plus.maa.backend.controller.request.user; - -import jakarta.validation.constraints.NotBlank; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; - -/** - * @author john180 - */ -@Data -@Accessors(chain = true) -@NoArgsConstructor -@AllArgsConstructor -public class ActivateDTO { - @NotBlank(message = "激活码不能为空") - private String token; -} diff --git a/src/main/java/plus/maa/backend/controller/request/user/LoginDTO.java b/src/main/java/plus/maa/backend/controller/request/user/LoginDTO.java index af64ceba..2c2f8270 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/LoginDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/LoginDTO.java @@ -15,6 +15,7 @@ @NoArgsConstructor @AllArgsConstructor public class LoginDTO { + @NotBlank(message = "邮箱格式错误") @Email(message = "邮箱格式错误") private String email; @NotBlank(message = "请输入用户密码") diff --git a/src/main/java/plus/maa/backend/controller/request/user/PasswordResetDTO.java b/src/main/java/plus/maa/backend/controller/request/user/PasswordResetDTO.java index 6e9f41f6..e0fdf9ad 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/PasswordResetDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/PasswordResetDTO.java @@ -18,6 +18,7 @@ public class PasswordResetDTO { /** * 邮箱 */ + @NotBlank(message = "邮箱格式错误") @Email(message = "邮箱格式错误") private String email; /** diff --git a/src/main/java/plus/maa/backend/controller/request/user/PasswordResetVCodeDTO.java b/src/main/java/plus/maa/backend/controller/request/user/PasswordResetVCodeDTO.java index 73afc856..4b843cd0 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/PasswordResetVCodeDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/PasswordResetVCodeDTO.java @@ -1,6 +1,7 @@ package plus.maa.backend.controller.request.user; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -17,6 +18,7 @@ public class PasswordResetVCodeDTO { /** * 邮箱 */ + @NotBlank(message = "邮箱格式错误") @Email(message = "邮箱格式错误") private String email; } diff --git a/src/main/java/plus/maa/backend/controller/request/user/PasswordUpdateDTO.java b/src/main/java/plus/maa/backend/controller/request/user/PasswordUpdateDTO.java index 15084688..8775b4c6 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/PasswordUpdateDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/PasswordUpdateDTO.java @@ -17,6 +17,7 @@ public class PasswordUpdateDTO { @NotBlank(message = "请输入原密码") private String originalPassword; + @NotBlank(message = "密码长度必须在8-32位之间") @Length(min = 8, max = 32, message = "密码长度必须在8-32位之间") private String newPassword; } diff --git a/src/main/java/plus/maa/backend/controller/request/user/RegisterDTO.java b/src/main/java/plus/maa/backend/controller/request/user/RegisterDTO.java index 45770cde..4272cb9a 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/RegisterDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/RegisterDTO.java @@ -1,6 +1,7 @@ package plus.maa.backend.controller.request.user; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,11 +16,15 @@ @NoArgsConstructor @AllArgsConstructor public class RegisterDTO { + @NotBlank(message = "邮箱格式错误") @Email(message = "邮箱格式错误") private String email; - @Length(min = 4, max = 24, message = "用户名长度应在2-24位之间") + @NotBlank(message = "用户名长度应在4-24位之间") + @Length(min = 4, max = 24, message = "用户名长度应在4-24位之间") private String userName; + @NotBlank(message = "密码长度必须在8-32位之间") @Length(min = 8, max = 32, message = "密码长度必须在8-32位之间") private String password; + @NotBlank(message = "请输入验证码") private String registrationToken; } diff --git a/src/main/java/plus/maa/backend/controller/request/user/SendRegistrationTokenDTO.java b/src/main/java/plus/maa/backend/controller/request/user/SendRegistrationTokenDTO.java index 11851c5f..582271a4 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/SendRegistrationTokenDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/SendRegistrationTokenDTO.java @@ -1,10 +1,12 @@ package plus.maa.backend.controller.request.user; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class SendRegistrationTokenDTO { + @NotBlank(message = "邮箱格式错误") @Email(message = "邮箱格式错误") private String email; } diff --git a/src/main/java/plus/maa/backend/controller/request/user/UserInfoUpdateDTO.java b/src/main/java/plus/maa/backend/controller/request/user/UserInfoUpdateDTO.java index e7a6d622..2f03476a 100644 --- a/src/main/java/plus/maa/backend/controller/request/user/UserInfoUpdateDTO.java +++ b/src/main/java/plus/maa/backend/controller/request/user/UserInfoUpdateDTO.java @@ -1,5 +1,6 @@ package plus.maa.backend.controller.request.user; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -14,6 +15,7 @@ @NoArgsConstructor @AllArgsConstructor public class UserInfoUpdateDTO { - @Length(min = 4, max = 24, message = "用户名长度应在2-24位之间") + @NotBlank(message = "用户名长度应在4-24位之间") + @Length(min = 4, max = 24, message = "用户名长度应在4-24位之间") private String userName; } diff --git a/src/main/java/plus/maa/backend/repository/RedisCache.java b/src/main/java/plus/maa/backend/repository/RedisCache.java index e0aec204..3b21b6e2 100644 --- a/src/main/java/plus/maa/backend/repository/RedisCache.java +++ b/src/main/java/plus/maa/backend/repository/RedisCache.java @@ -55,6 +55,8 @@ public class RedisCache { 实际大小这么设计是为了避免频繁的 ZREMRANGEBYRANK 操作 */ private final RedisScript incZSetRedisScript = RedisScript.of(new ClassPathResource("redis-lua/incZSet.lua")); + // 比较与输入的键值对是否相同,相同则删除 + private final RedisScript removeKVIfEqualsScript = RedisScript.of(new ClassPathResource("redis-lua/removeKVIfEquals.lua"), Boolean.class); public void setData(final String key, T value) { setCache(key, value, 0, TimeUnit.SECONDS); @@ -69,15 +71,8 @@ public void setCache(final String key, T value, long timeout) { } public void setCache(final String key, T value, long timeout, TimeUnit timeUnit) { - String json; - try { - json = writeMapper.writeValueAsString(value); - } catch (JsonProcessingException e) { - if (log.isDebugEnabled()) { - log.debug(e.getMessage(), e); - } - return; - } + String json = getJson(value); + if (json == null) return; if (timeout <= 0) { redisTemplate.opsForValue().set(key, json); } else { @@ -85,6 +80,52 @@ public void setCache(final String key, T value, long timeout, TimeUnit timeU } } + /** + * 当缓存不存在时,则 set + * + * @param key 缓存的 key + * @param value 被缓存的值 + * @return 是否 set + */ + + public boolean setCacheIfAbsent(final String key, T value) { + return setCacheIfAbsent(key, value, expire); + } + + /** + * 当缓存不存在时,则 set + * + * @param key 缓存的 key + * @param value 被缓存的值 + * @param timeout 过期时间 + * @return 是否 set + */ + + public boolean setCacheIfAbsent(final String key, T value, long timeout) { + return setCacheIfAbsent(key, value, timeout, TimeUnit.SECONDS); + } + + /** + * 当缓存不存在时,则 set + * + * @param key 缓存的 key + * @param value 被缓存的值 + * @param timeout 过期时间 + * @param timeUnit 过期时间的单位 + * @return 是否 set + */ + public boolean setCacheIfAbsent(final String key, T value, long timeout, TimeUnit timeUnit) { + String json = getJson(value); + if (json == null) return false; + boolean result; + if (timeout <= 0) { + result = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, json)); + } else { + result = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, json, timeout, timeUnit)); + } + return result; + } + public void addSet(final String key, Collection set, long timeout) { addSet(key, set, timeout, TimeUnit.SECONDS); } @@ -94,17 +135,13 @@ public void addSet(final String key, Collection set, long timeout, TimeUn return; } String[] jsonList = new String[set.size()]; - try { - int i = 0; - for (T t : set) { - jsonList[i++] = writeMapper.writeValueAsString(t); - } - } catch (JsonProcessingException e) { - if (log.isDebugEnabled()) { - log.debug(e.getMessage(), e); - } - return; + int i = 0; + for (T t : set) { + String json = getJson(t); + if (json == null) return; + jsonList[i++] = json; } + if (timeout <= 0) { redisTemplate.opsForSet().add(key, jsonList); } else { @@ -144,12 +181,9 @@ public Set getZSetReverse(final String key, long start, long end) { public boolean valueMemberInSet(final String key, T value) { try { - String json = writeMapper.writeValueAsString(value); + String json = getJson(value); + if (json == null) return false; return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, json)); - } catch (JsonProcessingException e) { - if (log.isDebugEnabled()) { - log.debug(e.getMessage(), e); - } } catch (Exception e) { log.error(e.getMessage(), e); } @@ -244,6 +278,21 @@ public void removeCache(String key) { redisTemplate.delete(key); } + /** + * 相同则删除键值对 + * + * @param key 待比较和删除的键 + * @param value 待比较的值 + * @return 是否删除 + */ + public boolean removeKVIfEquals(String key, T value) { + String json = getJson(value); + if (json == null) return false; + return Boolean.TRUE.equals( + redisTemplate.execute(removeKVIfEqualsScript, List.of(key), json) + ); + } + /** * 模糊删除缓存。 * @@ -282,4 +331,19 @@ public void removeCacheByPattern(String pattern) { redisTemplate.delete(keysToDelete); } } + + + @Nullable + private String getJson(T value) { + String json; + try { + json = writeMapper.writeValueAsString(value); + } catch (JsonProcessingException e) { + if (log.isDebugEnabled()) { + log.debug(e.getMessage(), e); + } + return null; + } + return json; + } } diff --git a/src/main/java/plus/maa/backend/service/EmailService.java b/src/main/java/plus/maa/backend/service/EmailService.java index c04e21b6..b1a6ba5d 100644 --- a/src/main/java/plus/maa/backend/service/EmailService.java +++ b/src/main/java/plus/maa/backend/service/EmailService.java @@ -2,15 +2,15 @@ import cn.hutool.extra.mail.MailAccount; import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import org.springframework.util.Assert; import plus.maa.backend.common.bo.EmailBusinessObject; import plus.maa.backend.config.external.MaaCopilotProperties; import plus.maa.backend.config.external.Mail; @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.UUID; /** * @author LoMu @@ -45,6 +44,11 @@ public class EmailService { private final MailAccount MAIL_ACCOUNT = new MailAccount(); + // 注入自身代理类的延迟加载代理类 + @Lazy + @Resource + private EmailService emailService; + /** * 初始化邮件账户信息 */ @@ -71,8 +75,19 @@ private void initMailAccount() { * @param email 邮箱 */ - @Async public void sendVCode(String email) { + // 一个过期周期最多重发十条,记录已发送的邮箱以及间隔时间 + final int timeout = expire / 10; + if (!redisCache.setCacheIfAbsent("HasBeenSentVCode:" + email , timeout, timeout)) { + // 设置失败,说明 key 已存在 + throw new MaaResultException(403, String.format("发送验证码的请求至少需要间隔 %d 秒", timeout)); + } + // 调用注入的代理类执行异步任务 + emailService.asyncSendVCode(email); + } + + @Async + protected void asyncSendVCode(String email) { // 6位随机数验证码 String vcode = RandomStringUtils.random(6, true, true).toUpperCase(); if (flagNoSend) { @@ -95,51 +110,9 @@ public void sendVCode(String email) { * @throws MaaResultException 验证码错误 */ public void verifyVCode(String email, String vcode) { - String cacheVCode = redisCache.getCache("vCodeEmail:" + email, String.class); - if (!StringUtils.equalsIgnoreCase(cacheVCode, vcode)) { + if (!redisCache.removeKVIfEquals("vCodeEmail:" + email, vcode.toUpperCase())) { throw new MaaResultException(401, "验证码错误"); } - redisCache.removeCache("vCodeEmail:" + email); - } - - /** - * 验证发到某个邮箱的验证码 - * - * @param email 邮箱 - * @param vcode 验证码 - * @param clearVCodeOnSuccess 验证成功是否删除验证码 - * @return 是否一致 - */ - - public boolean verifyVCode2(String email, String vcode, boolean clearVCodeOnSuccess) { - // FIXME:可能出现多线程数据争用问题,想办法用redis的一些方法直接比较完删除 - String cacheVCode = redisCache.getCache("vCodeEmail:" + email, String.class); - boolean result = StringUtils.equalsIgnoreCase(cacheVCode, vcode); - if (clearVCodeOnSuccess && result) { - redisCache.removeCache("vCodeEmail:" + email); - } - return result; - } - - /** - * @param email 发送激活验证邮箱 - */ - @Async - public void sendActivateUrl(String email) { - // 生成uuid作为唯一标识符 - String uuid = UUID.randomUUID().toString().replaceAll("-", ""); - String url = domain + "/user/activateAccount?nonce=" + uuid; - if (flagNoSend) { - log.debug("url is " + url); - log.warn("Email not sent, no-send enabled"); - } else { - EmailBusinessObject.builder() - .setMailAccount(MAIL_ACCOUNT) - .setEmail(email) - .sendActivateUrlMessage(url); - } - // 存redis - redisCache.setCache("UUID:" + uuid, email, expire); } @Async diff --git a/src/main/java/plus/maa/backend/service/UserService.java b/src/main/java/plus/maa/backend/service/UserService.java index 111e8270..764c55e4 100644 --- a/src/main/java/plus/maa/backend/service/UserService.java +++ b/src/main/java/plus/maa/backend/service/UserService.java @@ -1,6 +1,5 @@ package plus.maa.backend.service; -import cn.hutool.core.lang.Assert; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -39,7 +38,6 @@ public class UserService { // 未来转为配置项 private static final int LOGIN_LIMIT = 1; - private final RedisCache redisCache; private final UserRepository userRepository; private final EmailService emailService; private final PasswordEncoder passwordEncoder; @@ -58,6 +56,10 @@ public MaaLoginRsp login(LoginDTO loginDTO) { if (user == null || !passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) { throw new MaaResultException(401, "用户不存在或者密码错误"); } + // 未激活的用户 + if (Objects.equals(user.getStatus(), 0)) { + throw new MaaResultException(MaaStatusCode.MAA_USER_NOT_ENABLED); + } var jwtId = UUID.randomUUID().toString(); var jwtIds = user.getRefreshJwtIds(); @@ -105,14 +107,14 @@ public void modifyPassword(String userId, String rawPassword) { public MaaUserInfo register(RegisterDTO registerDTO) { String encode = passwordEncoder.encode(registerDTO.getPassword()); + // 校验验证码 + emailService.verifyVCode(registerDTO.getEmail(), registerDTO.getRegistrationToken()); + MaaUser user = new MaaUser(); BeanUtils.copyProperties(registerDTO, user); user.setPassword(encode); user.setStatus(1); MaaUserInfo userInfo; - if (!emailService.verifyVCode2(user.getEmail(), registerDTO.getRegistrationToken(), false)) { - throw new MaaResultException(MaaStatusCode.MAA_REGISTRATION_CODE_NOT_FOUND); - } try { MaaUser save = userRepository.save(user); userInfo = new MaaUserInfo(save); @@ -122,22 +124,6 @@ public MaaUserInfo register(RegisterDTO registerDTO) { return userInfo; } - /** - * 通过传入的JwtToken来获取当前用户的信息 - * - * @param userId 当前用户 - * @param activateDTO 邮箱激活码 - */ - public void activateUser(@NotNull String userId, ActivateDTO activateDTO) { - userRepository.findById(userId).ifPresent((maaUser) -> { - if (1 == maaUser.getStatus()) return; - var email = maaUser.getEmail(); - emailService.verifyVCode(email, activateDTO.getToken()); - maaUser.setStatus(1); - userRepository.save(maaUser); - }); - } - /** * 更新用户信息 * @@ -151,19 +137,6 @@ public void updateUserInfo(@NotNull String userId, UserInfoUpdateDTO updateDTO) }); } - /** - * 为用户发送激活验证码 - * - * @param userId 用户 id - */ - public void sendActiveCodeByEmail(String userId) { - userRepository.findById(userId).ifPresent((maaUser) -> { - Assert.state(Objects.equals(maaUser.getStatus(), 0), - "用户已经激活,无法再次发送验证码"); - emailService.sendVCode(maaUser.getEmail()); - }); - } - /** * 刷新token * @@ -227,29 +200,17 @@ public void checkUserExistByEmail(String email) { } /** - * 激活账户 - * - * @param activateDTO uuid + * 注册时发送验证码 */ - public void activateAccount(EmailActivateReq activateDTO) { - String uuid = activateDTO.getNonce(); - String email = redisCache.getCache("UUID:" + uuid, String.class); - Assert.notNull(email, "链接已过期"); - MaaUser user = userRepository.findByEmail(email); - - try { - if (Objects.equals(user.getStatus(), 1)) { - return; - } - // 激活账户 - user.setStatus(1); - userRepository.save(user); - - // 清除缓存 - } finally { - redisCache.removeCache("UUID:" + uuid); + public void sendRegistrationToken(SendRegistrationTokenDTO regDTO) { + // 判断用户是否存在 + MaaUser maaUser = userRepository.findByEmail(regDTO.getEmail()); + if (maaUser != null) { + // 用户已存在 + throw new MaaResultException(MaaStatusCode.MAA_USER_EXISTS); } + // 发送验证码 + emailService.sendVCode(regDTO.getEmail()); } - } diff --git a/src/main/resources/redis-lua/removeKVIfEquals.lua b/src/main/resources/redis-lua/removeKVIfEquals.lua new file mode 100644 index 00000000..09c76db2 --- /dev/null +++ b/src/main/resources/redis-lua/removeKVIfEquals.lua @@ -0,0 +1,6 @@ +local dbValue = redis.call('GET', KEYS[1]) +if dbValue == ARGV[1] then + redis.call('DEL', KEYS[1]) + return true +end +return false \ No newline at end of file