refactor(auth):重构认证服务,分离用户逻辑到独立服务
- 将用户相关业务迁移至用户模块,通过OpenFeign远程调用。
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -42,6 +42,6 @@ build/
|
|||||||
/han-note-auth/src/main/resources/application-prod.yml
|
/han-note-auth/src/main/resources/application-prod.yml
|
||||||
/han-note-auth/logs/
|
/han-note-auth/logs/
|
||||||
/logs/
|
/logs/
|
||||||
/.idea/
|
|
||||||
/han-note-oss/han-note-oss-biz/src/main/resources/application-dev.yml
|
/han-note-oss/han-note-oss-biz/src/main/resources/application-dev.yml
|
||||||
/han-note-user/han-note-user-biz/src/main/resources/application-dev.yml
|
/han-note-user/han-note-user-biz/src/main/resources/application-dev.yml
|
||||||
|
/han-note-user/han-note-user-biz/logs/
|
||||||
|
|||||||
@@ -26,18 +26,6 @@
|
|||||||
<groupId>com.hanserwei</groupId>
|
<groupId>com.hanserwei</groupId>
|
||||||
<artifactId>hanserwei-spring-boot-starter-biz-operationlog</artifactId>
|
<artifactId>hanserwei-spring-boot-starter-biz-operationlog</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba</groupId>
|
|
||||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.hanserwei</groupId>
|
<groupId>com.hanserwei</groupId>
|
||||||
<artifactId>hanserwei-spring-boot-starter-jackson</artifactId>
|
<artifactId>hanserwei-spring-boot-starter-jackson</artifactId>
|
||||||
@@ -102,6 +90,10 @@
|
|||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-crypto</artifactId>
|
<artifactId>spring-security-crypto</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hanserwei</groupId>
|
||||||
|
<artifactId>han-note-user-api</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.hanserwei.hannote.auth;
|
package com.hanserwei.hannote.auth;
|
||||||
|
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@MapperScan("com.hanserwei.hannote.auth.domain.mapper")
|
@EnableFeignClients(basePackages = "com.hanserwei.hannote")
|
||||||
public class HanNoteAuthApplication {
|
public class HanNoteAuthApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
|
|||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.auth.model.vo.user.UpdatePasswordReqVO;
|
import com.hanserwei.hannote.auth.model.vo.user.UpdatePasswordReqVO;
|
||||||
import com.hanserwei.hannote.auth.model.vo.user.UserLoginReqVO;
|
import com.hanserwei.hannote.auth.model.vo.user.UserLoginReqVO;
|
||||||
import com.hanserwei.hannote.auth.service.UserService;
|
import com.hanserwei.hannote.auth.service.AuthService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -16,26 +16,26 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UserController {
|
public class AuthController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserService userService;
|
private AuthService authService;
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ApiOperationLog(description = "用户登录/注册")
|
@ApiOperationLog(description = "用户登录/注册")
|
||||||
public Response<String> loginAndRegister(@Validated @RequestBody UserLoginReqVO userLoginReqVO) {
|
public Response<String> loginAndRegister(@Validated @RequestBody UserLoginReqVO userLoginReqVO) {
|
||||||
return userService.loginAndRegister(userLoginReqVO);
|
return authService.loginAndRegister(userLoginReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
@ApiOperationLog(description = "账号登出")
|
@ApiOperationLog(description = "账号登出")
|
||||||
public Response<?> logout() {
|
public Response<?> logout() {
|
||||||
return userService.logout();
|
return authService.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/password/update")
|
@PostMapping("/password/update")
|
||||||
@ApiOperationLog(description = "修改密码")
|
@ApiOperationLog(description = "修改密码")
|
||||||
public Response<?> updatePassword(@Validated @RequestBody UpdatePasswordReqVO updatePasswordReqVO) {
|
public Response<?> updatePassword(@Validated @RequestBody UpdatePasswordReqVO updatePasswordReqVO) {
|
||||||
return userService.updatePassword(updatePasswordReqVO);
|
return authService.updatePassword(updatePasswordReqVO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.dataobject;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户表
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@TableName(value = "t_user")
|
|
||||||
public class UserDO {
|
|
||||||
/**
|
|
||||||
* 主键ID
|
|
||||||
*/
|
|
||||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小憨书号(唯一凭证)
|
|
||||||
*/
|
|
||||||
@TableField(value = "han_note_id")
|
|
||||||
private String hanNoteId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
@TableField(value = "`password`")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 昵称
|
|
||||||
*/
|
|
||||||
@TableField(value = "nickname")
|
|
||||||
private String nickname;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 头像
|
|
||||||
*/
|
|
||||||
@TableField(value = "avatar")
|
|
||||||
private String avatar;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生日
|
|
||||||
*/
|
|
||||||
@TableField(value = "birthday")
|
|
||||||
private LocalDate birthday;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 背景图
|
|
||||||
*/
|
|
||||||
@TableField(value = "background_img")
|
|
||||||
private String backgroundImg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 邮箱
|
|
||||||
*/
|
|
||||||
@TableField(value = "email")
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 性别(0:女 1:男)
|
|
||||||
*/
|
|
||||||
@TableField(value = "sex")
|
|
||||||
private Integer sex;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 状态(0:启用 1:禁用)
|
|
||||||
*/
|
|
||||||
@TableField(value = "`status`")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 个人简介
|
|
||||||
*/
|
|
||||||
@TableField(value = "introduction")
|
|
||||||
private String introduction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
@TableField(value = "create_time")
|
|
||||||
private LocalDateTime createTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新时间
|
|
||||||
*/
|
|
||||||
@TableField(value = "update_time")
|
|
||||||
private LocalDateTime updateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 逻辑删除(0:未删除 1:已删除)
|
|
||||||
*/
|
|
||||||
@TableField(value = "is_deleted")
|
|
||||||
private Boolean isDeleted;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.UserDO;
|
|
||||||
|
|
||||||
public interface UserDOMapper extends BaseMapper<UserDO> {
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,7 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
|
|||||||
LOGIN_TYPE_ERROR("AUTH-20002", "登录类型错误"),
|
LOGIN_TYPE_ERROR("AUTH-20002", "登录类型错误"),
|
||||||
USER_NOT_FOUND("AUTH-20003", "该用户不存在"),
|
USER_NOT_FOUND("AUTH-20003", "该用户不存在"),
|
||||||
MAIL_OR_PASSWORD_ERROR("AUTH-20004", "邮箱号或密码错误"),
|
MAIL_OR_PASSWORD_ERROR("AUTH-20004", "邮箱号或密码错误"),
|
||||||
|
LOGIN_FAIL("AUTH-20005", "登录失败"),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.hanserwei.hannote.auth.rpc;
|
||||||
|
|
||||||
|
import com.hanserwei.framework.common.response.Response;
|
||||||
|
import com.hanserwei.hannote.user.api.UserFeignApi;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserRpcService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserFeignApi userFeignApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注册
|
||||||
|
*
|
||||||
|
* @param email 邮箱
|
||||||
|
* @return 用户ID
|
||||||
|
*/
|
||||||
|
public Long registerUser(String email) {
|
||||||
|
RegisterUserReqDTO registerUserReqDTO = new RegisterUserReqDTO();
|
||||||
|
registerUserReqDTO.setEmail(email);
|
||||||
|
|
||||||
|
Response<Long> response = userFeignApi.registerUser(registerUserReqDTO);
|
||||||
|
|
||||||
|
if (!response.isSuccess()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据邮箱号查询用户信息
|
||||||
|
*
|
||||||
|
* @param email 邮箱
|
||||||
|
* @return 用户信息
|
||||||
|
*/
|
||||||
|
public FindUserByEmailRspDTO findUserByEmail(String email) {
|
||||||
|
FindUserByEmailReqDTO findUserByEmailReqDTO = new FindUserByEmailReqDTO();
|
||||||
|
findUserByEmailReqDTO.setEmail(email);
|
||||||
|
|
||||||
|
Response<FindUserByEmailRspDTO> response = userFeignApi.findByPhone(findUserByEmailReqDTO);
|
||||||
|
|
||||||
|
if (!response.isSuccess()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码更新
|
||||||
|
*
|
||||||
|
* @param encodePassword 加密后的密码
|
||||||
|
*/
|
||||||
|
public void updatePassword(String encodePassword) {
|
||||||
|
UpdateUserPasswordReqDTO updateUserPasswordReqDTO = new UpdateUserPasswordReqDTO();
|
||||||
|
updateUserPasswordReqDTO.setEncodePassword(encodePassword);
|
||||||
|
|
||||||
|
userFeignApi.updatePassword(updateUserPasswordReqDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
package com.hanserwei.hannote.auth.service;
|
package com.hanserwei.hannote.auth.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.UserDO;
|
|
||||||
import com.hanserwei.hannote.auth.model.vo.user.UpdatePasswordReqVO;
|
import com.hanserwei.hannote.auth.model.vo.user.UpdatePasswordReqVO;
|
||||||
import com.hanserwei.hannote.auth.model.vo.user.UserLoginReqVO;
|
import com.hanserwei.hannote.auth.model.vo.user.UserLoginReqVO;
|
||||||
|
|
||||||
public interface UserService extends IService<UserDO> {
|
public interface AuthService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录与注册
|
* 登录与注册
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.hanserwei.hannote.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
|
||||||
|
import com.hanserwei.framework.common.exception.ApiException;
|
||||||
|
import com.hanserwei.framework.common.response.Response;
|
||||||
|
import com.hanserwei.hannote.auth.constant.RedisKeyConstants;
|
||||||
|
import com.hanserwei.hannote.auth.enums.LoginTypeEnum;
|
||||||
|
import com.hanserwei.hannote.auth.enums.ResponseCodeEnum;
|
||||||
|
import com.hanserwei.hannote.auth.model.vo.user.UpdatePasswordReqVO;
|
||||||
|
import com.hanserwei.hannote.auth.model.vo.user.UserLoginReqVO;
|
||||||
|
import com.hanserwei.hannote.auth.rpc.UserRpcService;
|
||||||
|
import com.hanserwei.hannote.auth.service.AuthService;
|
||||||
|
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthServiceImpl implements AuthService {
|
||||||
|
|
||||||
|
|
||||||
|
private final RedisTemplate<String, Object> redisTemplate;
|
||||||
|
private final UserRpcService userRpcService;
|
||||||
|
@Resource(name = "authTaskExecutor")
|
||||||
|
private ThreadPoolTaskExecutor authTaskExecutor;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<String> loginAndRegister(UserLoginReqVO reqVO) {
|
||||||
|
Integer loginType = reqVO.getType();
|
||||||
|
String email = reqVO.getEmail();
|
||||||
|
LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(loginType);
|
||||||
|
|
||||||
|
Long userId = null;
|
||||||
|
|
||||||
|
//noinspection DataFlowIssue
|
||||||
|
switch (loginTypeEnum) {
|
||||||
|
case VERIFICATION_CODE:
|
||||||
|
String verificationCode = reqVO.getCode();
|
||||||
|
//校验参数是否为空
|
||||||
|
Preconditions.checkArgument(StringUtils.isNotBlank(verificationCode), "验证码不能为空");
|
||||||
|
|
||||||
|
//构建验证码的RedisKey
|
||||||
|
String key = RedisKeyConstants.buildVerificationCodeKey(email);
|
||||||
|
// 查询存储在 Redis 中该用户的登录验证码
|
||||||
|
String sentCode = (String) redisTemplate.opsForValue().get(key);
|
||||||
|
// 判断用户提交的验证码,与 Redis 中的验证码是否一致
|
||||||
|
if (!StrUtil.equals(verificationCode, sentCode)) {
|
||||||
|
throw new ApiException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
|
||||||
|
}
|
||||||
|
// RPC: 调用用户服务,注册用户
|
||||||
|
Long userIdTmp = userRpcService.registerUser(email);
|
||||||
|
|
||||||
|
// 若调用用户服务,返回的用户 ID 为空,则提示登录失败
|
||||||
|
if (Objects.isNull(userIdTmp)) {
|
||||||
|
throw new ApiException(ResponseCodeEnum.LOGIN_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
userId = userIdTmp;
|
||||||
|
break;
|
||||||
|
case PASSWORD:
|
||||||
|
String password = reqVO.getPassword();
|
||||||
|
|
||||||
|
// RPC: 调用用户服务,通过手机号查询用户
|
||||||
|
FindUserByEmailRspDTO findUserByEmailRspDTO = userRpcService.findUserByEmail(email);
|
||||||
|
|
||||||
|
// 判断该手机号是否注册
|
||||||
|
if (Objects.isNull(findUserByEmailRspDTO)) {
|
||||||
|
throw new ApiException(ResponseCodeEnum.USER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拿到密文密码
|
||||||
|
String encodePassword = findUserByEmailRspDTO.getPassword();
|
||||||
|
|
||||||
|
// 匹配密码是否一致
|
||||||
|
boolean isPasswordCorrect = passwordEncoder.matches(password, encodePassword);
|
||||||
|
|
||||||
|
// 如果不正确,则抛出业务异常,提示用户名或者密码不正确
|
||||||
|
if (!isPasswordCorrect) {
|
||||||
|
throw new ApiException(ResponseCodeEnum.MAIL_OR_PASSWORD_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
userId = findUserByEmailRspDTO.getId();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// SaToken 登录用户,并返回 token 令牌
|
||||||
|
StpUtil.login(userId);
|
||||||
|
|
||||||
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||||
|
|
||||||
|
return Response.success(tokenInfo.getTokenValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<?> logout() {
|
||||||
|
Long userId = LoginUserContextHolder.getUserId();
|
||||||
|
authTaskExecutor.submit(() -> {
|
||||||
|
Long userId2 = LoginUserContextHolder.getUserId();
|
||||||
|
log.info("==> 异步线程中获取 userId: {}", userId2);
|
||||||
|
});
|
||||||
|
StpUtil.logout(userId);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<?> updatePassword(UpdatePasswordReqVO updatePasswordReqVO) {
|
||||||
|
// 新密码
|
||||||
|
String newPassword = updatePasswordReqVO.getNewPassword();
|
||||||
|
// 加密后的密码
|
||||||
|
String encodePassword = passwordEncoder.encode(newPassword);
|
||||||
|
// RPC: 调用用户服务:更新密码
|
||||||
|
userRpcService.updatePassword(encodePassword);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth.service.impl;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
|
|
||||||
import com.hanserwei.framework.common.enums.DeletedEnum;
|
|
||||||
import com.hanserwei.framework.common.enums.StatusEnum;
|
|
||||||
import com.hanserwei.framework.common.exception.ApiException;
|
|
||||||
import com.hanserwei.framework.common.response.Response;
|
|
||||||
import com.hanserwei.framework.common.utils.JsonUtils;
|
|
||||||
import com.hanserwei.hannote.auth.constant.RedisKeyConstants;
|
|
||||||
import com.hanserwei.hannote.auth.constant.RoleConstants;
|
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.RoleDO;
|
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.UserDO;
|
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.UserRoleDO;
|
|
||||||
import com.hanserwei.hannote.auth.domain.mapper.RoleDOMapper;
|
|
||||||
import com.hanserwei.hannote.auth.domain.mapper.UserDOMapper;
|
|
||||||
import com.hanserwei.hannote.auth.domain.mapper.UserRoleDOMapper;
|
|
||||||
import com.hanserwei.hannote.auth.enums.LoginTypeEnum;
|
|
||||||
import com.hanserwei.hannote.auth.enums.ResponseCodeEnum;
|
|
||||||
import com.hanserwei.hannote.auth.model.vo.user.UpdatePasswordReqVO;
|
|
||||||
import com.hanserwei.hannote.auth.model.vo.user.UserLoginReqVO;
|
|
||||||
import com.hanserwei.hannote.auth.service.UserService;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implements UserService {
|
|
||||||
|
|
||||||
|
|
||||||
private final RedisTemplate<String, Object> redisTemplate;
|
|
||||||
private final UserRoleDOMapper userRoleDOMapper;
|
|
||||||
private final TransactionTemplate transactionTemplate;
|
|
||||||
private final RoleDOMapper roleDOMapper;
|
|
||||||
@Resource(name = "authTaskExecutor")
|
|
||||||
private ThreadPoolTaskExecutor authTaskExecutor;
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response<String> loginAndRegister(UserLoginReqVO reqVO) {
|
|
||||||
Integer loginType = reqVO.getType();
|
|
||||||
String email = reqVO.getEmail();
|
|
||||||
LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(loginType);
|
|
||||||
|
|
||||||
Long userId = null;
|
|
||||||
|
|
||||||
//noinspection DataFlowIssue
|
|
||||||
switch (loginTypeEnum) {
|
|
||||||
case VERIFICATION_CODE:
|
|
||||||
String verificationCode = reqVO.getCode();
|
|
||||||
//校验参数是否为空
|
|
||||||
Preconditions.checkArgument(StringUtils.isNotBlank(verificationCode), "验证码不能为空");
|
|
||||||
|
|
||||||
//构建验证码的RedisKey
|
|
||||||
String key = RedisKeyConstants.buildVerificationCodeKey(email);
|
|
||||||
// 查询存储在 Redis 中该用户的登录验证码
|
|
||||||
String sentCode = (String) redisTemplate.opsForValue().get(key);
|
|
||||||
// 判断用户提交的验证码,与 Redis 中的验证码是否一致
|
|
||||||
if (!StrUtil.equals(verificationCode, sentCode)) {
|
|
||||||
throw new ApiException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
|
|
||||||
}
|
|
||||||
//通过邮箱查询用户
|
|
||||||
UserDO userDO = this.getOne(new QueryWrapper<UserDO>().eq("email", email));
|
|
||||||
log.info("==> 用户是否注册, email: {}, userDO: {}", email, JsonUtils.toJsonString(userDO));
|
|
||||||
// 判断是否注册
|
|
||||||
if (Objects.isNull(userDO)) {
|
|
||||||
// 若此用户还没有注册,系统自动注册该用户
|
|
||||||
userId = registerUser(email);
|
|
||||||
} else {
|
|
||||||
// 已注册,则获取其用户 ID
|
|
||||||
userId = userDO.getId();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PASSWORD:
|
|
||||||
String password = reqVO.getPassword();
|
|
||||||
// 根据邮箱号查询
|
|
||||||
UserDO userDO1 = this.getOne(new QueryWrapper<UserDO>().eq("email", email));
|
|
||||||
if (Objects.isNull(userDO1)){
|
|
||||||
throw new ApiException(ResponseCodeEnum.USER_NOT_FOUND);
|
|
||||||
}
|
|
||||||
// 拿到密文密码
|
|
||||||
String encodePassword = userDO1.getPassword();
|
|
||||||
boolean isPasswordCorrect = passwordEncoder.matches(password, encodePassword);
|
|
||||||
if (!isPasswordCorrect) {
|
|
||||||
throw new ApiException(ResponseCodeEnum.MAIL_OR_PASSWORD_ERROR);
|
|
||||||
}
|
|
||||||
userId = userDO1.getId();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// SaToken 登录用户,并返回 token 令牌
|
|
||||||
StpUtil.login(userId);
|
|
||||||
|
|
||||||
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
|
||||||
|
|
||||||
return Response.success(tokenInfo.getTokenValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long registerUser(String email) {
|
|
||||||
return transactionTemplate.execute(status -> {
|
|
||||||
try {
|
|
||||||
// 获取全局自增的小憨书ID
|
|
||||||
Long hanNoteId = redisTemplate.opsForValue().increment(RedisKeyConstants.HAN_NOTE_ID_GENERATOR_KEY);
|
|
||||||
UserDO userDO = UserDO.builder()
|
|
||||||
.hanNoteId(String.valueOf(hanNoteId)) // 自动生成小红书号 ID
|
|
||||||
.nickname("小憨憨" + hanNoteId) // 自动生成昵称, 如:小憨憨10000
|
|
||||||
.status(StatusEnum.ENABLE.getValue()) // 状态为启用
|
|
||||||
.email(email)
|
|
||||||
.createTime(LocalDateTime.now())
|
|
||||||
.updateTime(LocalDateTime.now())
|
|
||||||
.isDeleted(DeletedEnum.NO.getValue()) // 逻辑删除
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// 添加入库
|
|
||||||
this.save(userDO);
|
|
||||||
|
|
||||||
// 获取入库的用户ID
|
|
||||||
Long userId = userDO.getId();
|
|
||||||
|
|
||||||
// 添加默认用户角色
|
|
||||||
UserRoleDO userRoleDO = UserRoleDO.builder()
|
|
||||||
.userId(userId)
|
|
||||||
.roleId(RoleConstants.COMMON_USER_ROLE_ID)
|
|
||||||
.createTime(LocalDateTime.now())
|
|
||||||
.updateTime(LocalDateTime.now())
|
|
||||||
.isDeleted(DeletedEnum.NO.getValue())
|
|
||||||
.build();
|
|
||||||
userRoleDOMapper.insert(userRoleDO);
|
|
||||||
|
|
||||||
RoleDO roleDO = roleDOMapper.selectByPrimaryKey(RoleConstants.COMMON_USER_ROLE_ID);
|
|
||||||
|
|
||||||
// 将该用户的角色 ID 存入 Redis 中,指定初始容量为 1,这样可以减少在扩容时的性能开销
|
|
||||||
List<String> roles = new ArrayList<>(1);
|
|
||||||
roles.add(roleDO.getRoleKey());
|
|
||||||
|
|
||||||
String userRolesKey = RedisKeyConstants.buildUserRoleKey(userId);
|
|
||||||
redisTemplate.opsForValue().set(userRolesKey, JsonUtils.toJsonString(roles));
|
|
||||||
|
|
||||||
return userId;
|
|
||||||
} catch (Exception e) {
|
|
||||||
status.setRollbackOnly(); // 标记事务为回滚
|
|
||||||
log.error("==> 系统注册用户异常: ", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response<?> logout() {
|
|
||||||
Long userId = LoginUserContextHolder.getUserId();
|
|
||||||
authTaskExecutor.submit(() -> {
|
|
||||||
Long userId2 = LoginUserContextHolder.getUserId();
|
|
||||||
log.info("==> 异步线程中获取 userId: {}", userId2);
|
|
||||||
});
|
|
||||||
StpUtil.logout(userId);
|
|
||||||
return Response.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response<?> updatePassword(UpdatePasswordReqVO updatePasswordReqVO) {
|
|
||||||
// 新密码
|
|
||||||
String newPassword = updatePasswordReqVO.getNewPassword();
|
|
||||||
// 加密后的密码
|
|
||||||
String encodePassword = passwordEncoder.encode(newPassword);
|
|
||||||
// 获取用户ID
|
|
||||||
Long userId = LoginUserContextHolder.getUserId();
|
|
||||||
|
|
||||||
UserDO userDO = UserDO.builder()
|
|
||||||
.id(userId)
|
|
||||||
.password(encodePassword)
|
|
||||||
.updateTime(LocalDateTime.now())
|
|
||||||
.build();
|
|
||||||
// 更新用户密码
|
|
||||||
this.updateById(userDO);
|
|
||||||
return Response.success();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,13 +34,6 @@ spring:
|
|||||||
mail.smtp.starttls.required: true
|
mail.smtp.starttls.required: true
|
||||||
server:
|
server:
|
||||||
port: 8080 # 项目启动的端口
|
port: 8080 # 项目启动的端口
|
||||||
mybatis-plus:
|
|
||||||
configuration:
|
|
||||||
map-underscore-to-camel-case: true
|
|
||||||
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
|
||||||
global-config:
|
|
||||||
banner: false
|
|
||||||
mapper-locations: classpath*:/mapperxml/*.xml
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
com.hanserwei.hannote.auth.domain.mapper: debug
|
com.hanserwei.hannote.auth.domain.mapper: debug
|
||||||
@@ -62,5 +55,3 @@ sa-token:
|
|||||||
token-style: random-128
|
token-style: random-128
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
alarm:
|
|
||||||
type: mail # 告警类型
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="com.hanserwei.hannote.auth.domain.mapper.UserDOMapper">
|
|
||||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.auth.domain.dataobject.UserDO">
|
|
||||||
<!--@mbg.generated-->
|
|
||||||
<!--@Table t_user-->
|
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
|
||||||
<result column="han_note_id" jdbcType="VARCHAR" property="hanNoteId" />
|
|
||||||
<result column="password" jdbcType="VARCHAR" property="password" />
|
|
||||||
<result column="nickname" jdbcType="VARCHAR" property="nickname" />
|
|
||||||
<result column="avatar" jdbcType="VARCHAR" property="avatar" />
|
|
||||||
<result column="birthday" jdbcType="DATE" property="birthday" />
|
|
||||||
<result column="background_img" jdbcType="VARCHAR" property="backgroundImg" />
|
|
||||||
<result column="email" jdbcType="VARCHAR" property="email" />
|
|
||||||
<result column="sex" jdbcType="TINYINT" property="sex" />
|
|
||||||
<result column="status" jdbcType="TINYINT" property="status" />
|
|
||||||
<result column="introduction" jdbcType="VARCHAR" property="introduction" />
|
|
||||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
|
|
||||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
|
|
||||||
<result column="is_deleted" jdbcType="BIT" property="isDeleted" />
|
|
||||||
</resultMap>
|
|
||||||
<sql id="Base_Column_List">
|
|
||||||
<!--@mbg.generated-->
|
|
||||||
id, han_note_id, `password`, nickname, avatar, birthday, background_img, email, sex,
|
|
||||||
`status`, introduction, create_time, update_time, is_deleted
|
|
||||||
</sql>
|
|
||||||
</mapper>
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth;
|
|
||||||
|
|
||||||
import com.alibaba.druid.filter.config.ConfigTools;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@Slf4j
|
|
||||||
class DruidTests {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Druid 密码加密
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@SneakyThrows
|
|
||||||
void testEncodePassword() {
|
|
||||||
// 你的密码
|
|
||||||
String password = "mysql";
|
|
||||||
String[] arr = ConfigTools.genKeyPair(512);
|
|
||||||
|
|
||||||
// 私钥
|
|
||||||
log.info("privateKey: {}", arr[0]);
|
|
||||||
// 公钥
|
|
||||||
log.info("publicKey: {}", arr[1]);
|
|
||||||
|
|
||||||
// 通过私钥加密密码
|
|
||||||
String encodePassword = ConfigTools.encrypt(arr[0], password);
|
|
||||||
log.info("password: {}", encodePassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@Slf4j
|
|
||||||
class HanNoteAuthApplicationTests {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@Slf4j
|
|
||||||
class RedisTests {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set key value
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testSetKeyValue() {
|
|
||||||
// 添加一个 key 为 name, value 值为 Hanserwei
|
|
||||||
redisTemplate.opsForValue().set("name", "Hanserwei");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断某个 key 是否存在
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testHasKey() {
|
|
||||||
log.info("key 是否存在:{}", redisTemplate.hasKey("name"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取某个 key 的 value
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testGetValue() {
|
|
||||||
log.info("value 值:{}", redisTemplate.opsForValue().get("name"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除某个 key
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testDelete() {
|
|
||||||
redisTemplate.delete("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.hanserwei.hannote.auth;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
@Slf4j
|
|
||||||
public class ThreadPoolTaskExecutorTests {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试线程池
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testSubmit() {
|
|
||||||
threadPoolTaskExecutor.submit(() -> log.info("异步线程中说: Hanserwei是傻逼"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,6 +20,18 @@
|
|||||||
<groupId>com.hanserwei</groupId>
|
<groupId>com.hanserwei</groupId>
|
||||||
<artifactId>hanserwei-common</artifactId>
|
<artifactId>hanserwei-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- OpenFeign -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 负载均衡 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.hanserwei.hannote.user.api;
|
||||||
|
|
||||||
|
import com.hanserwei.framework.common.response.Response;
|
||||||
|
import com.hanserwei.hannote.user.constant.ApiConstants;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
@FeignClient(name = ApiConstants.SERVICE_NAME)
|
||||||
|
public interface UserFeignApi {
|
||||||
|
|
||||||
|
String PREFIX = "/user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注册
|
||||||
|
*
|
||||||
|
* @param registerUserReqDTO 注册信息
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
@PostMapping(value = PREFIX + "/register")
|
||||||
|
Response<Long> registerUser(@RequestBody RegisterUserReqDTO registerUserReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机号查询用户信息
|
||||||
|
*
|
||||||
|
* @param findUserByEmailReqDTO 查询信息请求
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
@PostMapping(value = PREFIX + "/findByEmail")
|
||||||
|
Response<FindUserByEmailRspDTO> findByPhone(@RequestBody FindUserByEmailReqDTO findUserByEmailReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新密码
|
||||||
|
*
|
||||||
|
* @param updateUserPasswordReqDTO 修改密码请求
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
@PostMapping(value = PREFIX + "/password/update")
|
||||||
|
Response<?> updatePassword(@RequestBody UpdateUserPasswordReqDTO updateUserPasswordReqDTO);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.hanserwei.hannote.user.constant;
|
||||||
|
|
||||||
|
public interface ApiConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
String SERVICE_NAME = "han-note-user";
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.hanserwei.hannote.user.dto.req;
|
||||||
|
|
||||||
|
import com.hanserwei.framework.common.validate.EmailNumber;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindUserByEmailReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱号
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "邮箱号不能为空")
|
||||||
|
@EmailNumber
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.hanserwei.hannote.user.dto.req;
|
||||||
|
|
||||||
|
import com.hanserwei.framework.common.validate.EmailNumber;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class RegisterUserReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "邮箱号不能为空")
|
||||||
|
@EmailNumber
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hanserwei.hannote.user.dto.req;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class UpdateUserPasswordReqDTO {
|
||||||
|
|
||||||
|
@NotBlank(message = "密码不能为空")
|
||||||
|
private String encodePassword;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hanserwei.hannote.user.dto.resp;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindUserByEmailRspDTO {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -70,6 +70,20 @@
|
|||||||
<groupId>com.hanserwei</groupId>
|
<groupId>com.hanserwei</groupId>
|
||||||
<artifactId>han-note-oss-api</artifactId>
|
<artifactId>han-note-oss-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- Redis 连接池 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-pool2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hanserwei</groupId>
|
||||||
|
<artifactId>han-note-user-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.hanserwei.hannote.user.biz.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisTemplateConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||||
|
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||||
|
// 设置 RedisTemplate 的连接工厂
|
||||||
|
redisTemplate.setConnectionFactory(connectionFactory);
|
||||||
|
|
||||||
|
// 使用 StringRedisSerializer 来序列化和反序列化 redis 的 key 值,确保 key 是可读的字符串
|
||||||
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
|
||||||
|
// 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value 值, 确保存储的是 JSON 格式
|
||||||
|
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||||
|
redisTemplate.setValueSerializer(serializer);
|
||||||
|
redisTemplate.setHashValueSerializer(serializer);
|
||||||
|
|
||||||
|
redisTemplate.afterPropertiesSet();
|
||||||
|
return redisTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.hanserwei.hannote.user.biz.constant;
|
||||||
|
|
||||||
|
public class RedisKeyConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小憨书全局 ID 生成器 KEY
|
||||||
|
*/
|
||||||
|
public static final String HAN_NOTE_ID_GENERATOR_KEY = "hannote.id.generator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户角色数据 KEY 前缀
|
||||||
|
*/
|
||||||
|
private static final String USER_ROLES_KEY_PREFIX = "user:roles:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色对应的权限集合 KEY 前缀
|
||||||
|
*/
|
||||||
|
private static final String ROLE_PERMISSIONS_KEY_PREFIX = "role:permissions:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建用户-角色 Key
|
||||||
|
*
|
||||||
|
* @param userId 邮箱
|
||||||
|
* @return 用户角色key
|
||||||
|
*/
|
||||||
|
public static String buildUserRoleKey(Long userId) {
|
||||||
|
return USER_ROLES_KEY_PREFIX + userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建角色对应的权限集合 KEY
|
||||||
|
*
|
||||||
|
* @param roleKey 角色ID
|
||||||
|
* @return 角色权限集合key
|
||||||
|
*/
|
||||||
|
public static String buildRolePermissionsKey(String roleKey) {
|
||||||
|
return ROLE_PERMISSIONS_KEY_PREFIX + roleKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.hanserwei.hannote.user.biz.constant;
|
||||||
|
|
||||||
|
public class RoleConstants {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通用户的角色 ID
|
||||||
|
*/
|
||||||
|
public static final Long COMMON_USER_ROLE_ID = 1L;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +1,19 @@
|
|||||||
package com.hanserwei.hannote.user.biz.controller;
|
package com.hanserwei.hannote.user.biz.controller;
|
||||||
|
|
||||||
|
import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
||||||
import com.hanserwei.hannote.user.biz.service.UserService;
|
import com.hanserwei.hannote.user.biz.service.UserService;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@@ -30,4 +36,23 @@ public class UserController {
|
|||||||
return userService.updateUserInfo(updateUserInfoReqVO);
|
return userService.updateUserInfo(updateUserInfoReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================================== 对其他服务提供的接口 =====================================
|
||||||
|
@PostMapping("/register")
|
||||||
|
@ApiOperationLog(description = "用户注册")
|
||||||
|
public Response<Long> register(@Validated @RequestBody RegisterUserReqDTO registerUserReqDTO) {
|
||||||
|
return userService.register(registerUserReqDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/findByEmail")
|
||||||
|
@ApiOperationLog(description = "邮箱号查询用户信息")
|
||||||
|
public Response<FindUserByEmailRspDTO> findByPhone(@Validated @RequestBody FindUserByEmailReqDTO findUserByEmailReqDTO) {
|
||||||
|
return userService.findByEmail(findUserByEmailReqDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/password/update")
|
||||||
|
@ApiOperationLog(description = "密码更新")
|
||||||
|
public Response<?> updatePassword(@Validated @RequestBody UpdateUserPasswordReqDTO updateUserPasswordReqDTO) {
|
||||||
|
return userService.updatePassword(updateUserPasswordReqDTO);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.dataobject;
|
package com.hanserwei.hannote.user.biz.domain.dataobject;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import java.util.Date;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限表
|
* 权限表
|
||||||
*/
|
*/
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.dataobject;
|
package com.hanserwei.hannote.user.biz.domain.dataobject;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import java.util.Date;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色表
|
* 角色表
|
||||||
*/
|
*/
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.dataobject;
|
package com.hanserwei.hannote.user.biz.domain.dataobject;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import java.util.Date;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户权限表
|
* 用户权限表
|
||||||
*/
|
*/
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.dataobject;
|
package com.hanserwei.hannote.user.biz.domain.dataobject;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.mapper;
|
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.PermissionDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.PermissionDO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.mapper;
|
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.RoleDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.mapper;
|
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.RolePermissionDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.RolePermissionDO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.hanserwei.hannote.auth.domain.mapper;
|
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.UserRoleDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.UserRoleDO;
|
||||||
|
|
||||||
public interface UserRoleDOMapper extends BaseMapper<UserRoleDO> {
|
public interface UserRoleDOMapper extends BaseMapper<UserRoleDO> {
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
|
|||||||
INTRODUCTION_VALID_FAIL("USER-20004", "个人简介请设置1-100个字符"),
|
INTRODUCTION_VALID_FAIL("USER-20004", "个人简介请设置1-100个字符"),
|
||||||
UPLOAD_AVATAR_FAIL("USER-20005", "头像上传失败"),
|
UPLOAD_AVATAR_FAIL("USER-20005", "头像上传失败"),
|
||||||
UPLOAD_BACKGROUND_IMG_FAIL("USER-20006", "背景图上传失败"),
|
UPLOAD_BACKGROUND_IMG_FAIL("USER-20006", "背景图上传失败"),
|
||||||
|
USER_NOT_FOUND("USER-20007", "该用户不存在"),
|
||||||
;
|
;
|
||||||
|
|
||||||
// 异常码
|
// 异常码
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package com.hanserwei.hannote.auth.runner;
|
package com.hanserwei.hannote.user.biz.runner;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.hanserwei.framework.common.utils.JsonUtils;
|
import com.hanserwei.framework.common.utils.JsonUtils;
|
||||||
import com.hanserwei.hannote.auth.constant.RedisKeyConstants;
|
import com.hanserwei.hannote.user.biz.constant.RedisKeyConstants;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.PermissionDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.PermissionDO;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.RoleDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO;
|
||||||
import com.hanserwei.hannote.auth.domain.dataobject.RolePermissionDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.RolePermissionDO;
|
||||||
import com.hanserwei.hannote.auth.domain.mapper.PermissionDOMapper;
|
import com.hanserwei.hannote.user.biz.domain.mapper.PermissionDOMapper;
|
||||||
import com.hanserwei.hannote.auth.domain.mapper.RoleDOMapper;
|
import com.hanserwei.hannote.user.biz.domain.mapper.RoleDOMapper;
|
||||||
import com.hanserwei.hannote.auth.domain.mapper.RolePermissionDOMapper;
|
import com.hanserwei.hannote.user.biz.domain.mapper.RolePermissionDOMapper;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
@@ -4,6 +4,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
|
||||||
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
|
||||||
|
|
||||||
public interface UserService extends IService<UserDO> {
|
public interface UserService extends IService<UserDO> {
|
||||||
|
|
||||||
@@ -14,4 +18,28 @@ public interface UserService extends IService<UserDO> {
|
|||||||
* @return 响应结果
|
* @return 响应结果
|
||||||
*/
|
*/
|
||||||
Response<?> updateUserInfo(UpdateUserInfoReqVO updateUserInfoReqVO);
|
Response<?> updateUserInfo(UpdateUserInfoReqVO updateUserInfoReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注册
|
||||||
|
*
|
||||||
|
* @param registerUserReqDTO 注册用户请求参数
|
||||||
|
* @return 响应结果
|
||||||
|
*/
|
||||||
|
Response<Long> register(RegisterUserReqDTO registerUserReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据邮箱号查询用户信息
|
||||||
|
*
|
||||||
|
* @param findUserByEmailReqDTO 查询用户信息请求参数
|
||||||
|
* @return 响应结果
|
||||||
|
*/
|
||||||
|
Response<FindUserByEmailRspDTO> findByEmail(FindUserByEmailReqDTO findUserByEmailReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新密码
|
||||||
|
*
|
||||||
|
* @param updateUserPasswordReqDTO 更新密码请求参数
|
||||||
|
* @return 响应结果
|
||||||
|
*/
|
||||||
|
Response<?> updatePassword(UpdateUserPasswordReqDTO updateUserPasswordReqDTO);
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,44 @@
|
|||||||
package com.hanserwei.hannote.user.biz.service.impl;
|
package com.hanserwei.hannote.user.biz.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
|
import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
|
||||||
|
import com.hanserwei.framework.common.enums.DeletedEnum;
|
||||||
|
import com.hanserwei.framework.common.enums.StatusEnum;
|
||||||
import com.hanserwei.framework.common.exception.ApiException;
|
import com.hanserwei.framework.common.exception.ApiException;
|
||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
|
import com.hanserwei.framework.common.utils.JsonUtils;
|
||||||
import com.hanserwei.framework.common.utils.ParamUtils;
|
import com.hanserwei.framework.common.utils.ParamUtils;
|
||||||
|
import com.hanserwei.hannote.user.biz.constant.RedisKeyConstants;
|
||||||
|
import com.hanserwei.hannote.user.biz.constant.RoleConstants;
|
||||||
|
import com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO;
|
||||||
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
|
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
|
||||||
|
import com.hanserwei.hannote.user.biz.domain.dataobject.UserRoleDO;
|
||||||
|
import com.hanserwei.hannote.user.biz.domain.mapper.RoleDOMapper;
|
||||||
import com.hanserwei.hannote.user.biz.domain.mapper.UserDOMapper;
|
import com.hanserwei.hannote.user.biz.domain.mapper.UserDOMapper;
|
||||||
|
import com.hanserwei.hannote.user.biz.domain.mapper.UserRoleDOMapper;
|
||||||
import com.hanserwei.hannote.user.biz.enums.ResponseCodeEnum;
|
import com.hanserwei.hannote.user.biz.enums.ResponseCodeEnum;
|
||||||
import com.hanserwei.hannote.user.biz.enums.SexEnum;
|
import com.hanserwei.hannote.user.biz.enums.SexEnum;
|
||||||
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
||||||
import com.hanserwei.hannote.user.biz.rpc.OssRpcService;
|
import com.hanserwei.hannote.user.biz.rpc.OssRpcService;
|
||||||
import com.hanserwei.hannote.user.biz.service.UserService;
|
import com.hanserwei.hannote.user.biz.service.UserService;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
|
||||||
|
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -29,6 +47,12 @@ public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implement
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private OssRpcService ossRpcService;
|
private OssRpcService ossRpcService;
|
||||||
|
@Resource
|
||||||
|
private UserRoleDOMapper userRoleDOMapper;
|
||||||
|
@Resource
|
||||||
|
private RoleDOMapper roleDOMapper;
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response<?> updateUserInfo(UpdateUserInfoReqVO updateUserInfoReqVO) {
|
public Response<?> updateUserInfo(UpdateUserInfoReqVO updateUserInfoReqVO) {
|
||||||
@@ -114,4 +138,92 @@ public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implement
|
|||||||
}
|
}
|
||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Response<Long> register(RegisterUserReqDTO registerUserReqDTO) {
|
||||||
|
String email = registerUserReqDTO.getEmail();
|
||||||
|
|
||||||
|
// 先判断该手机号是否已被注册
|
||||||
|
UserDO userDO1 = this.getOne(new QueryWrapper<UserDO>().eq("email", email));
|
||||||
|
|
||||||
|
log.info("==> 用户是否注册, email: {}, userDO: {}", email, JsonUtils.toJsonString(userDO1));
|
||||||
|
|
||||||
|
// 若已注册,则直接返回用户 ID
|
||||||
|
if (Objects.nonNull(userDO1)) {
|
||||||
|
return Response.success(userDO1.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则注册新用户
|
||||||
|
// 获取全局自增的小憨书 ID
|
||||||
|
Long hanNoteId = redisTemplate.opsForValue().increment(RedisKeyConstants.HAN_NOTE_ID_GENERATOR_KEY);
|
||||||
|
|
||||||
|
UserDO userDO = UserDO.builder()
|
||||||
|
.email(email)
|
||||||
|
.hanNoteId(String.valueOf(hanNoteId)) // 自动生成小憨书号 ID
|
||||||
|
.nickname("小憨憨" + hanNoteId) // 自动生成昵称, 如:小憨憨10000
|
||||||
|
.status(StatusEnum.ENABLE.getValue()) // 状态为启用
|
||||||
|
.createTime(LocalDateTime.now())
|
||||||
|
.updateTime(LocalDateTime.now())
|
||||||
|
.isDeleted(DeletedEnum.NO.getValue()) // 逻辑删除
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 添加入库
|
||||||
|
this.save(userDO);
|
||||||
|
|
||||||
|
// 获取刚刚添加入库的用户 ID
|
||||||
|
Long userId = userDO.getId();
|
||||||
|
|
||||||
|
// 给该用户分配一个默认角色
|
||||||
|
UserRoleDO userRoleDO = UserRoleDO.builder()
|
||||||
|
.userId(userId)
|
||||||
|
.roleId(RoleConstants.COMMON_USER_ROLE_ID)
|
||||||
|
.createTime(LocalDateTime.now())
|
||||||
|
.updateTime(LocalDateTime.now())
|
||||||
|
.isDeleted(DeletedEnum.NO.getValue())
|
||||||
|
.build();
|
||||||
|
userRoleDOMapper.insert(userRoleDO);
|
||||||
|
|
||||||
|
RoleDO roleDO = roleDOMapper.selectByPrimaryKey(RoleConstants.COMMON_USER_ROLE_ID);
|
||||||
|
|
||||||
|
// 将该用户的角色 ID 存入 Redis 中
|
||||||
|
List<String> roles = new ArrayList<>(1);
|
||||||
|
roles.add(roleDO.getRoleKey());
|
||||||
|
|
||||||
|
String userRolesKey = RedisKeyConstants.buildUserRoleKey(userId);
|
||||||
|
redisTemplate.opsForValue().set(userRolesKey, JsonUtils.toJsonString(roles));
|
||||||
|
|
||||||
|
return Response.success(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<FindUserByEmailRspDTO> findByEmail(FindUserByEmailReqDTO findUserByEmailReqDTO) {
|
||||||
|
String email = findUserByEmailReqDTO.getEmail();
|
||||||
|
UserDO userDO = this.getOne(new QueryWrapper<UserDO>().eq("email", email));
|
||||||
|
if (Objects.isNull(userDO)){
|
||||||
|
throw new ApiException(ResponseCodeEnum.USER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
// 构建返参
|
||||||
|
FindUserByEmailRspDTO findUserByEmailRspDTO = FindUserByEmailRspDTO.builder()
|
||||||
|
.id(userDO.getId())
|
||||||
|
.password(userDO.getPassword())
|
||||||
|
.build();
|
||||||
|
return Response.success(findUserByEmailRspDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<?> updatePassword(UpdateUserPasswordReqDTO updateUserPasswordReqDTO) {
|
||||||
|
// 获取当前请求对应的用户 ID
|
||||||
|
Long userId = LoginUserContextHolder.getUserId();
|
||||||
|
|
||||||
|
UserDO userDO = UserDO.builder()
|
||||||
|
.id(userId)
|
||||||
|
.password(updateUserPasswordReqDTO.getEncodePassword()) // 加密后的密码
|
||||||
|
.updateTime(LocalDateTime.now())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 更新用户密码
|
||||||
|
return updateById(userDO) ? Response.success() : Response.fail();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,20 @@ spring:
|
|||||||
multipart:
|
multipart:
|
||||||
max-file-size: 20MB # 单个文件最大大小
|
max-file-size: 20MB # 单个文件最大大小
|
||||||
max-request-size: 100MB # 单次请求最大大小(包含多个文件)
|
max-request-size: 100MB # 单次请求最大大小(包含多个文件)
|
||||||
|
data:
|
||||||
|
redis:
|
||||||
|
database: 5 # Redis 数据库索引(默认为 0)
|
||||||
|
host: 127.0.0.1 # Redis 服务器地址
|
||||||
|
port: 6379 # Redis 服务器连接端口
|
||||||
|
password: redis # Redis 服务器连接密码(默认为空)
|
||||||
|
timeout: 5s # 读超时时间
|
||||||
|
connect-timeout: 5s # 链接超时时间
|
||||||
|
lettuce:
|
||||||
|
pool:
|
||||||
|
max-active: 200 # 连接池最大连接数
|
||||||
|
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||||
|
min-idle: 0 # 连接池中的最小空闲连接
|
||||||
|
max-idle: 10 # 连接池中的最大空闲连接
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
configuration:
|
configuration:
|
||||||
map-underscore-to-camel-case: true
|
map-underscore-to-camel-case: true
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.hanserwei.hannote.auth.domain.mapper.PermissionDOMapper">
|
<mapper namespace="com.hanserwei.hannote.user.biz.domain.mapper.PermissionDOMapper">
|
||||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.auth.domain.dataobject.PermissionDO">
|
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.PermissionDO">
|
||||||
<!--@mbg.generated-->
|
<!--@mbg.generated-->
|
||||||
<!--@Table t_permission-->
|
<!--@Table t_permission-->
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.hanserwei.hannote.auth.domain.mapper.RoleDOMapper">
|
<mapper namespace="com.hanserwei.hannote.user.biz.domain.mapper.RoleDOMapper">
|
||||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.auth.domain.dataobject.RoleDO">
|
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO">
|
||||||
<!--@mbg.generated-->
|
<!--@mbg.generated-->
|
||||||
<!--@Table t_role-->
|
<!--@Table t_role-->
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.hanserwei.hannote.auth.domain.mapper.RolePermissionDOMapper">
|
<mapper namespace="com.hanserwei.hannote.user.biz.domain.mapper.RolePermissionDOMapper">
|
||||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.auth.domain.dataobject.RolePermissionDO">
|
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.RolePermissionDO">
|
||||||
<!--@mbg.generated-->
|
<!--@mbg.generated-->
|
||||||
<!--@Table t_role_permission_rel-->
|
<!--@Table t_role_permission_rel-->
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.hanserwei.hannote.auth.domain.mapper.UserRoleDOMapper">
|
<mapper namespace="com.hanserwei.hannote.user.biz.domain.mapper.UserRoleDOMapper">
|
||||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.auth.domain.dataobject.UserRoleDO">
|
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.UserRoleDO">
|
||||||
<!--@mbg.generated-->
|
<!--@mbg.generated-->
|
||||||
<!--@Table t_user_role_rel-->
|
<!--@Table t_user_role_rel-->
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import com.hanserwei.hannote.user.biz.HannoteUserBizApplication;
|
||||||
|
import com.hanserwei.hannote.user.biz.constant.RedisKeyConstants;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = HannoteUserBizApplication.class)
|
||||||
|
public class HannoteIdGenerateTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
// Long id = redisTemplate.opsForValue().increment(RedisKeyConstants.HAN_NOTE_ID_GENERATOR_KEY);
|
||||||
|
Object id = redisTemplate.opsForValue().get(RedisKeyConstants.HAN_NOTE_ID_GENERATOR_KEY);
|
||||||
|
System.out.println(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
7
pom.xml
7
pom.xml
@@ -215,6 +215,13 @@
|
|||||||
<artifactId>feign-form</artifactId>
|
<artifactId>feign-form</artifactId>
|
||||||
<version>${feign-form.version}</version>
|
<version>${feign-form.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hanserwei</groupId>
|
||||||
|
<artifactId>han-note-user-api</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user