diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/controllers/v1/UserController.java b/src/main/kotlin/com/frontleaves/fantasticeditor/controllers/v1/UserController.java index 215b857..1c2d727 100644 --- a/src/main/kotlin/com/frontleaves/fantasticeditor/controllers/v1/UserController.java +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/controllers/v1/UserController.java @@ -16,6 +16,7 @@ import com.frontleaves.fantasticeditor.exceptions.BusinessException; import com.frontleaves.fantasticeditor.models.vo.api.user.UserMailVerifyVO; +import com.frontleaves.fantasticeditor.models.vo.api.user.UserPublicInfoVO; import com.frontleaves.fantasticeditor.services.interfaces.UserService; import com.frontleaves.fantasticeditor.utility.BaseResponse; import com.frontleaves.fantasticeditor.utility.ErrorCode; @@ -31,50 +32,72 @@ *
* 用户控制器,用于处理用户相关的请求; * - * @since v1.0.0 - * @version v1.0.0 * @author xiao_lfeng + * @version v1.0.0 + * @since v1.0.0 */ @Slf4j @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/user") public class UserController { - private final UserService userService; + private final UserService userService; + + /** + * 邮箱验证 + *
+ * 用户邮箱验证的地址,用于验证用户的邮箱是否合法;邮箱验证码的发送会根据用户在注册后,执行 authResendMailVerify 方法时的邮箱地址发送; + * 验证码的有效时间为 15 分钟;获取到的验证码在当前接口进行验证; + * + * @return 注册结果 + */ + @PostMapping("/mail/verify") + public ResponseEntity> userMailVerify( + @RequestBody @Validated final UserMailVerifyVO userMailVerifyVO + ) { + userService.checkMailVerify(userMailVerifyVO.getEmail(), userMailVerifyVO.getVerifyCode()); + return ResultUtil.success("验证成功"); + } + + /** + * 重发邮件验证码 + *
+ * 用于用户在注册时,未收到验证码或者验证码失效时,重新发送验证码; + * + * @param email 邮箱地址 + * @return 重发结果 + */ + @GetMapping("/mail/resend") + public ResponseEntity> authResendMailVerify( + @RequestParam("email") final String email + ) { + if (email.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) { + userService.sendMailVerify(email); + return ResultUtil.success("发送成功"); + } else { + throw new BusinessException("邮箱格式错误", ErrorCode.REQUEST_BODY_PARAMETERS_ERROR); + } + } + + /** + * 通过uuid获取用户信息 + *
+ * 根据uuid参数查询用户的基本信息,信息包括:角色组信息,权限信息,付费会员信息,以及个人其他信息 + * + * @param uuid 用户uuid + * @return 用户公开信息 + */ + @GetMapping("/info/get/ByUUID/{uuid}") + public ResponseEntity> getMyUserProfileInfo( + @PathVariable("uuid") final String uuid + ) { + + if (uuid == null || uuid.isEmpty()) { + throw new BusinessException("uuid参数为空", ErrorCode.REQUEST_PARAMETERS_ERROR); + } - /** - * 邮箱验证 - *
- * 用户邮箱验证的地址,用于验证用户的邮箱是否合法;邮箱验证码的发送会根据用户在注册后,执行 authResendMailVerify 方法时的邮箱地址发送; - * 验证码的有效时间为 15 分钟;获取到的验证码在当前接口进行验证; - * - * @return 注册结果 - */ - @PostMapping("/mail/verify") - public ResponseEntity> userMailVerify( - @RequestBody @Validated final UserMailVerifyVO userMailVerifyVO - ) { - userService.checkMailVerify(userMailVerifyVO.getEmail(), userMailVerifyVO.getVerifyCode()); - return ResultUtil.success("验证成功"); - } + UserPublicInfoVO userVO = userService.getMyUserProfileInfo(uuid); + return ResultUtil.success("获取当前用户信息成功", userVO); + } - /** - * 重发邮件验证码 - *
- * 用于用户在注册时,未收到验证码或者验证码失效时,重新发送验证码; - * - * @param email 邮箱地址 - * @return 重发结果 - */ - @GetMapping("/mail/resend") - public ResponseEntity> authResendMailVerify( - @RequestParam("email") final String email - ) { - if (email.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) { - userService.sendMailVerify(email); - return ResultUtil.success("发送成功"); - } else { - throw new BusinessException("邮箱格式错误", ErrorCode.REQUEST_BODY_PARAMETERS_ERROR); - } - } } diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/dao/VipDAO.kt b/src/main/kotlin/com/frontleaves/fantasticeditor/dao/VipDAO.kt new file mode 100644 index 0000000..e6eaba2 --- /dev/null +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/dao/VipDAO.kt @@ -0,0 +1,56 @@ +/* + * ******************************************************************************* + * Copyright (C) 2024-NOW(至今) 妙笔智编 + * Author: 锋楪技术团队 + * + * 本文件包含 妙笔智编「FantasticEditor」 的源代码,该项目的所有源代码均遵循MIT开源许可证协议。 + * 本代码仅允许在十三届软件杯比赛授权比赛方可直接使用 + * ******************************************************************************* + * 免责声明: + * 使用本软件的风险由用户自担。作者或版权持有人在法律允许的最大范围内, + * 对因使用本软件内容而导致的任何直接或间接的损失不承担任何责任。 + * ******************************************************************************* + */ + +package com.frontleaves.fantasticeditor.dao + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper +import com.baomidou.mybatisplus.extension.service.IService +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import com.frontleaves.fantasticeditor.mappers.VipMapper +import com.frontleaves.fantasticeditor.models.entity.sql.SqlVipDO +import com.frontleaves.fantasticeditor.utility.Util +import com.frontleaves.fantasticeditor.utility.redis.RedisUtil +import org.springframework.stereotype.Repository + +/** + * # 会员数据访问对象 + * 用于定义会员数据访问对象; + * + * @since v1.0.0 + * @see ServiceImpl + * @property VipMapper 会员映射器 + * @property SqlVipDO 会员实体类 + * @constructor 创建一个会员数据访问对象 + * @author zrx + */ +@Repository +class VipDAO(private val redisUtil: RedisUtil) : + ServiceImpl(), IService { + + /** + * ## 通过UUID获取会员 + * 通过UUID获取会员的基本信息 + * + * @param vuuid 会员UUID + * @return 会员实体类 + */ + fun getVipByVUUID(vuuid: String): SqlVipDO? { + return redisUtil.hashGet("vip:vuuid:$vuuid") + .takeIf { !it.isNullOrEmpty() }?.let { + Util.mapToObject(it, SqlVipDO::class.java) + } ?: run { + this.getOne(QueryWrapper().eq("vuuid", vuuid)) + } + } +} diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/mappers/VipMapper.kt b/src/main/kotlin/com/frontleaves/fantasticeditor/mappers/VipMapper.kt new file mode 100644 index 0000000..ca75b17 --- /dev/null +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/mappers/VipMapper.kt @@ -0,0 +1,30 @@ +/* + * ******************************************************************************* + * Copyright (C) 2024-NOW(至今) 妙笔智编 + * Author: 锋楪技术团队 + * + * 本文件包含 妙笔智编「FantasticEditor」 的源代码,该项目的所有源代码均遵循MIT开源许可证协议。 + * 本代码仅允许在十三届软件杯比赛授权比赛方可直接使用 + * ******************************************************************************* + * 免责声明: + * 使用本软件的风险由用户自担。作者或版权持有人在法律允许的最大范围内, + * 对因使用本软件内容而导致的任何直接或间接的损失不承担任何责任。 + * ******************************************************************************* + */ + +package com.frontleaves.fantasticeditor.mappers + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import com.frontleaves.fantasticeditor.models.entity.sql.SqlVipDO +import org.apache.ibatis.annotations.Mapper + +/** + * # 会员映射器 + * 用于定义会员映射器; + * + * @since v1.0.0 + * @constructor 创建一个会员映射器 + * @author zrx + */ +@Mapper +interface VipMapper : BaseMapper diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/models/entity/redis/RedisUserPublicInfoDO.java b/src/main/kotlin/com/frontleaves/fantasticeditor/models/entity/redis/RedisUserPublicInfoDO.java new file mode 100644 index 0000000..294f510 --- /dev/null +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/models/entity/redis/RedisUserPublicInfoDO.java @@ -0,0 +1,55 @@ +/* + * ******************************************************************************* + * Copyright (C) 2024-NOW(至今) 妙笔智编 + * Author: 锋楪技术团队 + * + * 本文件包含 妙笔智编「FantasticEditor」 的源代码,该项目的所有源代码均遵循MIT开源许可证协议。 + * 本代码仅允许在十三届软件杯比赛授权比赛方可直接使用 + * ******************************************************************************* + * 免责声明: + * 使用本软件的风险由用户自担。作者或版权持有人在法律允许的最大范围内, + * 对因使用本软件内容而导致的任何直接或间接的损失不承担任何责任。 + * ******************************************************************************* + */ + +package com.frontleaves.fantasticeditor.models.entity.redis; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + * Redis用户基本信息实体 + *

+ * 用于存储用户基本信息的实体 + * @since v1.0.0 + * @version v1.0.0 + * @author zrx + * @date 2024/6/1 8:45 + */ +@Data +@NoArgsConstructor +@Accessors(chain = true) +public class RedisUserPublicInfoDO { + + public String uuid; + + public String username; + + public String email; + + public String phone; + + public String basicInformation; + + public String roleId; + + public String roleName; + + public String vipId; + + public String vipName; + +} + + diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/models/vo/api/user/UserPublicInfoVO.java b/src/main/kotlin/com/frontleaves/fantasticeditor/models/vo/api/user/UserPublicInfoVO.java new file mode 100644 index 0000000..8e49c60 --- /dev/null +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/models/vo/api/user/UserPublicInfoVO.java @@ -0,0 +1,52 @@ +/* + * ******************************************************************************* + * Copyright (C) 2024-NOW(至今) 妙笔智编 + * Author: 锋楪技术团队 + * + * 本文件包含 妙笔智编「FantasticEditor」 的源代码,该项目的所有源代码均遵循MIT开源许可证协议。 + * 本代码仅允许在十三届软件杯比赛授权比赛方可直接使用 + * ******************************************************************************* + * 免责声明: + * 使用本软件的风险由用户自担。作者或版权持有人在法律允许的最大范围内, + * 对因使用本软件内容而导致的任何直接或间接的损失不承担任何责任。 + * ******************************************************************************* + */ + +package com.frontleaves.fantasticeditor.models.vo.api.user; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + * 用户基本信息 + *

+ * + * @author zrx + * @date 2024/5/31 21:33 + * @since v1.0.0 + */ +@Data +@NoArgsConstructor +@Accessors(chain = true) +public class UserPublicInfoVO { + public String uuid; + + public String username; + + public String email; + + public String phone; + + public String basicInformation; + + public String roleId; + + public String roleName; + + public String vipId; + + public String vipName; +} + + diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/services/UserServiceImpl.java b/src/main/kotlin/com/frontleaves/fantasticeditor/services/UserServiceImpl.java index af0aba8..1799d83 100644 --- a/src/main/kotlin/com/frontleaves/fantasticeditor/services/UserServiceImpl.java +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/services/UserServiceImpl.java @@ -19,14 +19,18 @@ import com.frontleaves.fantasticeditor.constant.SmsControl; import com.frontleaves.fantasticeditor.dao.RoleDAO; import com.frontleaves.fantasticeditor.dao.UserDAO; +import com.frontleaves.fantasticeditor.dao.VipDAO; import com.frontleaves.fantasticeditor.exceptions.BusinessException; import com.frontleaves.fantasticeditor.models.dto.UserCurrentDTO; import com.frontleaves.fantasticeditor.models.entity.redis.RedisMailCodeDO; import com.frontleaves.fantasticeditor.models.entity.redis.RedisSmsCodeDO; +import com.frontleaves.fantasticeditor.models.entity.redis.RedisUserPublicInfoDO; import com.frontleaves.fantasticeditor.models.entity.sql.SqlRoleDO; import com.frontleaves.fantasticeditor.models.entity.sql.SqlUserDO; +import com.frontleaves.fantasticeditor.models.entity.sql.SqlVipDO; import com.frontleaves.fantasticeditor.models.vo.api.auth.AuthUserLoginVO; import com.frontleaves.fantasticeditor.models.vo.api.auth.AuthUserRegisterVO; +import com.frontleaves.fantasticeditor.models.vo.api.user.UserPublicInfoVO; import com.frontleaves.fantasticeditor.services.interfaces.MailService; import com.frontleaves.fantasticeditor.services.interfaces.SmsService; import com.frontleaves.fantasticeditor.services.interfaces.UserService; @@ -59,200 +63,249 @@ @Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { - private final UserDAO userDAO; - private final RoleDAO roleDAO; - private final RedisUtil redisUtil; - private final OperateUtil operateUtil; - private final SmsService smsService; - private final MailService mailService; + private final UserDAO userDAO; + private final RoleDAO roleDAO; + private final VipDAO vipDAO; + private final RedisUtil redisUtil; + private final OperateUtil operateUtil; + private final SmsService smsService; + private final MailService mailService; - /** - * 用户注册 - *

- * 用户注册,使用用户名和密码注册 - * - * @param authUserRegisterVO 用户注册信息 - * @return 注册结果 - */ - @NotNull - @Override - public UserCurrentDTO userRegister(final @NotNull AuthUserRegisterVO authUserRegisterVO) { - assert authUserRegisterVO.getUsername() != null; - assert authUserRegisterVO.getEmail() != null; - assert authUserRegisterVO.getPhone() != null; - assert authUserRegisterVO.getPassword() != null; - // 获取信息查询用户 - SqlUserDO getUser = userDAO.getUserByUsername(authUserRegisterVO.getUsername()); - if (getUser == null) { - getUser = userDAO.getUserByEmail(authUserRegisterVO.getEmail()); - } - if (getUser == null) { - getUser = userDAO.getUserByEmail(authUserRegisterVO.getPhone()); - } - if (getUser != null) { - throw new BusinessException("用户已存在", ErrorCode.USER_EXIST); - } - // 获取基本用户组 - SqlRoleDO getRole = roleDAO.getRoleByRoleName("user"); - assert getRole != null; - assert getRole.getRuuid() != null; - // 创建用户 - SqlUserDO user = new SqlUserDO() - .setUuid(Util.INSTANCE.makeNoDashUUID()) - .setUsername(authUserRegisterVO.getUsername()) - .setEmail(authUserRegisterVO.getEmail()) - .setPhone(authUserRegisterVO.getPhone()) - .setPassword(Util.INSTANCE.encryptPassword(authUserRegisterVO.getPassword())) - .setOtpAuth(Util.INSTANCE.makeNoDashUUID()) - .setMailVerify(false) - .setPhoneVerify(true) - .setBasicInformation("{1=1}") - .setRole(getRole.getRuuid()); - if (userDAO.save(user)) { - UserCurrentDTO getUserCurrent = new UserCurrentDTO(); - BeanUtils.copyProperties(user, getUserCurrent); - return getUserCurrent; - } else { - throw new BusinessException("用户注册失败", ErrorCode.OPERATION_FAILED); - } - } + /** + * 用户注册 + *

+ * 用户注册,使用用户名和密码注册 + * + * @param authUserRegisterVO 用户注册信息 + * @return 注册结果 + */ + @NotNull + @Override + public UserCurrentDTO userRegister(final @NotNull AuthUserRegisterVO authUserRegisterVO) { + assert authUserRegisterVO.getUsername() != null; + assert authUserRegisterVO.getEmail() != null; + assert authUserRegisterVO.getPhone() != null; + assert authUserRegisterVO.getPassword() != null; + // 获取信息查询用户 + SqlUserDO getUser = userDAO.getUserByUsername(authUserRegisterVO.getUsername()); + if (getUser == null) { + getUser = userDAO.getUserByEmail(authUserRegisterVO.getEmail()); + } + if (getUser == null) { + getUser = userDAO.getUserByEmail(authUserRegisterVO.getPhone()); + } + if (getUser != null) { + throw new BusinessException("用户已存在", ErrorCode.USER_EXIST); + } + // 获取基本用户组 + SqlRoleDO getRole = roleDAO.getRoleByRoleName("user"); + assert getRole != null; + assert getRole.getRuuid() != null; + // 创建用户 + SqlUserDO user = new SqlUserDO() + .setUuid(Util.INSTANCE.makeNoDashUUID()) + .setUsername(authUserRegisterVO.getUsername()) + .setEmail(authUserRegisterVO.getEmail()) + .setPhone(authUserRegisterVO.getPhone()) + .setPassword(Util.INSTANCE.encryptPassword(authUserRegisterVO.getPassword())) + .setOtpAuth(Util.INSTANCE.makeNoDashUUID()) + .setMailVerify(false) + .setPhoneVerify(true) + .setBasicInformation("{1=1}") + .setRole(getRole.getRuuid()); + if (userDAO.save(user)) { + UserCurrentDTO getUserCurrent = new UserCurrentDTO(); + BeanUtils.copyProperties(user, getUserCurrent); + return getUserCurrent; + } else { + throw new BusinessException("用户注册失败", ErrorCode.OPERATION_FAILED); + } + } - @Override - public void sendRegisterPhoneCode(final @NotNull String phone) { - // 对手机号内容进行检查,检查缓存中是否存在 - operateUtil.checkSmsResendAble(phone); - // 检查此手机是否已被注册 - SqlUserDO getUser = userDAO.getUserByPhone(phone); - if (getUser != null) { - throw new BusinessException("手机号已被注册", ErrorCode.USER_EXIST); - } - // 新建验证码并存入缓存 - String getNumberCode = Util.INSTANCE.generateNumber(6); - RedisSmsCodeDO smsPhoneDO = new RedisSmsCodeDO() - .setPhone(phone) - .setCode(getNumberCode) - .setSendAt(String.valueOf(System.currentTimeMillis())) - .setFrequency("1"); - RedisSmsCodeDO getPhoneCode = Util.INSTANCE.mapToObject( - redisUtil.hashGet("sms:code:" + phone), - RedisSmsCodeDO.class - ); - if (getPhoneCode != null) { - smsPhoneDO.setFrequency(String.valueOf(Long.parseLong(getPhoneCode.getFrequency()) + 1)); - } - if (redisUtil.hashSet("sms:code:" + phone, smsPhoneDO, 15 * 60)) { - // 发送验证码 - if (!smsService.sendCode(phone, getNumberCode, SmsControl.USER_REGISTER)) { - throw new BusinessException("发送失败", ErrorCode.VERIFY_CODE_ERROR); - } - } else { - throw new BusinessException("发送失败", ErrorCode.VERIFY_CODE_ERROR); - } - } + @Override + public void sendRegisterPhoneCode(final @NotNull String phone) { + // 对手机号内容进行检查,检查缓存中是否存在 + operateUtil.checkSmsResendAble(phone); + // 检查此手机是否已被注册 + SqlUserDO getUser = userDAO.getUserByPhone(phone); + if (getUser != null) { + throw new BusinessException("手机号已被注册", ErrorCode.USER_EXIST); + } + // 新建验证码并存入缓存 + String getNumberCode = Util.INSTANCE.generateNumber(6); + RedisSmsCodeDO smsPhoneDO = new RedisSmsCodeDO() + .setPhone(phone) + .setCode(getNumberCode) + .setSendAt(String.valueOf(System.currentTimeMillis())) + .setFrequency("1"); + RedisSmsCodeDO getPhoneCode = Util.INSTANCE.mapToObject( + redisUtil.hashGet("sms:code:" + phone), + RedisSmsCodeDO.class + ); + if (getPhoneCode != null) { + smsPhoneDO.setFrequency(String.valueOf(Long.parseLong(getPhoneCode.getFrequency()) + 1)); + } + if (redisUtil.hashSet("sms:code:" + phone, smsPhoneDO, 15 * 60)) { + // 发送验证码 + if (!smsService.sendCode(phone, getNumberCode, SmsControl.USER_REGISTER)) { + throw new BusinessException("发送失败", ErrorCode.VERIFY_CODE_ERROR); + } + } else { + throw new BusinessException("发送失败", ErrorCode.VERIFY_CODE_ERROR); + } + } - @Override - public boolean userLogin(@NotNull final AuthUserLoginVO authUserLoginVO) { - // 定义邮箱的正则表达式 - String emailRegex = - "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; - Pattern emailPattern = Pattern.compile(emailRegex); - // 定义手机号的正则表达式 - String phoneRegex = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$"; - Pattern phonePattern = Pattern.compile(phoneRegex); - // 先判断传入的username为什么类型 - String username = authUserLoginVO.getUsername(); - Matcher emailMatcher = emailPattern.matcher(username); - Matcher phoneMatcher = phonePattern.matcher(username); - if (emailMatcher.matches()) { - SqlUserDO sqlUserDO = userDAO.getUserByEmail(username); - if (sqlUserDO == null) { - return false; - } - if (!sqlUserDO.getMailVerify()) { - throw new BusinessException("邮箱未验证", ErrorCode.OPERATION_FAILED); - } - if (!Util.INSTANCE.verifyPassword(authUserLoginVO.getPassword(), sqlUserDO.getPassword())) { - throw new BusinessException("邮箱或密码错误", ErrorCode.OPERATION_FAILED); - } - return true; - } else if (phoneMatcher.matches()) { - SqlUserDO sqlUserDO = userDAO.getUserByPhone(username); - if (sqlUserDO == null) { - return false; - } - if (!Util.INSTANCE.verifyPassword(authUserLoginVO.getPassword(), sqlUserDO.getPassword())) { - throw new BusinessException("手机号或密码错误", ErrorCode.OPERATION_FAILED); - } - return true; - } else { - SqlUserDO sqlUserDO = userDAO.getUserByUsername(username); - if (sqlUserDO == null) { - return false; - } - if (!Util.INSTANCE.verifyPassword(authUserLoginVO.getPassword(), sqlUserDO.getPassword())) { - throw new BusinessException("用户名或密码错误", ErrorCode.OPERATION_FAILED); - } - return true; - } - } + @Override + public boolean userLogin(@NotNull final AuthUserLoginVO authUserLoginVO) { + // 定义邮箱的正则表达式 + String emailRegex = + "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; + Pattern emailPattern = Pattern.compile(emailRegex); + // 定义手机号的正则表达式 + String phoneRegex = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$"; + Pattern phonePattern = Pattern.compile(phoneRegex); + // 先判断传入的username为什么类型 + String username = authUserLoginVO.getUsername(); + Matcher emailMatcher = emailPattern.matcher(username); + Matcher phoneMatcher = phonePattern.matcher(username); + if (emailMatcher.matches()) { + SqlUserDO sqlUserDO = userDAO.getUserByEmail(username); + if (sqlUserDO == null) { + return false; + } + if (!sqlUserDO.getMailVerify()) { + throw new BusinessException("邮箱未验证", ErrorCode.OPERATION_FAILED); + } + if (!Util.INSTANCE.verifyPassword(authUserLoginVO.getPassword(), sqlUserDO.getPassword())) { + throw new BusinessException("邮箱或密码错误", ErrorCode.OPERATION_FAILED); + } + return true; + } else if (phoneMatcher.matches()) { + SqlUserDO sqlUserDO = userDAO.getUserByPhone(username); + if (sqlUserDO == null) { + return false; + } + if (!Util.INSTANCE.verifyPassword(authUserLoginVO.getPassword(), sqlUserDO.getPassword())) { + throw new BusinessException("手机号或密码错误", ErrorCode.OPERATION_FAILED); + } + return true; + } else { + SqlUserDO sqlUserDO = userDAO.getUserByUsername(username); + if (sqlUserDO == null) { + return false; + } + if (!Util.INSTANCE.verifyPassword(authUserLoginVO.getPassword(), sqlUserDO.getPassword())) { + throw new BusinessException("用户名或密码错误", ErrorCode.OPERATION_FAILED); + } + return true; + } + } - @Override - @Transactional - public void checkMailVerify(@NotNull final String email, @NotNull final String verifyCode) { - // 获取验证码 - RedisMailCodeDO getMailCode = Util.INSTANCE.mapToObject( - redisUtil.hashGet("mail:code:" + email), - RedisMailCodeDO.class - ); - if (getMailCode == null) { - throw new BusinessException("验证码不存在", ErrorCode.VERIFY_CODE_ERROR); - } - // 检查验证码 - if (!getMailCode.getCode().equals(verifyCode)) { - throw new BusinessException("验证码错误", ErrorCode.VERIFY_CODE_ERROR); - } - // 删除验证码 - redisUtil.delete("mail:code:" + email); - // 检查用户是否已验证 - SqlUserDO getUser = userDAO.getUserByEmail(email); - if (getUser == null) { - throw new BusinessException("用户不存在", ErrorCode.USER_NOT_EXIST); - } - if (getUser.getMailVerify()) { - throw new BusinessException("用户已验证", ErrorCode.OPERATION_FAILED); - } - // 验证成功 - getUser.setMailVerify(true) - .setUpdatedAt(new Timestamp(System.currentTimeMillis())); - if (!userDAO.update(getUser, new UpdateWrapper().eq("uuid", getUser.getUuid()))) { - throw new BusinessException("验证失败", ErrorCode.OPERATION_FAILED); - } - } + @Override + @Transactional + public void checkMailVerify(@NotNull final String email, @NotNull final String verifyCode) { + // 获取验证码 + RedisMailCodeDO getMailCode = Util.INSTANCE.mapToObject( + redisUtil.hashGet("mail:code:" + email), + RedisMailCodeDO.class + ); + if (getMailCode == null) { + throw new BusinessException("验证码不存在", ErrorCode.VERIFY_CODE_ERROR); + } + // 检查验证码 + if (!getMailCode.getCode().equals(verifyCode)) { + throw new BusinessException("验证码错误", ErrorCode.VERIFY_CODE_ERROR); + } + // 删除验证码 + redisUtil.delete("mail:code:" + email); + // 检查用户是否已验证 + SqlUserDO getUser = userDAO.getUserByEmail(email); + if (getUser == null) { + throw new BusinessException("用户不存在", ErrorCode.USER_NOT_EXIST); + } + if (getUser.getMailVerify()) { + throw new BusinessException("用户已验证", ErrorCode.OPERATION_FAILED); + } + // 验证成功 + getUser.setMailVerify(true) + .setUpdatedAt(new Timestamp(System.currentTimeMillis())); + if (!userDAO.update(getUser, new UpdateWrapper().eq("uuid", getUser.getUuid()))) { + throw new BusinessException("验证失败", ErrorCode.OPERATION_FAILED); + } + } + + @Override + public void sendMailVerify(@NotNull final String email) { + // 检查邮箱是否已被注册 + SqlUserDO getUser = userDAO.getUserByEmail(email); + if (getUser == null) { + throw new BusinessException("邮箱未注册", ErrorCode.USER_NOT_EXIST); + } + // 检查邮箱是否已验证 + if (getUser.getMailVerify()) { + throw new BusinessException("邮箱已验证", ErrorCode.OPERATION_FAILED); + } + // 检查前一次所发送的验证码是否已过期或达到可重新发送的标准 + RedisMailCodeDO getMailCode = Util.INSTANCE.mapToObject( + redisUtil.hashGet("mail:code:" + email), + RedisMailCodeDO.class + ); + // 生成验证码 + String getNumberCode = Util.INSTANCE.generateNumber(6); + if (getMailCode != null) { + if (System.currentTimeMillis() - Long.parseLong(getMailCode.getSendAt()) < 60 * 1000) { + throw new BusinessException("发送过于频繁", ErrorCode.OPERATION_FAILED); + } + } + // 发送验证码 + mailService.sendVerifyCodeMail(email, getNumberCode, MailTemplateEnum.USER_REGISTER); + } + + + @Override + public UserPublicInfoVO getMyUserProfileInfo(@NotNull final String uuid) { + + UserPublicInfoVO userPublicInfoVO = new UserPublicInfoVO(); + + // redis查询的uuid + String redisKey = "user:uuid:" + uuid; + + // 先从redis中查询 用户公开信息实体类 + RedisUserPublicInfoDO getUserPInfoFromRedis = + Util.INSTANCE.mapToObject( + redisUtil.hashGet(redisKey), + RedisUserPublicInfoDO.class + ); + + // 如果redis数据不为空,返回redis的数据 + if (getUserPInfoFromRedis != null) { + Util.INSTANCE.copyPropertiesData(getUserPInfoFromRedis, userPublicInfoVO); + } + + // 如果redis数据为空,则进行封装,并将数据存储到redis中 + // 从数据库获取User数据 + SqlUserDO userDO = userDAO.getUserByUUID(uuid); + // 复制属性相同的数据 + Util.INSTANCE.copyPropertiesData(userDO, userPublicInfoVO); + // 设置用户Vip名称 + SqlVipDO vipDO = null; + if (userDO.getVip() != null) { + vipDO = vipDAO.getVipByVUUID(userDO.getVip()); + } + userPublicInfoVO.setVipName( + (vipDO != null && vipDO.getDisplayName() != null) ? vipDO.getDisplayName() : ""); + userPublicInfoVO.setVipId( + (vipDO != null && vipDO.getVuuid() != null) ? vipDO.getVuuid() : ""); + // 设置用户角色名称与id + SqlRoleDO roleDO = roleDAO.getRoleByRUUID(userDO.getRole()); + userPublicInfoVO.setRoleName((roleDO != null && roleDO.getDisplayName() + != null) ? roleDO.getDisplayName() : ""); + userPublicInfoVO.setRoleId((roleDO != null && roleDO.getRuuid() != null) ? roleDO.getRuuid() : ""); + + // 设置redis数据 + redisUtil.setHasKey(redisKey, Util.INSTANCE.objectToMap(userPublicInfoVO)); + + return userPublicInfoVO; + } - @Override - public void sendMailVerify(@NotNull final String email) { - // 检查邮箱是否已被注册 - SqlUserDO getUser = userDAO.getUserByEmail(email); - if (getUser == null) { - throw new BusinessException("邮箱未注册", ErrorCode.USER_NOT_EXIST); - } - // 检查邮箱是否已验证 - if (getUser.getMailVerify()) { - throw new BusinessException("邮箱已验证", ErrorCode.OPERATION_FAILED); - } - // 检查前一次所发送的验证码是否已过期或达到可重新发送的标准 - RedisMailCodeDO getMailCode = Util.INSTANCE.mapToObject( - redisUtil.hashGet("mail:code:" + email), - RedisMailCodeDO.class - ); - // 生成验证码 - String getNumberCode = Util.INSTANCE.generateNumber(6); - if (getMailCode != null) { - if (System.currentTimeMillis() - Long.parseLong(getMailCode.getSendAt()) < 60 * 1000) { - throw new BusinessException("发送过于频繁", ErrorCode.OPERATION_FAILED); - } - } - // 发送验证码 - mailService.sendVerifyCodeMail(email, getNumberCode, MailTemplateEnum.USER_REGISTER); - } } diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/services/interfaces/UserService.kt b/src/main/kotlin/com/frontleaves/fantasticeditor/services/interfaces/UserService.kt index 7cb18f5..60d8097 100644 --- a/src/main/kotlin/com/frontleaves/fantasticeditor/services/interfaces/UserService.kt +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/services/interfaces/UserService.kt @@ -17,6 +17,7 @@ package com.frontleaves.fantasticeditor.services.interfaces import com.frontleaves.fantasticeditor.models.dto.UserCurrentDTO import com.frontleaves.fantasticeditor.models.vo.api.auth.AuthUserLoginVO import com.frontleaves.fantasticeditor.models.vo.api.auth.AuthUserRegisterVO +import com.frontleaves.fantasticeditor.models.vo.api.user.UserPublicInfoVO /** * ## 用户服务接口 @@ -72,4 +73,12 @@ interface UserService { * @return 成功发送返回真,否则返回假 */ fun sendMailVerify(email: String) + + /** + * + * + * + * @return 用户公开信息实体类 + */ + fun getMyUserProfileInfo(uuid: String): UserPublicInfoVO } diff --git a/src/main/kotlin/com/frontleaves/fantasticeditor/utility/Util.kt b/src/main/kotlin/com/frontleaves/fantasticeditor/utility/Util.kt index 2c88014..a779145 100644 --- a/src/main/kotlin/com/frontleaves/fantasticeditor/utility/Util.kt +++ b/src/main/kotlin/com/frontleaves/fantasticeditor/utility/Util.kt @@ -17,6 +17,7 @@ package com.frontleaves.fantasticeditor.utility import com.frontleaves.fantasticeditor.exceptions.BusinessException import jakarta.servlet.http.HttpServletRequest import org.springframework.security.crypto.bcrypt.BCrypt +import java.lang.reflect.Field import java.util.* /** @@ -213,4 +214,53 @@ object Util { } return target.getDeclaredConstructor().newInstance() } + + /** + * 将属性从源对象复制到目标对象。 + * + * @param S 源对象的类型。 + * @param T 目标对象的类型。 + * @param source 从中复制属性的源对象。 + * @param target 属性将复制到的目标对象。 + */ + fun copyPropertiesData(source: S, target: T) { + val sourceClass: Class<*> = source.javaClass + val targetClass: Class<*> = target.javaClass + + try { + val sourceFields: Array = sourceClass.declaredFields + for (sourceField in sourceFields) { + val fieldName: String = sourceField.name + val targetField: Field + targetField = try { + targetClass.getDeclaredField(fieldName) + } catch (e: NoSuchFieldException) { + // 目标对象不存在该属性,忽略 + continue + } + + sourceField.isAccessible = true + targetField.isAccessible = true + + val value: Any? = sourceField.get(source) + + if (value == null) { + continue + } + + // 如果获取的值不为数字且等于“”,则跳过 + if ("" == value) { + continue + } + + if (sourceField.type != targetField.type) { + continue + } + + targetField.set(target, value) + } + } catch (e: NoSuchFieldException) { + // 忽略异常 + } + } }