Просмотр исходного кода

!60 用户中心修改密码,修改手机功能重做,发送短信 拓展设置对应模板编号
Merge pull request !60 from 宋天/feature/user-register

芋道源码 3 лет назад
Родитель
Сommit
678e2def97
20 измененных файлов с 234 добавлено и 291 удалено
  1. 13 0
      yudao-admin-server/src/main/resources/application-local.yaml
  2. 0 9
      yudao-user-server/pom.xml
  3. 0 7
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.java
  4. 15 2
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserUpdateMobileReqVO.java
  5. 23 9
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java
  6. 1 19
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java
  7. 6 0
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java
  8. 40 0
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthCheckCodeReqVO.java
  9. 4 2
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/sms/SysSmsCodeMapper.java
  10. 1 1
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java
  11. 24 4
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/sms/SysSmsSceneEnum.java
  12. 10 0
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/sms/SysSmsTemplateCodeConstants.java
  13. 1 8
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java
  14. 22 30
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
  15. 16 11
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java
  16. 38 38
      yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java
  17. 0 62
      yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/controller/SysUserProfileControllerTest.java
  18. 15 13
      yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java
  19. 0 68
      yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/controller/SysAuthControllerTest.java
  20. 5 8
      yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java

+ 13 - 0
yudao-admin-server/src/main/resources/application-local.yaml

@@ -55,6 +55,19 @@ spring:
           username: root
           username: root
           password: 123456
           password: 123456
 
 
+  activiti:
+    #1.false:默认值,activiti启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
+    #2.true:启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
+    #3.create_drop:启动时自动创建表,关闭时自动删除表
+    #4.drop_create:启动时,删除旧表,再创建新表
+    database-schema-update: true
+    #activiti7默认不生成历史信息表,需手动设置开启
+    db-history-used: true
+    check-process-definitions: true
+    #full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
+    history-level: full
+
+
   # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
   # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
   redis:
   redis:
     host: 127.0.0.1 # 地址
     host: 127.0.0.1 # 地址

+ 0 - 9
yudao-user-server/pom.xml

@@ -90,15 +90,6 @@
             <artifactId>yudao-spring-boot-starter-test</artifactId>
             <artifactId>yudao-spring-boot-starter-test</artifactId>
             <scope>test</scope>
             <scope>test</scope>
         </dependency>
         </dependency>
-
-        <!-- TODO @宋天:junit 已经在 yudao-spring-boot-starter-test 啦,不用在引入哈 -->
-        <!--单元测试相关-->
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
         <!-- 工具类相关 -->
         <!-- 工具类相关 -->
 
 
     </dependencies>
     </dependencies>

+ 0 - 7
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.java

@@ -35,9 +35,6 @@ public class SysUserProfileController {
     @Resource
     @Resource
     private MbrUserService userService;
     private MbrUserService userService;
 
 
-    @Resource
-    private SysSmsCodeService smsCodeService;
-
     @PutMapping("/update-nickname")
     @PutMapping("/update-nickname")
     @ApiOperation("修改用户昵称")
     @ApiOperation("修改用户昵称")
     @PreAuthenticated
     @PreAuthenticated
@@ -68,10 +65,6 @@ public class SysUserProfileController {
     @ApiOperation(value = "修改用户手机")
     @ApiOperation(value = "修改用户手机")
     @PreAuthenticated
     @PreAuthenticated
     public CommonResult<Boolean> updateMobile(@RequestBody @Valid MbrUserUpdateMobileReqVO reqVO) {
     public CommonResult<Boolean> updateMobile(@RequestBody @Valid MbrUserUpdateMobileReqVO reqVO) {
-        // 校验验证码
-        // TODO @宋天:统一到 userService.updateMobile 方法里
-        smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
-
         userService.updateMobile(getLoginUserId(), reqVO);
         userService.updateMobile(getLoginUserId(), reqVO);
         return success(true);
         return success(true);
     }
     }

+ 15 - 2
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserUpdateMobileReqVO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.userserver.modules.member.controller.user.vo;
 package cn.iocoder.yudao.userserver.modules.member.controller.user.vo;
 
 
+import cn.iocoder.yudao.framework.common.validation.Mobile;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
@@ -27,9 +28,21 @@ public class MbrUserUpdateMobileReqVO {
 
 
     @ApiModelProperty(value = "手机号",required = true,example = "15823654487")
     @ApiModelProperty(value = "手机号",required = true,example = "15823654487")
     @NotBlank(message = "手机号不能为空")
     @NotBlank(message = "手机号不能为空")
-    // TODO @宋天:手机校验,直接使用 @Mobile 哈
     @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
     @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
-    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
+    @Mobile
     private String mobile;
     private String mobile;
 
 
+    @ApiModelProperty(value = "原手机验证码", required = true, example = "1024")
+    @NotEmpty(message = "原手机验证码不能为空")
+    @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
+    @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
+    private String oldCode;
+
+    @ApiModelProperty(value = "原手机号",required = true,example = "15823654487")
+    @NotBlank(message = "手机号不能为空")
+    @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
+    @Mobile
+    private String oldMobile;
+
+
 }
 }

+ 23 - 9
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java

@@ -4,17 +4,20 @@ import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
-import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
 import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
 import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
 import cn.iocoder.yudao.userserver.modules.member.convert.user.UserProfileConvert;
 import cn.iocoder.yudao.userserver.modules.member.convert.user.UserProfileConvert;
 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
-import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
+import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
+import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
+import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import javax.validation.Valid;
@@ -22,7 +25,9 @@ import java.io.InputStream;
 import java.util.Date;
 import java.util.Date;
 
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.USER_NOT_EXISTS;
 import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.USER_NOT_EXISTS;
+import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants.USER_SMS_CODE_IS_UNUSED;
 
 
 /**
 /**
  * User Service 实现类
  * User Service 实现类
@@ -44,7 +49,8 @@ public class MbrUserServiceImpl implements MbrUserService {
     private PasswordEncoder passwordEncoder;
     private PasswordEncoder passwordEncoder;
 
 
     @Resource
     @Resource
-    private SysAuthService sysAuthService;
+    private SysSmsCodeService smsCodeService;
+
 
 
     @Override
     @Override
     public MbrUserDO getUserByMobile(String mobile) {
     public MbrUserDO getUserByMobile(String mobile) {
@@ -120,15 +126,23 @@ public class MbrUserServiceImpl implements MbrUserService {
     }
     }
 
 
     @Override
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateMobile(Long userId, MbrUserUpdateMobileReqVO reqVO) {
     public void updateMobile(Long userId, MbrUserUpdateMobileReqVO reqVO) {
         // 检测用户是否存在
         // 检测用户是否存在
-        MbrUserDO userDO = checkUserExists(userId);
-        // 检测手机与验证码是否匹配
-        // TODO @宋天:修改手机的时候。应该要校验,老手机 + 老手机 code;新手机 + 新手机 code
-        sysAuthService.checkIfMobileMatchCodeAndDeleteCode(userDO.getMobile(),reqVO.getCode());
+        checkUserExists(userId);
+
+        // 校验旧手机和旧验证码
+        SysSmsCodeDO sysSmsCodeDO = smsCodeService.checkCodeIsExpired(reqVO.getOldMobile(), reqVO.getOldCode(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
+        // 判断旧code是否未被使用,如果是,抛出异常
+        if (Boolean.FALSE.equals(sysSmsCodeDO.getUsed())){
+            throw exception(USER_SMS_CODE_IS_UNUSED);
+        }
+
+        // 使用新验证码
+        smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
+
         // 更新用户手机
         // 更新用户手机
-        // TODO @宋天:更新的时候,单独创建对象。直接全量更新,会可能导致属性覆盖。可以看看打印出来的 SQL 哈
-        userDO.setMobile(reqVO.getMobile());
+        MbrUserDO userDO = MbrUserDO.builder().id(userId).mobile(reqVO.getMobile()).build();
         userMapper.updateById(userDO);
         userMapper.updateById(userDO);
     }
     }
 
 

+ 1 - 19
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java

@@ -5,10 +5,8 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;
 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;
-import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
-import com.alibaba.fastjson.JSON;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiImplicitParams;
@@ -18,7 +16,6 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
 import javax.validation.Valid;
 
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -57,19 +54,12 @@ public class SysAuthController {
     }
     }
 
 
     @PostMapping("/send-sms-code")
     @PostMapping("/send-sms-code")
-    @ApiOperation(value = "发送手机验证码",notes = "不检测该手机号是否已被注册")
+    @ApiOperation(value = "发送手机验证码")
     public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) {
     public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) {
         smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP());
         smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP());
         return success(true);
         return success(true);
     }
     }
 
 
-    @PostMapping("/send-sms-new-code")
-    @ApiOperation(value = "发送手机验证码",notes = "检测该手机号是否已被注册,用于修改手机时使用")
-    public CommonResult<Boolean> sendSmsNewCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) {
-        smsCodeService.sendSmsNewCode(reqVO);
-        return success(true);
-    }
-
     @GetMapping("/send-sms-code-login")
     @GetMapping("/send-sms-code-login")
     @ApiOperation(value = "向已登录用户发送验证码",notes = "修改手机时验证原手机号使用")
     @ApiOperation(value = "向已登录用户发送验证码",notes = "修改手机时验证原手机号使用")
     public CommonResult<Boolean> sendSmsCodeLogin() {
     public CommonResult<Boolean> sendSmsCodeLogin() {
@@ -93,14 +83,6 @@ public class SysAuthController {
         return success(true);
         return success(true);
     }
     }
 
 
-    @PostMapping("/check-sms-code")
-    @ApiOperation(value = "校验验证码是否正确")
-    @PreAuthenticated
-    public CommonResult<Boolean> checkSmsCode(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) {
-        // TODO @宋天:check 的时候,不应该使用 useSmsCode 哈,这样验证码就直接被使用了。另外,check 开头的方法,更多是校验的逻辑,不会有 update 数据的动作。这点,在方法命名上,也是要注意的
-        smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHECK_CODE_BY_SMS.getScene(),reqVO.getCode(),getClientIP());
-        return success(true);
-    }
 
 
     // ========== 社交登录相关 ==========
     // ========== 社交登录相关 ==========
 
 

+ 6 - 0
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
 
 
+import cn.iocoder.yudao.framework.common.validation.Mobile;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
@@ -8,6 +9,7 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 import org.hibernate.validator.constraints.Length;
 import org.hibernate.validator.constraints.Length;
 
 
+import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.Pattern;
 import javax.validation.constraints.Pattern;
 
 
@@ -29,4 +31,8 @@ public class MbrAuthResetPasswordReqVO {
     @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
     @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
     private String code;
     private String code;
 
 
+    @ApiModelProperty(value = "手机号",required = true,example = "15878962356")
+    @NotBlank(message = "手机号不能为空")
+    @Mobile
+    private String mobile;
 }
 }

+ 40 - 0
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthCheckCodeReqVO.java

@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.framework.common.validation.Mobile;
+import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+@ApiModel("校验验证码 Request VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class SysAuthCheckCodeReqVO {
+
+    @ApiModelProperty(value = "手机号", example = "15601691234")
+    @NotBlank(message = "手机号不能为空")
+    @Mobile
+    private String mobile;
+
+    @ApiModelProperty(value = "手机验证码", required = true, example = "1024")
+    @NotBlank(message = "手机验证码不能为空")
+    @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
+    @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
+    private String code;
+
+    @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 MbrSmsSceneEnum 枚举")
+    @NotNull(message = "发送场景不能为空")
+    @InEnum(SysSmsSceneEnum.class)
+    private Integer scene;
+}

+ 4 - 2
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/sms/SysSmsCodeMapper.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
 
 
+
 @Mapper
 @Mapper
 public interface SysSmsCodeMapper extends BaseMapperX<SysSmsCodeDO> {
 public interface SysSmsCodeMapper extends BaseMapperX<SysSmsCodeDO> {
 
 
@@ -13,14 +14,15 @@ public interface SysSmsCodeMapper extends BaseMapperX<SysSmsCodeDO> {
      *
      *
      * @param mobile 手机号
      * @param mobile 手机号
      * @param scene 发送场景,选填
      * @param scene 发送场景,选填
+     * @param code 验证码 选填
      * @return 手机验证码
      * @return 手机验证码
      */
      */
-    default SysSmsCodeDO selectLastByMobile(String mobile, Integer scene) {
+    default SysSmsCodeDO selectLastByMobile(String mobile,String code,Integer scene) {
         return selectOne(new QueryWrapperX<SysSmsCodeDO>()
         return selectOne(new QueryWrapperX<SysSmsCodeDO>()
                 .eq("mobile", mobile)
                 .eq("mobile", mobile)
                 .eqIfPresent("scene", scene)
                 .eqIfPresent("scene", scene)
+                .eqIfPresent("code", code)
                 .orderByDesc("id")
                 .orderByDesc("id")
                 .last("LIMIT 1"));
                 .last("LIMIT 1"));
     }
     }
-
 }
 }

+ 1 - 1
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java

@@ -24,9 +24,9 @@ public interface SysErrorCodeConstants {
     ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量");
     ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量");
     ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率");
     ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率");
     ErrorCode USER_SMS_CODE_IS_EXISTS = new ErrorCode(1005001006, "手机号已被使用");
     ErrorCode USER_SMS_CODE_IS_EXISTS = new ErrorCode(1005001006, "手机号已被使用");
+    ErrorCode USER_SMS_CODE_IS_UNUSED = new ErrorCode(1005001006, "验证码未被使用");
 
 
     // ========== 用户模块 1005002000 ==========
     // ========== 用户模块 1005002000 ==========
     ErrorCode USER_NOT_EXISTS = new ErrorCode(1005002001, "用户不存在");
     ErrorCode USER_NOT_EXISTS = new ErrorCode(1005002001, "用户不存在");
-    ErrorCode USER_CODE_FAILED = new ErrorCode(1005002002, "验证码不匹配");
     ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1005002003, "密码校验失败");
     ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1005002003, "密码校验失败");
 }
 }

+ 24 - 4
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/sms/SysSmsSceneEnum.java

@@ -15,15 +15,26 @@ import java.util.Arrays;
 @AllArgsConstructor
 @AllArgsConstructor
 public enum SysSmsSceneEnum implements IntArrayValuable {
 public enum SysSmsSceneEnum implements IntArrayValuable {
 
 
-    LOGIN_BY_SMS(1, "手机号登陆"),
-    CHANGE_MOBILE_BY_SMS(2, "更换手机号"),
-    FORGET_MOBILE_BY_SMS(3, "忘记密码"),
-    CHECK_CODE_BY_SMS(4, "审核验证码"),
+    LOGIN_BY_SMS(1,SysSmsTemplateCodeConstants.USER_SMS_LOGIN, "手机号登陆"),
+    CHANGE_MOBILE_BY_SMS(2,SysSmsTemplateCodeConstants.USER_SMS_UPDATE_MOBILE, "更换手机号"),
+    FORGET_MOBILE_BY_SMS(3,SysSmsTemplateCodeConstants.USER_SMS_RESET_PASSWORD, "忘记密码"),
     ;
     ;
 
 
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSmsSceneEnum::getScene).toArray();
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSmsSceneEnum::getScene).toArray();
 
 
+    /**
+     * 验证那场景编号
+     */
     private final Integer scene;
     private final Integer scene;
+
+    /**
+     * 模版编码
+     */
+    private final String code;
+
+    /**
+     * 描述
+     */
     private final String name;
     private final String name;
 
 
     @Override
     @Override
@@ -31,4 +42,13 @@ public enum SysSmsSceneEnum implements IntArrayValuable {
         return ARRAYS;
         return ARRAYS;
     }
     }
 
 
+    public static String getCodeByScene(Integer scene){
+        for (SysSmsSceneEnum value : values()) {
+            if (value.getScene().equals(scene)){
+                return value.getCode();
+            }
+        }
+        return null;
+    }
+
 }
 }

+ 10 - 0
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/sms/SysSmsTemplateCodeConstants.java

@@ -12,4 +12,14 @@ public interface SysSmsTemplateCodeConstants {
      */
      */
     String USER_SMS_LOGIN = "user-sms-login";
     String USER_SMS_LOGIN = "user-sms-login";
 
 
+    /**
+     * 用户忘记密码
+     */
+    String USER_SMS_RESET_PASSWORD = "user-sms-reset-password";
+
+    /**
+     * 用户更新手机号
+     */
+    String USER_SMS_UPDATE_MOBILE = "user-sms-update-mobile";
+
 }
 }

+ 1 - 8
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java

@@ -68,18 +68,11 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
      * @param userId 用户id
      * @param userId 用户id
      * @param userReqVO 用户请求实体类
      * @param userReqVO 用户请求实体类
      */
      */
-    void updatePassword(Long userId, @Valid MbrAuthUpdatePasswordReqVO userReqVO);
+    void updatePassword(Long userId,MbrAuthUpdatePasswordReqVO userReqVO);
 
 
     /**
     /**
      * 忘记密码
      * 忘记密码
      * @param userReqVO 用户请求实体类
      * @param userReqVO 用户请求实体类
      */
      */
     void resetPassword(MbrAuthResetPasswordReqVO userReqVO);
     void resetPassword(MbrAuthResetPasswordReqVO userReqVO);
-
-    /**
-     * 检测手机与验证码是否匹配
-     * @param phone 手机号
-     * @param code 验证码
-     */
-    void checkIfMobileMatchCodeAndDeleteCode(String phone,String code);
 }
 }

+ 22 - 30
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java

@@ -40,7 +40,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
-import javax.validation.Valid;
 import java.util.List;
 import java.util.List;
 import java.util.Objects;
 import java.util.Objects;
 
 
@@ -285,46 +284,30 @@ public class SysAuthServiceImpl implements SysAuthService {
     }
     }
 
 
     @Override
     @Override
-    public void updatePassword(Long userId, @Valid MbrAuthUpdatePasswordReqVO reqVO) {
+    public void updatePassword(Long userId,MbrAuthUpdatePasswordReqVO reqVO) {
         // 检验旧密码
         // 检验旧密码
         MbrUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
         MbrUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
 
 
         // 更新用户密码
         // 更新用户密码
-        // TODO @宋天:不要更新整个对象哈
-        userDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
-        userMapper.updateById(userDO);
+        MbrUserDO mbrUserDO = MbrUserDO.builder().build();
+        mbrUserDO.setId(userDO.getId());
+        mbrUserDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
+        userMapper.updateById(mbrUserDO);
     }
     }
 
 
     @Override
     @Override
     public void resetPassword(MbrAuthResetPasswordReqVO reqVO) {
     public void resetPassword(MbrAuthResetPasswordReqVO reqVO) {
-        // 根据验证码取出手机号,并查询用户
-        String mobile = stringRedisTemplate.opsForValue().get(reqVO.getCode());
-        MbrUserDO userDO = userMapper.selectByMobile(mobile);
-        if (userDO == null){
-            throw exception(USER_NOT_EXISTS);
-        }
-        // TODO @芋艿 这一步没必要检验验证码与手机是否匹配,因为是根据验证码去redis中查找手机号,然后根据手机号查询用户
-        //  也就是说 即便黑客以其他方式将验证码发送到自己手机上,最终还是会根据手机号查询用户然后进行重置密码的操作,不存在安全问题
+        // 检验用户是否存在
+        MbrUserDO userDO = checkUserIfExists(reqVO.getMobile());
 
 
-        // TODO @宋天:这块微信在讨论下哈~~~
-
-        // 校验验证码
-        smsCodeService.useSmsCode(userDO.getMobile(), SysSmsSceneEnum.FORGET_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
+        // 使用验证码
+        smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.FORGET_MOBILE_BY_SMS.getScene(),reqVO.getCode(),getClientIP());
 
 
         // 更新密码
         // 更新密码
-        userDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
-        userMapper.updateById(userDO);
-    }
-
-    @Override
-    public void checkIfMobileMatchCodeAndDeleteCode(String phone, String code) {
-        // 检验用户手机与验证码是否匹配
-        String mobile = stringRedisTemplate.opsForValue().get(code);
-        if (!phone.equals(mobile)){
-            throw exception(USER_CODE_FAILED);
-        }
-        // 销毁redis中此验证码
-        stringRedisTemplate.delete(code);
+        MbrUserDO mbrUserDO = MbrUserDO.builder().build();
+        mbrUserDO.setId(userDO.getId());
+        mbrUserDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
+        userMapper.updateById(mbrUserDO);
     }
     }
 
 
     /**
     /**
@@ -347,6 +330,15 @@ public class SysAuthServiceImpl implements SysAuthService {
         return user;
         return user;
     }
     }
 
 
+    public MbrUserDO checkUserIfExists(String mobile) {
+        MbrUserDO user = userMapper.selectByMobile(mobile);
+        if (user == null) {
+            throw exception(USER_NOT_EXISTS);
+        }
+        return user;
+    }
+
+
     private void createLogoutLog(Long userId, String username) {
     private void createLogoutLog(Long userId, String username) {
         SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
         SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
         reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
         reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());

+ 16 - 11
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.userserver.modules.system.service.sms;
 
 
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.validation.Mobile;
 import cn.iocoder.yudao.framework.common.validation.Mobile;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;
+import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
 
 
 /**
 /**
@@ -15,33 +15,38 @@ public interface SysSmsCodeService {
     /**
     /**
      * 创建短信验证码,并进行发送
      * 创建短信验证码,并进行发送
      *
      *
-     * @param mobile 手机号
-     * @param scene 发送场景 {@link SysSmsSceneEnum}
+     * @param mobile   手机号
+     * @param scene    发送场景 {@link SysSmsSceneEnum}
      * @param createIp 发送 IP
      * @param createIp 发送 IP
      */
      */
     void sendSmsCode(@Mobile String mobile, Integer scene, String createIp);
     void sendSmsCode(@Mobile String mobile, Integer scene, String createIp);
 
 
-    /**
-     * 发送短信验证码,并检测手机号是否已被注册
-     * @param reqVO 请求实体
-     */
-    void sendSmsNewCode(SysAuthSendSmsReqVO reqVO);
-
     /**
     /**
      * 验证短信验证码,并进行使用
      * 验证短信验证码,并进行使用
      * 如果正确,则将验证码标记成已使用
      * 如果正确,则将验证码标记成已使用
      * 如果错误,则抛出 {@link ServiceException} 异常
      * 如果错误,则抛出 {@link ServiceException} 异常
      *
      *
      * @param mobile 手机号
      * @param mobile 手机号
-     * @param scene 发送场景
-     * @param code 验证码
+     * @param scene  发送场景
+     * @param code   验证码
      * @param usedIp 使用 IP
      * @param usedIp 使用 IP
      */
      */
     void useSmsCode(@Mobile String mobile, Integer scene, String code, String usedIp);
     void useSmsCode(@Mobile String mobile, Integer scene, String code, String usedIp);
 
 
     /**
     /**
      * 根据用户id发送验证码
      * 根据用户id发送验证码
+     *
      * @param userId 用户id
      * @param userId 用户id
      */
      */
     void sendSmsCodeLogin(Long userId);
     void sendSmsCodeLogin(Long userId);
+
+
+    /**
+     * 检查验证码是否有效
+     * @param mobile 手机
+     * @param code 验证码
+     * @param scene 使用场景
+     * @return 验证码记录
+     */
+    SysSmsCodeDO checkCodeIsExpired(String mobile, String code, Integer scene);
 }
 }

+ 38 - 38
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java

@@ -4,20 +4,16 @@ import cn.hutool.core.map.MapUtil;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService;
 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.dal.mysql.sms.SysSmsCodeMapper;
 import cn.iocoder.yudao.userserver.modules.system.dal.mysql.sms.SysSmsCodeMapper;
 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
-import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsTemplateCodeConstants;
 import cn.iocoder.yudao.userserver.modules.system.framework.sms.SmsCodeProperties;
 import cn.iocoder.yudao.userserver.modules.system.framework.sms.SmsCodeProperties;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
-import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.validation.annotation.Validated;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.Date;
-import java.util.concurrent.TimeUnit;
 
 
 import static cn.hutool.core.util.RandomUtil.randomInt;
 import static cn.hutool.core.util.RandomUtil.randomInt;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -33,11 +29,6 @@ import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConst
 @Validated
 @Validated
 public class SysSmsCodeServiceImpl implements SysSmsCodeService {
 public class SysSmsCodeServiceImpl implements SysSmsCodeService {
 
 
-    /**
-     * 验证码 + 手机 在redis中存储的有效时间,单位:分钟
-     */
-    private static final Long CODE_TIME = 10L;
-
     @Resource
     @Resource
     private SmsCodeProperties smsCodeProperties;
     private SmsCodeProperties smsCodeProperties;
 
 
@@ -50,40 +41,38 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
     @Resource
     @Resource
     private SysSmsCoreService smsCoreService;
     private SysSmsCoreService smsCoreService;
 
 
-    @Resource
-    private StringRedisTemplate stringRedisTemplate;
-
     @Override
     @Override
     public void sendSmsCode(String mobile, Integer scene, String createIp) {
     public void sendSmsCode(String mobile, Integer scene, String createIp) {
         // 创建验证码
         // 创建验证码
         String code = this.createSmsCode(mobile, scene, createIp);
         String code = this.createSmsCode(mobile, scene, createIp);
+
+        // 获取发送模板
+        String codeTemplate = SysSmsSceneEnum.getCodeByScene(scene);
+
+        // 如果是更换手机号发送验证码,则需要检测手机号是否被注册
+        if (SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene().equals(scene)){
+            this.checkMobileIsRegister(mobile,scene);
+        }
+
         // 发送验证码
         // 发送验证码
-        // TODO @宋天:这里可以拓展下 SysSmsSceneEnum,支持设置对应的短信模板编号(不同场景的短信文案是不同的)、是否要校验手机号已经注册。这样 Controller 就可以收口成一个接口了。相当于说,不同场景,不同策略
-        smsCoreService.sendSingleSmsToMember(mobile, null, SysSmsTemplateCodeConstants.USER_SMS_LOGIN,
+        smsCoreService.sendSingleSmsToMember(mobile, null, codeTemplate,
                 MapUtil.of("code", code));
                 MapUtil.of("code", code));
-
-        // 存储手机号与验证码到redis,用于标记
-        // TODO @宋天:SysSmsCodeDO 表应该足够,无需增加额外的 redis 存储哇
-        // TODO @宋天:Redis 相关的操作,不要散落到业务层,而是写一个它对应的 RedisDAO。这样,实现业务与技术的解耦
-        // TODO @宋天:直接使用 code 作为 key,会存在 2 个问题:1)code 可能会冲突,多个手机号之间;2)缺少前缀。例如说 sms_code_${code}
-        stringRedisTemplate.opsForValue().set(code,mobile,CODE_TIME, TimeUnit.MINUTES);
     }
     }
 
 
-    @Override
-    public void sendSmsNewCode(SysAuthSendSmsReqVO reqVO) {
+    public void checkMobileIsRegister(String mobile, Integer scene) {
         // 检测手机号是否已被使用
         // 检测手机号是否已被使用
-        MbrUserDO userByMobile = mbrUserService.getUserByMobile(reqVO.getMobile());
+        MbrUserDO userByMobile = mbrUserService.getUserByMobile(mobile);
         if (userByMobile != null){
         if (userByMobile != null){
             throw exception(USER_SMS_CODE_IS_EXISTS);
             throw exception(USER_SMS_CODE_IS_EXISTS);
         }
         }
 
 
         // 发送短信
         // 发送短信
-        this.sendSmsCode(reqVO.getMobile(),reqVO.getScene(),getClientIP());
+        this.sendSmsCode(mobile,scene,getClientIP());
     }
     }
 
 
     private String createSmsCode(String mobile, Integer scene, String ip) {
     private String createSmsCode(String mobile, Integer scene, String ip) {
         // 校验是否可以发送验证码,不用筛选场景
         // 校验是否可以发送验证码,不用筛选场景
-        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null);
+        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null,null);
         if (lastSmsCode != null) {
         if (lastSmsCode != null) {
             if (lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。
             if (lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。
                 throw exception(USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);
                 throw exception(USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);
@@ -107,21 +96,14 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
 
 
     @Override
     @Override
     public void useSmsCode(String mobile, Integer scene, String code, String usedIp) {
     public void useSmsCode(String mobile, Integer scene, String code, String usedIp) {
-        // 校验验证码
-        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, scene);
-        if (lastSmsCode == null) { // 若验证码不存在,抛出异常
-            throw exception(USER_SMS_CODE_NOT_FOUND);
-        }
-        if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()
-                >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
-            throw exception(USER_SMS_CODE_EXPIRED);
-        }
-        if (lastSmsCode.getUsed()) { // 验证码已使用
+
+        // 检测验证码是否有效
+        SysSmsCodeDO lastSmsCode = this.checkCodeIsExpired(mobile, code, scene);
+
+        // 判断验证码是否已被使用
+        if (Boolean.TRUE.equals(lastSmsCode.getUsed())) {
             throw exception(USER_SMS_CODE_USED);
             throw exception(USER_SMS_CODE_USED);
         }
         }
-        if (!lastSmsCode.getCode().equals(code)) {
-            throw exception(USER_SMS_CODE_NOT_CORRECT);
-        }
 
 
         // 使用验证码
         // 使用验证码
         smsCodeMapper.updateById(SysSmsCodeDO.builder().id(lastSmsCode.getId())
         smsCodeMapper.updateById(SysSmsCodeDO.builder().id(lastSmsCode.getId())
@@ -138,4 +120,22 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
         this.sendSmsCode(user.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), getClientIP());
         this.sendSmsCode(user.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), getClientIP());
     }
     }
 
 
+    @Override
+    public SysSmsCodeDO checkCodeIsExpired(String mobile, String code, Integer scene) {
+        // 校验验证码
+        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile,code,scene);
+
+        // 若验证码不存在,抛出异常
+        if (lastSmsCode == null) {
+            throw exception(USER_SMS_CODE_NOT_FOUND);
+        }
+        if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()
+                >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
+            throw exception(USER_SMS_CODE_EXPIRED);
+        }
+
+        return lastSmsCode;
+
+    }
+
 }
 }

+ 0 - 62
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/controller/SysUserProfileControllerTest.java

@@ -1,62 +0,0 @@
-package cn.iocoder.yudao.userserver.modules.member.controller;
-
-import cn.iocoder.yudao.userserver.modules.member.controller.user.SysUserProfileController;
-import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
-import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.http.MediaType;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-
-
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-/**
- * {@link SysUserProfileController} 的单元测试类
- *
- * @author 宋天
- */
-// TODO @宋天:controller 的单测可以不写哈,因为收益太低了。未来我们做 qa 自动化测试
-public class SysUserProfileControllerTest {
-
-    private MockMvc mockMvc;
-
-    @InjectMocks
-    private SysUserProfileController sysUserProfileController;
-
-    @Mock
-    private MbrUserService userService;
-
-    @Mock
-    private SysSmsCodeService smsCodeService;
-
-    @Before // TODO @宋天:使用 junit5 哈
-    public void setup() {
-        // 初始化
-        MockitoAnnotations.openMocks(this);
-
-        // 构建mvc环境
-        mockMvc = MockMvcBuilders.standaloneSetup(sysUserProfileController).build();
-    }
-
-    @Test
-    @Ignore
-    public void testUpdateMobile_success() throws Exception {
-        //模拟接口调用
-        this.mockMvc.perform(post("/system/user/profile/update-mobile")
-                        .contentType(MediaType.APPLICATION_JSON_VALUE)
-                        .content("{\"mobile\":\"15819844280\",\"code\":\"123456\"}}"))
-                .andExpect(status().isOk())
-                .andDo(MockMvcResultHandlers.print());
-// TODO @宋天:方法的结尾,不用空行哈
-    }
-
-
-}

+ 15 - 13
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.userserver.modules.member.service;
 package cn.iocoder.yudao.userserver.modules.member.service;
 
 
+import cn.hutool.core.util.RandomUtil;
 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -10,8 +11,7 @@ import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfo
 import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
 import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
 import cn.iocoder.yudao.userserver.modules.member.service.user.impl.MbrUserServiceImpl;
 import cn.iocoder.yudao.userserver.modules.member.service.user.impl.MbrUserServiceImpl;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;
-import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
+import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;
 import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
@@ -27,6 +27,7 @@ import java.util.function.Consumer;
 import static cn.hutool.core.util.RandomUtil.*;
 import static cn.hutool.core.util.RandomUtil.*;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
+import static cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.*;
 import static org.mockito.Mockito.*;
 
 
@@ -115,23 +116,24 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
         userDO.setMobile(oldMobile);
         userDO.setMobile(oldMobile);
         userMapper.insert(userDO);
         userMapper.insert(userDO);
 
 
-        // 验证旧手机
-        sysSmsCodeService.sendSmsCodeLogin(userDO.getId());
 
 
-        // 验证旧手机验证码是否正确
-        sysSmsCodeService.useSmsCode(oldMobile,SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(),"123","1.1.1.1");
-        // 验证新手机
-        SysAuthSendSmsReqVO smsReqVO = new SysAuthSendSmsReqVO();
-        smsReqVO.setMobile(oldMobile);
-        smsReqVO.setScene(SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
-        sysSmsCodeService.sendSmsNewCode(smsReqVO);
+        // 旧手机和旧验证码
+        SysSmsCodeDO codeDO = new SysSmsCodeDO();
+        String oldCode = RandomUtil.randomString(4);
+        codeDO.setMobile(userDO.getMobile());
+        codeDO.setCode(oldCode);
+        codeDO.setScene(CHANGE_MOBILE_BY_SMS.getScene());
+        codeDO.setUsed(Boolean.FALSE);
+        when(sysSmsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO);
 
 
         // 更新手机号
         // 更新手机号
         String newMobile = randomNumbers(11);
         String newMobile = randomNumbers(11);
-        String code = randomNumbers(4);
+        String newCode = randomNumbers(4);
         MbrUserUpdateMobileReqVO reqVO = new MbrUserUpdateMobileReqVO();
         MbrUserUpdateMobileReqVO reqVO = new MbrUserUpdateMobileReqVO();
         reqVO.setMobile(newMobile);
         reqVO.setMobile(newMobile);
-        reqVO.setCode(code);
+        reqVO.setCode(newCode);
+        reqVO.setOldMobile(oldMobile);
+        reqVO.setOldCode(oldCode);
         mbrUserService.updateMobile(userDO.getId(),reqVO);
         mbrUserService.updateMobile(userDO.getId(),reqVO);
 
 
         assertEquals(mbrUserService.getUser(userDO.getId()).getMobile(),newMobile);
         assertEquals(mbrUserService.getUser(userDO.getId()).getMobile(),newMobile);

+ 0 - 68
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/controller/SysAuthControllerTest.java

@@ -1,68 +0,0 @@
-package cn.iocoder.yudao.userserver.modules.system.controller;
-
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.SysAuthController;
-import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
-import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.http.MediaType;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-/**
- * {@link SysAuthController} 的单元测试类
- *
- * @author 宋天
- */
-public class SysAuthControllerTest {
-
-    private MockMvc mockMvc;
-
-    @InjectMocks
-    private SysAuthController sysAuthController;
-
-    @Mock
-    private SysAuthService authService;
-    @Mock
-    private SysSmsCodeService smsCodeService;
-    @Mock
-    private SysSocialCoreService socialService;
-
-    @Before
-    public void setup() {
-        // 初始化
-        MockitoAnnotations.openMocks(this);
-
-        // 构建mvc环境
-        mockMvc = MockMvcBuilders.standaloneSetup(sysAuthController).build();
-    }
-
-    @Test
-    public void testResetPassword_success() throws Exception {
-        // 模拟接口调用
-        this.mockMvc.perform(post("/reset-password")
-                        .contentType(MediaType.APPLICATION_JSON)
-                        .content("{\"password\":\"1123\",\"code\":\"123456\"}}"))
-                .andExpect(status().isOk())
-                .andDo(MockMvcResultHandlers.print());
-    }
-
-    @Test
-    public void testUpdatePassword_success() throws Exception {
-        // 模拟接口调用
-        this.mockMvc.perform(post("/update-password")
-                        .contentType(MediaType.APPLICATION_JSON)
-                        .content("{\"password\":\"1123\",\"code\":\"123456\",\"oldPassword\":\"1123\"}}"))
-                .andExpect(status().isOk())
-                .andDo(MockMvcResultHandlers.print());
-    }
-
-}

+ 5 - 8
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java

@@ -23,7 +23,6 @@ import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
-import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 
 
 import static cn.hutool.core.util.RandomUtil.randomEle;
 import static cn.hutool.core.util.RandomUtil.randomEle;
@@ -99,17 +98,15 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
         // 随机验证码
         // 随机验证码
         String code = randomNumbers(4);
         String code = randomNumbers(4);
 
 
-        MbrAuthResetPasswordReqVO reqVO = MbrAuthResetPasswordReqVO.builder()
-                .password(password)
-                .code(code)
-                .build();
-        // 放入code+手机号
-        stringRedisTemplate.opsForValue().set(code,userDO.getMobile(),10, TimeUnit.MINUTES);
-
         // mock
         // mock
         when(passwordEncoder.encode(password)).thenReturn(password);
         when(passwordEncoder.encode(password)).thenReturn(password);
 
 
         // 更新用户密码
         // 更新用户密码
+        MbrAuthResetPasswordReqVO reqVO = new MbrAuthResetPasswordReqVO();
+        reqVO.setMobile(userDO.getMobile());
+        reqVO.setPassword(password);
+        reqVO.setCode(code);
+
         authService.resetPassword(reqVO);
         authService.resetPassword(reqVO);
         assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),password);
         assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),password);
     }
     }