From 333a1b4a377a03230c7726e2828b774629276856 Mon Sep 17 00:00:00 2001 From: lihongjie0209 Date: Thu, 23 Nov 2023 22:30:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=87=8D=E7=BD=AE=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/lihongjie/coal/common/Constants.java | 3 + .../controller/ResetPwdController.java | 64 +++++++ .../resetPwd/dto/ConfirmResetPasswordDto.java | 17 ++ .../coal/resetPwd/dto/CreateResetPwdDto.java | 23 +++ .../coal/resetPwd/dto/ResetPwdDto.java | 38 ++++ .../coal/resetPwd/dto/UpdateResetPwdDto.java | 9 + .../coal/resetPwd/entity/ResetPwdEntity.java | 49 +++++ .../coal/resetPwd/mapper/ResetPwdMapper.java | 19 ++ .../repository/ResetPwdRepository.java | 10 ++ .../resetPwd/service/ResetPwdService.java | 168 ++++++++++++++++++ .../sysconfig/service/SysConfigService.java | 39 ++++ .../coal/user/service/UserService.java | 13 ++ 12 files changed, 452 insertions(+) create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/controller/ResetPwdController.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/dto/ConfirmResetPasswordDto.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/dto/CreateResetPwdDto.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/dto/ResetPwdDto.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/dto/UpdateResetPwdDto.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/entity/ResetPwdEntity.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/mapper/ResetPwdMapper.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/repository/ResetPwdRepository.java create mode 100644 src/main/java/cn/lihongjie/coal/resetPwd/service/ResetPwdService.java diff --git a/src/main/java/cn/lihongjie/coal/common/Constants.java b/src/main/java/cn/lihongjie/coal/common/Constants.java index 458eae3c..34de2402 100644 --- a/src/main/java/cn/lihongjie/coal/common/Constants.java +++ b/src/main/java/cn/lihongjie/coal/common/Constants.java @@ -15,4 +15,7 @@ public class Constants { public static String SYSCONFIG_ENABLE_CAPTCHA = "enable_captcha"; public static String SYSCONFIG_SESSION_TIMEOUT = "session_timeout"; public static String SYSCONFIG_ACCOUNT_MAX_ONLINE = "account_max_online"; + public static String SYSCONFIG_RESETPWD_ENABLE = "resetpwd_enable"; + public static String SYSCONFIG_RESETPWD_TIMEOUT = "resetpwd_timeout"; + public static String SYSCONFIG_RESETPWD_MAX_FAIL_COUNT = "resetpwd_max_fail_count"; } diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/controller/ResetPwdController.java b/src/main/java/cn/lihongjie/coal/resetPwd/controller/ResetPwdController.java new file mode 100644 index 00000000..a7426793 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/controller/ResetPwdController.java @@ -0,0 +1,64 @@ +package cn.lihongjie.coal.resetPwd.controller; + +import cn.lihongjie.coal.annotation.SysLog; +import cn.lihongjie.coal.base.dto.CommonQuery; +import cn.lihongjie.coal.base.dto.IdRequest; +import cn.lihongjie.coal.resetPwd.dto.ConfirmResetPasswordDto; +import cn.lihongjie.coal.resetPwd.dto.CreateResetPwdDto; +import cn.lihongjie.coal.resetPwd.dto.ResetPwdDto; +import cn.lihongjie.coal.resetPwd.dto.UpdateResetPwdDto; +import cn.lihongjie.coal.resetPwd.service.ResetPwdService; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +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; + +@RestController +@RequestMapping("/resetPwd") +@SysLog(module = "重置密码") +@Slf4j +public class ResetPwdController { + @Autowired private ResetPwdService service; + + @PostMapping("/create") + public ResetPwdDto create(@RequestBody CreateResetPwdDto request) { + return this.service.create(request); + } + + @PostMapping("/update") + public ResetPwdDto update(@RequestBody UpdateResetPwdDto request) { + return this.service.update(request); + } + + @PostMapping("/delete") + public Object delete(@RequestBody IdRequest request) { + this.service.delete(request); + return true; + } + + @PostMapping("/getById") + public ResetPwdDto getById(@RequestBody IdRequest request) { + return this.service.getById(request.getId()); + } + + @PostMapping("/list") + public Page list(@RequestBody CommonQuery request) { + return this.service.list(request); + } + + @PostMapping("/startReset") + public String startReset(@RequestBody CreateResetPwdDto request) { + return this.service.startReset(request); + } + + @PostMapping("/confirmReset") + public Object confirmReset(@RequestBody ConfirmResetPasswordDto request) { + this.service.confirmReset(request); + return null; + } +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/dto/ConfirmResetPasswordDto.java b/src/main/java/cn/lihongjie/coal/resetPwd/dto/ConfirmResetPasswordDto.java new file mode 100644 index 00000000..e9718fa5 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/dto/ConfirmResetPasswordDto.java @@ -0,0 +1,17 @@ +package cn.lihongjie.coal.resetPwd.dto; + +import lombok.Data; + +import java.util.*; + +@Data +public class ConfirmResetPasswordDto extends CreateResetPwdDto{ + + private String id; + + private String code; + + private String password; + + +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/dto/CreateResetPwdDto.java b/src/main/java/cn/lihongjie/coal/resetPwd/dto/CreateResetPwdDto.java new file mode 100644 index 00000000..0dabecd7 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/dto/CreateResetPwdDto.java @@ -0,0 +1,23 @@ +package cn.lihongjie.coal.resetPwd.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; + +import lombok.Data; + +import org.hibernate.annotations.Comment; + +@Data +public class CreateResetPwdDto extends OrgCommonDto { + private String userName; + + + @Comment("手机号") + private String phone; + + + @Comment("邮箱") + private String email; + + + +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/dto/ResetPwdDto.java b/src/main/java/cn/lihongjie/coal/resetPwd/dto/ResetPwdDto.java new file mode 100644 index 00000000..ba6c0c88 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/dto/ResetPwdDto.java @@ -0,0 +1,38 @@ +package cn.lihongjie.coal.resetPwd.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; +import cn.lihongjie.coal.user.dto.UserDto; + +import lombok.Data; + +import org.hibernate.annotations.Comment; + +import java.time.LocalDateTime; + +@Data +public class ResetPwdDto extends OrgCommonDto { + private UserDto user; + + + @Comment("手机号") + private String phone; + + + @Comment("邮箱") + private String email; + + + @Comment("验证码") + private String code; + + @Comment("最大失败次数, 超过之后需要重新获取验证码") + private Integer maxFailCount; + + + @Comment("失败次数") + private Integer failCount; + + + @Comment("过期时间") + private LocalDateTime expireTime; +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/dto/UpdateResetPwdDto.java b/src/main/java/cn/lihongjie/coal/resetPwd/dto/UpdateResetPwdDto.java new file mode 100644 index 00000000..d7867e5d --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/dto/UpdateResetPwdDto.java @@ -0,0 +1,9 @@ +package cn.lihongjie.coal.resetPwd.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; + +import lombok.Data; + +@Data +public class UpdateResetPwdDto extends OrgCommonDto { +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/entity/ResetPwdEntity.java b/src/main/java/cn/lihongjie/coal/resetPwd/entity/ResetPwdEntity.java new file mode 100644 index 00000000..6bdb73bf --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/entity/ResetPwdEntity.java @@ -0,0 +1,49 @@ +package cn.lihongjie.coal.resetPwd.entity; + +import cn.lihongjie.coal.base.entity.OrgCommonEntity; +import cn.lihongjie.coal.user.entity.UserEntity; + +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; + +import lombok.Data; + +import org.hibernate.annotations.Comment; + +import java.time.LocalDateTime; + +@Data +@Entity +public class ResetPwdEntity extends OrgCommonEntity { + + + @ManyToOne + private UserEntity user; + + + @Comment("手机号") + private String phone; + + + @Comment("邮箱") + private String email; + + + @Comment("验证码") + private String code; + + @Comment("最大失败次数, 超过之后需要重新获取验证码") + private Integer maxFailCount; + + + @Comment("失败次数") + private Integer failCount; + + + @Comment("过期时间") + private LocalDateTime expireTime; + + + + +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/mapper/ResetPwdMapper.java b/src/main/java/cn/lihongjie/coal/resetPwd/mapper/ResetPwdMapper.java new file mode 100644 index 00000000..3b85a783 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/mapper/ResetPwdMapper.java @@ -0,0 +1,19 @@ +package cn.lihongjie.coal.resetPwd.mapper; + +import cn.lihongjie.coal.base.mapper.BaseMapper; +import cn.lihongjie.coal.base.mapper.CommonMapper; +import cn.lihongjie.coal.resetPwd.dto.CreateResetPwdDto; +import cn.lihongjie.coal.resetPwd.dto.ResetPwdDto; +import cn.lihongjie.coal.resetPwd.dto.UpdateResetPwdDto; +import cn.lihongjie.coal.resetPwd.entity.ResetPwdEntity; + +import org.mapstruct.Mapper; +import org.mapstruct.control.DeepClone; + +@Mapper( + componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING, + uses = {CommonMapper.class}, + mappingControl = DeepClone.class +) +public interface ResetPwdMapper extends BaseMapper { +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/repository/ResetPwdRepository.java b/src/main/java/cn/lihongjie/coal/resetPwd/repository/ResetPwdRepository.java new file mode 100644 index 00000000..7be24012 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/repository/ResetPwdRepository.java @@ -0,0 +1,10 @@ +package cn.lihongjie.coal.resetPwd.repository; + +import cn.lihongjie.coal.base.dao.BaseRepository; +import cn.lihongjie.coal.resetPwd.entity.ResetPwdEntity; + +import org.springframework.stereotype.Repository; + +@Repository +public interface ResetPwdRepository extends BaseRepository { +} diff --git a/src/main/java/cn/lihongjie/coal/resetPwd/service/ResetPwdService.java b/src/main/java/cn/lihongjie/coal/resetPwd/service/ResetPwdService.java new file mode 100644 index 00000000..41840495 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/resetPwd/service/ResetPwdService.java @@ -0,0 +1,168 @@ +package cn.lihongjie.coal.resetPwd.service; + +import cn.lihongjie.coal.base.dto.CommonQuery; +import cn.lihongjie.coal.base.dto.IdRequest; +import cn.lihongjie.coal.base.service.BaseService; +import cn.lihongjie.coal.common.Constants; +import cn.lihongjie.coal.exception.BizException; +import cn.lihongjie.coal.resetPwd.dto.ConfirmResetPasswordDto; +import cn.lihongjie.coal.resetPwd.dto.CreateResetPwdDto; +import cn.lihongjie.coal.resetPwd.dto.ResetPwdDto; +import cn.lihongjie.coal.resetPwd.dto.UpdateResetPwdDto; +import cn.lihongjie.coal.resetPwd.entity.ResetPwdEntity; +import cn.lihongjie.coal.resetPwd.mapper.ResetPwdMapper; +import cn.lihongjie.coal.resetPwd.repository.ResetPwdRepository; +import cn.lihongjie.coal.sysconfig.service.SysConfigService; +import cn.lihongjie.coal.user.entity.UserEntity; +import cn.lihongjie.coal.user.service.UserService; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; + +@Service +@Slf4j +@Transactional +public class ResetPwdService extends BaseService { + @Autowired UserService userService; + @Autowired SysConfigService sysConfigService; + @Autowired private ResetPwdRepository repository; + @Autowired private ResetPwdMapper mapper; + @Autowired private ConversionService conversionService; + + public ResetPwdDto create(CreateResetPwdDto request) { + ResetPwdEntity entity = mapper.toEntity(request); + + this.repository.save(entity); + return getById(entity.getId()); + } + + public ResetPwdDto update(UpdateResetPwdDto request) { + ResetPwdEntity entity = this.repository.get(request.getId()); + this.mapper.updateEntity(entity, request); + + this.repository.save(entity); + + return getById(entity.getId()); + } + + public void delete(IdRequest request) { + this.repository.deleteAllById(request.getIds()); + } + + public ResetPwdDto getById(String id) { + ResetPwdEntity entity = repository.get(id); + + return mapper.toDto(entity); + } + + public Page list(CommonQuery query) { + Page page = + repository.findAll( + query.specification(conversionService), + PageRequest.of( + query.getPageNo(), + query.getPageSize(), + Sort.by(query.getOrders()))); + + return page.map(this.mapper::toDto); + } + + public String startReset(CreateResetPwdDto dto) { + + + + if (StringUtils.isEmpty(dto.getUserName())){ + throw new RuntimeException("用户名不能为空"); + } + + if (StringUtils.isEmpty(dto.getEmail()) && StringUtils.isEmpty(dto.getPhone())){ + throw new RuntimeException("邮箱和手机号不能同时为空"); + } + + if (!StringUtils.isEmpty(dto.getEmail()) && !StringUtils.isEmpty(dto.getPhone())){ + throw new RuntimeException("邮箱和手机号不能同时填写"); + } + + + + Optional user = userService.findByUsername(dto.getUserName()); + + if (!user.isPresent()){ + throw new RuntimeException("用户不存在"); + } + + if (!StringUtils.isEmpty(dto.getEmail()) && !dto.getEmail().equals(user.get().getEmail())){ + throw new RuntimeException("邮箱不正确"); + } + + if (!StringUtils.isEmpty(dto.getPhone()) && !dto.getPhone().equals(user.get().getPhone())){ + throw new RuntimeException("手机号不正确"); + } + + ResetPwdEntity resetPwdEntity = new ResetPwdEntity(); + resetPwdEntity.setUser(user.get()); + resetPwdEntity.setPhone(dto.getPhone()); + resetPwdEntity.setEmail(dto.getEmail()); + resetPwdEntity.setCode(ThreadLocalRandom.current().nextInt(100000, 999999) + ""); + resetPwdEntity.setFailCount(0); + resetPwdEntity.setMaxFailCount( + Integer.parseInt( + sysConfigService.getConfigVal( + Constants.SYSCONFIG_RESETPWD_MAX_FAIL_COUNT))); + resetPwdEntity.setExpireTime( + LocalDateTime.now() + .plusSeconds( + Integer.parseInt( + sysConfigService.getConfigVal( + Constants.SYSCONFIG_RESETPWD_TIMEOUT)))); + + this.save(resetPwdEntity); + log.info("重置密码会话创建成功: {}", resetPwdEntity); + + return resetPwdEntity.getId(); + + } + + + public void confirmReset(ConfirmResetPasswordDto dto) { + + ResetPwdEntity resetPwdEntity = this.repository.get(dto.getId()); + + if (resetPwdEntity == null){ + throw new BizException("当前重置密码会话不存在, 请重新开始重置密码"); + } + + + + + if (resetPwdEntity.getFailCount() >= resetPwdEntity.getMaxFailCount()){ + throw new BizException("当前重置密码会话失败次数过多, 请重新开始重置密码"); + } + + if (resetPwdEntity.getExpireTime().isBefore(LocalDateTime.now())){ + throw new BizException("当前重置密码会话已过期, 请重新开始重置密码"); + } + + if (!resetPwdEntity.getCode().equals(dto.getCode())){ + resetPwdEntity.setFailCount(resetPwdEntity.getFailCount() + 1); + this.repository.save(resetPwdEntity); + throw new BizException("验证码不正确"); + } + + userService.resetPwd(resetPwdEntity.getUser().getId(), dto.getPassword()); + + + } +} diff --git a/src/main/java/cn/lihongjie/coal/sysconfig/service/SysConfigService.java b/src/main/java/cn/lihongjie/coal/sysconfig/service/SysConfigService.java index 1b5657bd..44a4c70f 100644 --- a/src/main/java/cn/lihongjie/coal/sysconfig/service/SysConfigService.java +++ b/src/main/java/cn/lihongjie/coal/sysconfig/service/SysConfigService.java @@ -96,6 +96,45 @@ class SysConfigService extends BaseService entity.setType("2"); repository.save(entity); } + + if (!all.containsKey(Constants.SYSCONFIG_RESETPWD_ENABLE)) { + SysConfigEntity entity = new SysConfigEntity(); + entity.setName("重置密码状态"); + entity.setCode(Constants.SYSCONFIG_RESETPWD_ENABLE); + entity.setConfigVal("1"); + entity.setDictCode("status.type"); + entity.setMaxValue(null); + entity.setMinValue(null); + entity.setRegexValidator(null); + entity.setType("3"); + repository.save(entity); + } + + if (!all.containsKey(Constants.SYSCONFIG_RESETPWD_TIMEOUT)) { + SysConfigEntity entity = new SysConfigEntity(); + entity.setName("重置密码会话超时时间(s)"); + entity.setCode(Constants.SYSCONFIG_RESETPWD_TIMEOUT); + entity.setConfigVal(TimeUnit.MINUTES.toSeconds(10) + ""); + entity.setDictCode(null); + entity.setMaxValue((int) TimeUnit.HOURS.toSeconds(24)); + entity.setMinValue((int) TimeUnit.MINUTES.toSeconds(1)); + entity.setRegexValidator(null); + entity.setType("2"); + repository.save(entity); + } + + if (!all.containsKey(Constants.SYSCONFIG_RESETPWD_MAX_FAIL_COUNT)) { + SysConfigEntity entity = new SysConfigEntity(); + entity.setName("重置密码最多失败次数"); + entity.setCode(Constants.SYSCONFIG_RESETPWD_MAX_FAIL_COUNT); + entity.setConfigVal(3+""); + entity.setDictCode(null); + entity.setMaxValue(Integer.MAX_VALUE); + entity.setMinValue(1); + entity.setRegexValidator(null); + entity.setType("2"); + repository.save(entity); + } } @Autowired diff --git a/src/main/java/cn/lihongjie/coal/user/service/UserService.java b/src/main/java/cn/lihongjie/coal/user/service/UserService.java index 8a10310c..636765b3 100644 --- a/src/main/java/cn/lihongjie/coal/user/service/UserService.java +++ b/src/main/java/cn/lihongjie/coal/user/service/UserService.java @@ -176,6 +176,19 @@ class UserService extends BaseService { return getById(request.getId()); } + public void resetPwd(String userId, String password) { + + UserEntity user = + repository.findById(userId).orElseThrow(() -> new BizException("用户不存在")); + + + + user.setPassword(passwordEncoder.encode(password)); + + repository.save(user); + + } + public Page list(CommonQuery query) { Page page =