refactor(auth):重构认证服务,分离用户逻辑到独立服务
- 将用户相关业务迁移至用户模块,通过OpenFeign远程调用。
This commit is contained in:
@@ -70,6 +70,20 @@
|
||||
<groupId>com.hanserwei</groupId>
|
||||
<artifactId>han-note-oss-api</artifactId>
|
||||
</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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import com.hanserwei.framework.common.response.Response;
|
||||
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
||||
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 lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -30,4 +36,23 @@ public class UserController {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.hanserwei.hannote.user.biz.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.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 权限表
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "t_permission")
|
||||
public class PermissionDO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 父ID
|
||||
*/
|
||||
@TableField(value = "parent_id")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 权限名称
|
||||
*/
|
||||
@TableField(value = "`name`")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 类型(1:目录 2:菜单 3:按钮)
|
||||
*/
|
||||
@TableField(value = "`type`")
|
||||
private Byte type;
|
||||
|
||||
/**
|
||||
* 菜单路由
|
||||
*/
|
||||
@TableField(value = "menu_url")
|
||||
private String menuUrl;
|
||||
|
||||
/**
|
||||
* 菜单图标
|
||||
*/
|
||||
@TableField(value = "menu_icon")
|
||||
private String menuIcon;
|
||||
|
||||
/**
|
||||
* 管理系统中的显示顺序
|
||||
*/
|
||||
@TableField(value = "sort")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 权限标识
|
||||
*/
|
||||
@TableField(value = "permission_key")
|
||||
private String permissionKey;
|
||||
|
||||
/**
|
||||
* 状态(0:启用;1:禁用)
|
||||
*/
|
||||
@TableField(value = "`status`")
|
||||
private Byte status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField(value = "is_deleted")
|
||||
private Boolean isDeleted;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.hanserwei.hannote.user.biz.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.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 角色表
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "t_role")
|
||||
public class RoleDO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
@TableField(value = "role_name")
|
||||
private String roleName;
|
||||
|
||||
/**
|
||||
* 角色唯一标识
|
||||
*/
|
||||
@TableField(value = "role_key")
|
||||
private String roleKey;
|
||||
|
||||
/**
|
||||
* 状态(0:启用 1:禁用)
|
||||
*/
|
||||
@TableField(value = "`status`")
|
||||
private Byte status;
|
||||
|
||||
/**
|
||||
* 管理系统中的显示顺序
|
||||
*/
|
||||
@TableField(value = "sort")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@TableField(value = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 最后一次更新时间
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField(value = "is_deleted")
|
||||
private Boolean isDeleted;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.hanserwei.hannote.user.biz.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.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户权限表
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "t_role_permission_rel")
|
||||
public class RolePermissionDO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
@TableField(value = "role_id")
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 权限ID
|
||||
*/
|
||||
@TableField(value = "permission_id")
|
||||
private Long permissionId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField(value = "is_deleted")
|
||||
private Boolean isDeleted;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.hanserwei.hannote.user.biz.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.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户角色表
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "t_user_role_rel")
|
||||
public class UserRoleDO {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@TableField(value = "user_id")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
@TableField(value = "role_id")
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField(value = "is_deleted")
|
||||
private Boolean isDeleted;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.PermissionDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PermissionDOMapper extends BaseMapper<PermissionDO> {
|
||||
/**
|
||||
* 查询 APP 端所有被启用的权限
|
||||
*
|
||||
* @return 权限列表
|
||||
*/
|
||||
List<PermissionDO> selectAppEnabledList();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface RoleDOMapper extends BaseMapper<RoleDO> {
|
||||
|
||||
/**
|
||||
* 查询所有被启用的角色
|
||||
*
|
||||
* @return 角色列表
|
||||
*/
|
||||
List<RoleDO> selectEnabledList();
|
||||
|
||||
RoleDO selectByPrimaryKey(Long commonUserRoleId);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.RolePermissionDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface RolePermissionDOMapper extends BaseMapper<RolePermissionDO> {
|
||||
/**
|
||||
* 根据角色 ID 集合批量查询
|
||||
*
|
||||
* @param roleIds 角色 ID 集合
|
||||
* @return 角色权限关系
|
||||
*/
|
||||
List<RolePermissionDO> selectByRoleIds(@Param("roleIds") List<Long> roleIds);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.hanserwei.hannote.user.biz.domain.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.UserRoleDO;
|
||||
|
||||
public interface UserRoleDOMapper extends BaseMapper<UserRoleDO> {
|
||||
}
|
||||
@@ -19,6 +19,7 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
|
||||
INTRODUCTION_VALID_FAIL("USER-20004", "个人简介请设置1-100个字符"),
|
||||
UPLOAD_AVATAR_FAIL("USER-20005", "头像上传失败"),
|
||||
UPLOAD_BACKGROUND_IMG_FAIL("USER-20006", "背景图上传失败"),
|
||||
USER_NOT_FOUND("USER-20007", "该用户不存在"),
|
||||
;
|
||||
|
||||
// 异常码
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.hanserwei.hannote.user.biz.runner;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.hanserwei.framework.common.utils.JsonUtils;
|
||||
import com.hanserwei.hannote.user.biz.constant.RedisKeyConstants;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.PermissionDO;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.RolePermissionDO;
|
||||
import com.hanserwei.hannote.user.biz.domain.mapper.PermissionDOMapper;
|
||||
import com.hanserwei.hannote.user.biz.domain.mapper.RoleDOMapper;
|
||||
import com.hanserwei.hannote.user.biz.domain.mapper.RolePermissionDOMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PushRolePermissions2RedisRunner implements ApplicationRunner {
|
||||
@Resource
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
@Resource
|
||||
private RoleDOMapper roleDOMapper;
|
||||
@Resource
|
||||
private PermissionDOMapper permissionDOMapper;
|
||||
@Resource
|
||||
private RolePermissionDOMapper rolePermissionDOMapper;
|
||||
|
||||
// 权限同步标记 Key
|
||||
private static final String PUSH_PERMISSION_FLAG = "push.permission.flag";
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
try {
|
||||
// 是否能够同步数据: 原子操作,只有在键 PUSH_PERMISSION_FLAG 不存在时,才会设置该键的值为 "1",并设置过期时间为 1 天
|
||||
boolean canPushed = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(PUSH_PERMISSION_FLAG, "1", 1, TimeUnit.DAYS));
|
||||
|
||||
// 如果无法同步权限数据
|
||||
if (!canPushed) {
|
||||
log.warn("==> 角色权限数据已经同步至 Redis 中,不再同步...");
|
||||
return;
|
||||
}
|
||||
// 查询出所有角色
|
||||
List<RoleDO> roleDOS = roleDOMapper.selectEnabledList();
|
||||
|
||||
if (CollUtil.isNotEmpty(roleDOS)) {
|
||||
// 拿到所有角色的 ID
|
||||
List<Long> roleIds = roleDOS.stream().map(RoleDO::getId).toList();
|
||||
|
||||
// 根据角色 ID, 批量查询出所有角色对应的权限
|
||||
List<RolePermissionDO> rolePermissionDOS = rolePermissionDOMapper.selectByRoleIds(roleIds);
|
||||
// 按角色 ID 分组, 每个角色 ID 对应多个权限 ID
|
||||
Map<Long, List<Long>> roleIdPermissionIdsMap = rolePermissionDOS.stream().collect(
|
||||
Collectors.groupingBy(RolePermissionDO::getRoleId,
|
||||
Collectors.mapping(RolePermissionDO::getPermissionId, Collectors.toList()))
|
||||
);
|
||||
|
||||
// 查询 APP 端所有被启用的权限
|
||||
List<PermissionDO> permissionDOS = permissionDOMapper.selectAppEnabledList();
|
||||
// 权限 ID - 权限 DO
|
||||
Map<Long, PermissionDO> permissionIdDOMap = permissionDOS.stream().collect(
|
||||
Collectors.toMap(PermissionDO::getId, permissionDO -> permissionDO)
|
||||
);
|
||||
|
||||
// 组织 角色ID-权限 关系
|
||||
Map<String, List<String>> roleKeyPermissionMap = Maps.newHashMap();
|
||||
|
||||
// 循环所有角色
|
||||
roleDOS.forEach(roleDO -> {
|
||||
// 当前角色 roleKey
|
||||
String roleKey = roleDO.getRoleKey();
|
||||
// 当前角色 ID
|
||||
Long roleId = roleDO.getId();
|
||||
// 当前角色 ID 对应的权限 ID 集合
|
||||
List<Long> permissionIds = roleIdPermissionIdsMap.get(roleId);
|
||||
if (CollUtil.isNotEmpty(permissionIds)) {
|
||||
List<String> permissionKeys = Lists.newArrayList();
|
||||
permissionIds.forEach(permissionId -> {
|
||||
// 根据权限 ID 获取具体的权限 DO 对象
|
||||
PermissionDO permissionDO = permissionIdDOMap.get(permissionId);
|
||||
permissionKeys.add(permissionDO.getPermissionKey());
|
||||
});
|
||||
roleKeyPermissionMap.put(roleKey, permissionKeys);
|
||||
}
|
||||
});
|
||||
|
||||
// 同步至 Redis 中,方便后续网关查询鉴权使用
|
||||
roleKeyPermissionMap.forEach((roleId, permissions) -> {
|
||||
String key = RedisKeyConstants.buildRolePermissionsKey(roleId);
|
||||
redisTemplate.opsForValue().set(key, JsonUtils.toJsonString(permissions));
|
||||
});
|
||||
}
|
||||
|
||||
log.info("==> 服务启动,成功同步角色权限数据到 Redis 中...");
|
||||
} catch (Exception e) {
|
||||
log.error("==> 同步角色权限数据到 Redis 中失败: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.hanserwei.framework.common.response.Response;
|
||||
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
|
||||
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> {
|
||||
|
||||
@@ -14,4 +18,28 @@ public interface UserService extends IService<UserDO> {
|
||||
* @return 响应结果
|
||||
*/
|
||||
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;
|
||||
|
||||
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.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.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.UserRoleDOMapper;
|
||||
import com.hanserwei.hannote.user.biz.enums.ResponseCodeEnum;
|
||||
import com.hanserwei.hannote.user.biz.enums.SexEnum;
|
||||
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
|
||||
import com.hanserwei.hannote.user.biz.rpc.OssRpcService;
|
||||
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 lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@@ -29,6 +47,12 @@ public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implement
|
||||
|
||||
@Resource
|
||||
private OssRpcService ossRpcService;
|
||||
@Resource
|
||||
private UserRoleDOMapper userRoleDOMapper;
|
||||
@Resource
|
||||
private RoleDOMapper roleDOMapper;
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public Response<?> updateUserInfo(UpdateUserInfoReqVO updateUserInfoReqVO) {
|
||||
@@ -114,4 +138,92 @@ public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implement
|
||||
}
|
||||
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:
|
||||
max-file-size: 20MB # 单个文件最大大小
|
||||
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:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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.user.biz.domain.mapper.PermissionDOMapper">
|
||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.PermissionDO">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table t_permission-->
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="parent_id" jdbcType="BIGINT" property="parentId" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="type" jdbcType="TINYINT" property="type" />
|
||||
<result column="menu_url" jdbcType="VARCHAR" property="menuUrl" />
|
||||
<result column="menu_icon" jdbcType="VARCHAR" property="menuIcon" />
|
||||
<result column="sort" jdbcType="INTEGER" property="sort" />
|
||||
<result column="permission_key" jdbcType="VARCHAR" property="permissionKey" />
|
||||
<result column="status" jdbcType="TINYINT" property="status" />
|
||||
<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, parent_id, `name`, `type`, menu_url, menu_icon, sort, permission_key, `status`,
|
||||
create_time, update_time, is_deleted
|
||||
</sql>
|
||||
|
||||
<select id="selectAppEnabledList" resultMap="BaseResultMap">
|
||||
select id, name, permission_key
|
||||
from t_permission
|
||||
where status = 0
|
||||
and type = 3
|
||||
and is_deleted = 0
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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.user.biz.domain.mapper.RoleDOMapper">
|
||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.RoleDO">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table t_role-->
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="role_name" jdbcType="VARCHAR" property="roleName" />
|
||||
<result column="role_key" jdbcType="VARCHAR" property="roleKey" />
|
||||
<result column="status" jdbcType="TINYINT" property="status" />
|
||||
<result column="sort" jdbcType="INTEGER" property="sort" />
|
||||
<result column="remark" jdbcType="VARCHAR" property="remark" />
|
||||
<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, role_name, role_key, `status`, sort, remark, create_time, update_time, is_deleted
|
||||
</sql>
|
||||
|
||||
<select id="selectEnabledList" resultMap="BaseResultMap">
|
||||
select id, role_key, role_name
|
||||
from t_role
|
||||
where status = 0
|
||||
and is_deleted = 0;
|
||||
</select>
|
||||
|
||||
<select id="selectByPrimaryKey" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List"/>
|
||||
from t_role
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
and is_deleted = 0
|
||||
and status = 0;
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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.user.biz.domain.mapper.RolePermissionDOMapper">
|
||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.RolePermissionDO">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table t_role_permission_rel-->
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="role_id" jdbcType="BIGINT" property="roleId" />
|
||||
<result column="permission_id" jdbcType="BIGINT" property="permissionId" />
|
||||
<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, role_id, permission_id, create_time, update_time, is_deleted
|
||||
</sql>
|
||||
|
||||
<select id="selectByRoleIds" resultMap="BaseResultMap">
|
||||
select role_id, permission_id
|
||||
from t_role_permission_rel
|
||||
where role_id in
|
||||
<foreach collection="roleIds" item="roleId" separator="," open="(" close=")">
|
||||
#{roleId}
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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.user.biz.domain.mapper.UserRoleDOMapper">
|
||||
<resultMap id="BaseResultMap" type="com.hanserwei.hannote.user.biz.domain.dataobject.UserRoleDO">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table t_user_role_rel-->
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="user_id" jdbcType="BIGINT" property="userId" />
|
||||
<result column="role_id" jdbcType="BIGINT" property="roleId" />
|
||||
<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, user_id, role_id, create_time, update_time, is_deleted
|
||||
</sql>
|
||||
</mapper>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user