This commit is contained in:
@@ -145,6 +145,12 @@
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redis-jackson</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redis-jackson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Redis -->
|
||||
<dependency>
|
||||
|
||||
@@ -19,6 +19,12 @@ public class RedisKeyConstants {
|
||||
* 验证码 KEY 过期时间 (分钟)
|
||||
*/
|
||||
public static final long VERIFICATION_CODE_EXPIRE_TIME = 3;
|
||||
|
||||
/**
|
||||
* 用户角色数据 KEY 前缀
|
||||
*/
|
||||
private static final String USER_ROLES_KEY_PREFIX = "user:roles:";
|
||||
|
||||
/**
|
||||
* 构建验证码 KEY
|
||||
*
|
||||
@@ -29,4 +35,14 @@ public class RedisKeyConstants {
|
||||
return VERIFICATION_CODE_KEY_PREFIX + phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建用户角色数据 KEY
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @return 用户角色数据 KEY
|
||||
*/
|
||||
public static String buildUserRolesKey(Long userId) {
|
||||
return USER_ROLES_KEY_PREFIX + userId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.crushtj.xiaoyishu.auth.constant;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title RoleConstants
|
||||
* @date 2026/01/18 21:24
|
||||
* @description 角色常量
|
||||
*/
|
||||
|
||||
public class RoleConstants {
|
||||
/**
|
||||
* 普通用户的角色 ID
|
||||
*/
|
||||
public static final Long COMMON_USER_ROLE_ID = 1L;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package top.crushtj.xiaoyishu.auth.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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;
|
||||
import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import top.crushtj.framework.common.response.Response;
|
||||
import top.crushtj.xiaoyishu.auth.model.vo.User;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @title TestController
|
||||
* @description 测试控制器
|
||||
* @date 2025/11/21
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class TestController {
|
||||
|
||||
@GetMapping("/test")
|
||||
@ApiOperationLog(description = "测试接口")
|
||||
public Response<User> testController() {
|
||||
return Response.success(User.builder().id(1L).name("ayi").age(18).createTime(LocalDateTime.now()).build());
|
||||
}
|
||||
|
||||
@PostMapping("/test2")
|
||||
@ApiOperationLog(description = "测试接口2")
|
||||
public Response<User> test2(@RequestBody @Validated User user) {
|
||||
// int i = 1 / 0;
|
||||
return Response.success(user);
|
||||
}
|
||||
|
||||
@RequestMapping("/user/doLogin")
|
||||
public String doLogin(String username, String password) {
|
||||
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
|
||||
if ("ayi".equals(username) && "12345678".equals(password)) {
|
||||
StpUtil.login(10001);
|
||||
return "登录成功";
|
||||
}
|
||||
return "登录失败";
|
||||
}
|
||||
|
||||
// 查询登录状态,浏览器访问: http://localhost:8080/user/isLogin
|
||||
@RequestMapping("/user/isLogin")
|
||||
public String isLogin() {
|
||||
return "当前会话是否登录:" + StpUtil.isLogin();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package top.crushtj.xiaoyishu.auth.controller;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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;
|
||||
import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import top.crushtj.framework.common.response.Response;
|
||||
import top.crushtj.xiaoyishu.auth.model.vo.user.UserLoginReqVO;
|
||||
import top.crushtj.xiaoyishu.auth.service.UserService;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserController
|
||||
* @date 2026-01-18 20:40:21
|
||||
* @description 用户表(User)表控制层
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping("/login")
|
||||
@ApiOperationLog(description = "用户登录或注册")
|
||||
public Response<String> loginOrRegister(@RequestBody @Validated UserLoginReqVO userLoginReqVO) {
|
||||
return userService.loginOrRegister(userLoginReqVO);
|
||||
}
|
||||
}
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.entity;
|
||||
|
||||
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.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title PermissionEntity
|
||||
* @date 2026-01-18 21:20:36
|
||||
* @description 权限表(t_permission)表实体类
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName("t_permission")
|
||||
public class PermissionEntity implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -18586083527537804L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId("ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 父ID
|
||||
*/
|
||||
@TableField("PARENT_ID")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 权限名称
|
||||
*/
|
||||
@TableField("NAME")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 类型(1:目录 2:菜单 3:按钮)
|
||||
*/
|
||||
@TableField("TYPE")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 菜单路由
|
||||
*/
|
||||
@TableField("MENU_URL")
|
||||
private String menuUrl;
|
||||
|
||||
/**
|
||||
* 菜单图标
|
||||
*/
|
||||
@TableField("MENU_ICON")
|
||||
private String menuIcon;
|
||||
|
||||
/**
|
||||
* 管理系统中的显示顺序
|
||||
*/
|
||||
@TableField("SORT")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 权限标识
|
||||
*/
|
||||
@TableField("PERMISSION_KEY")
|
||||
private String permissionKey;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;0:禁用)
|
||||
*/
|
||||
@TableField("STATUS")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("CREATE_TIME")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("UPDATE_TIME")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField("IS_DELETED")
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.entity;
|
||||
|
||||
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.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title RoleEntity
|
||||
* @date 2026-01-18 21:20:51
|
||||
* @description 角色表(t_role)表实体类
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName("t_role")
|
||||
public class RoleEntity implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 294965117543247928L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId("ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
@TableField("ROLE_NAME")
|
||||
private String roleName;
|
||||
|
||||
/**
|
||||
* 角色唯一标识
|
||||
*/
|
||||
@TableField("ROLE_KEY")
|
||||
private String roleKey;
|
||||
|
||||
/**
|
||||
* 状态(1:启用 0:禁用)
|
||||
*/
|
||||
@TableField("STATUS")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 管理系统中的显示顺序
|
||||
*/
|
||||
@TableField("SORT")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@TableField("REMARK")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("CREATE_TIME")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 最后一次更新时间
|
||||
*/
|
||||
@TableField("UPDATE_TIME")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField("IS_DELETED")
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.entity;
|
||||
|
||||
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.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title RolePermissionRelEntity
|
||||
* @date 2026-01-18 21:21:12
|
||||
* @description 用户权限表(t_role_permission_rel)表实体类
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName("t_role_permission_rel")
|
||||
public class RolePermissionRelEntity implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 308157477991435934L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId("ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
@TableField("ROLE_ID")
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 权限ID
|
||||
*/
|
||||
@TableField("PERMISSION_ID")
|
||||
private Long permissionId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("CREATE_TIME")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("UPDATE_TIME")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField("IS_DELETED")
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
||||
+69
-12
@@ -3,8 +3,6 @@ package top.crushtj.xiaoyishu.auth.domain.entity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -12,14 +10,15 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserEntity
|
||||
* @date 2025/11/27
|
||||
* @description 用户测试表
|
||||
* @date 2026/01/18 19:33:00
|
||||
* @description 用户表
|
||||
*/
|
||||
|
||||
@Data
|
||||
@@ -28,22 +27,74 @@ import java.time.LocalDateTime;
|
||||
@NoArgsConstructor
|
||||
@TableName("t_user")
|
||||
public class UserEntity implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 403394297290102294L;
|
||||
private static final long serialVersionUID = -31680834394879938L;
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
* 主键ID
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@TableId("ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
* 小壹书号(唯一凭证)
|
||||
*/
|
||||
@TableField("USERNAME")
|
||||
private String username;
|
||||
@TableField("XIAOYISHU_ID")
|
||||
private String xiaoyishuId;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@TableField("PASSWORD")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@TableField("NICKNAME")
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
@TableField("AVATAR")
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 生日
|
||||
*/
|
||||
@TableField("BIRTHDAY")
|
||||
private LocalDate birthday;
|
||||
|
||||
/**
|
||||
* 背景图
|
||||
*/
|
||||
@TableField("BACKGROUND_IMG")
|
||||
private String backgroundImg;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@TableField("PHONE")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 性别(1: 男 2: 女 3: 未知)
|
||||
*/
|
||||
@TableField("SEX")
|
||||
private Integer sex;
|
||||
|
||||
/**
|
||||
* 状态(1:启用 0:禁用)
|
||||
*/
|
||||
@TableField("STATUS")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 个人简介
|
||||
*/
|
||||
@TableField("INTRODUCTION")
|
||||
private String introduction;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
@@ -57,4 +108,10 @@ public class UserEntity implements Serializable {
|
||||
@TableField("UPDATE_TIME")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField("IS_DELETED")
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.entity;
|
||||
|
||||
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.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserRoleRelEntity
|
||||
* @date 2026-01-18 21:21:25
|
||||
* @description 用户角色表(t_user_role_rel)表实体类
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName("t_user_role_rel")
|
||||
public class UserRoleRelEntity implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 788758889499348222L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId("ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@TableField("USER_ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
@TableField("ROLE_ID")
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("CREATE_TIME")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("UPDATE_TIME")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0:未删除 1:已删除)
|
||||
*/
|
||||
@TableField("IS_DELETED")
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.PermissionEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title PermissionMapper
|
||||
* @date 2026-01-18 21:20:37
|
||||
* @description 权限表(t_permission)表数据库访问层
|
||||
*/
|
||||
public interface PermissionMapper extends BaseMapper<PermissionEntity> {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RoleEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title RoleMapper
|
||||
* @date 2026-01-18 21:20:51
|
||||
* @description 角色表(t_role)表数据库访问层
|
||||
*/
|
||||
public interface RoleMapper extends BaseMapper<RoleEntity> {
|
||||
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RolePermissionRelEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title RolePermissionRelMapper
|
||||
* @date 2026-01-18 21:21:12
|
||||
* @description 用户权限表(t_role_permission_rel)表数据库访问层
|
||||
*/
|
||||
public interface RolePermissionRelMapper extends BaseMapper<RolePermissionRelEntity> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.UserEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @title 用户测试表
|
||||
* @date 2025/11/27
|
||||
* @description (t_user)表数据库访问层
|
||||
* @version V1.0
|
||||
* @title User
|
||||
* @date 2026/01/18 19:33:00
|
||||
* @description 用户表(t_user)表数据库访问层
|
||||
*/
|
||||
public interface UserMapper extends BaseMapper<UserEntity> {
|
||||
|
||||
UserEntity selectByPhone(@Param("phone") String phone);
|
||||
}
|
||||
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.UserRoleRelEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserRoleRelMapper
|
||||
* @date 2026-01-18 21:21:25
|
||||
* @description 用户角色表(t_user_role_rel)表数据库访问层
|
||||
*/
|
||||
public interface UserRoleRelMapper extends BaseMapper<UserRoleRelEntity> {
|
||||
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?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 = "top.crushtj.xiaoyishu.auth.domain.mappers.PermissionMapper">
|
||||
|
||||
<resultMap type = "top.crushtj.xiaoyishu.auth.domain.entity.PermissionEntity" id = "PermissionMap">
|
||||
<result property = "id" column = "id" jdbcType = "INTEGER"/>
|
||||
<result property = "parentId" column = "parent_id" jdbcType = "INTEGER"/>
|
||||
<result property = "name" column = "name" jdbcType = "VARCHAR"/>
|
||||
<result property = "type" column = "type" jdbcType = "INTEGER"/>
|
||||
<result property = "menuUrl" column = "menu_url" jdbcType = "VARCHAR"/>
|
||||
<result property = "menuIcon" column = "menu_icon" jdbcType = "VARCHAR"/>
|
||||
<result property = "sort" column = "sort" jdbcType = "INTEGER"/>
|
||||
<result property = "permissionKey" column = "permission_key" jdbcType = "VARCHAR"/>
|
||||
<result property = "status" column = "status" jdbcType = "INTEGER"/>
|
||||
<result property = "createTime" column = "create_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "updateTime" column = "update_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "isDeleted" column = "is_deleted" jdbcType = "INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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 = "top.crushtj.xiaoyishu.auth.domain.mappers.RoleMapper">
|
||||
|
||||
<resultMap type = "top.crushtj.xiaoyishu.auth.domain.entity.RoleEntity" id = "RoleMap">
|
||||
<result property = "id" column = "id" jdbcType = "INTEGER"/>
|
||||
<result property = "roleName" column = "role_name" jdbcType = "VARCHAR"/>
|
||||
<result property = "roleKey" column = "role_key" jdbcType = "VARCHAR"/>
|
||||
<result property = "status" column = "status" jdbcType = "INTEGER"/>
|
||||
<result property = "sort" column = "sort" jdbcType = "INTEGER"/>
|
||||
<result property = "remark" column = "remark" jdbcType = "VARCHAR"/>
|
||||
<result property = "createTime" column = "create_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "updateTime" column = "update_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "isDeleted" column = "is_deleted" jdbcType = "INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<?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 = "top.crushtj.xiaoyishu.auth.domain.mappers.RolePermissionRelMapper">
|
||||
|
||||
<resultMap type = "top.crushtj.xiaoyishu.auth.domain.entity.RolePermissionRelEntity" id = "RolePermissionRelMap">
|
||||
<result property = "id" column = "id" jdbcType = "INTEGER"/>
|
||||
<result property = "roleId" column = "role_id" jdbcType = "INTEGER"/>
|
||||
<result property = "permissionId" column = "permission_id" jdbcType = "INTEGER"/>
|
||||
<result property = "createTime" column = "create_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "updateTime" column = "update_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "isDeleted" column = "is_deleted" jdbcType = "INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
||||
+16
-5
@@ -4,13 +4,24 @@
|
||||
|
||||
<resultMap type = "top.crushtj.xiaoyishu.auth.domain.entity.UserEntity" id = "UserMap">
|
||||
<result property = "id" column = "id" jdbcType = "INTEGER"/>
|
||||
<result property="username" column="username" jdbcType="VARCHAR"/>
|
||||
<result property = "xiaoyishuId" column = "xiaoyishu_id" jdbcType = "VARCHAR"/>
|
||||
<result property = "password" column = "password" jdbcType = "VARCHAR"/>
|
||||
<result property = "nickname" column = "nickname" jdbcType = "VARCHAR"/>
|
||||
<result property = "avatar" column = "avatar" jdbcType = "VARCHAR"/>
|
||||
<result property = "birthday" column = "birthday" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "backgroundImg" column = "background_img" jdbcType = "VARCHAR"/>
|
||||
<result property = "phone" column = "phone" jdbcType = "VARCHAR"/>
|
||||
<result property = "sex" column = "sex" jdbcType = "INTEGER"/>
|
||||
<result property = "status" column = "status" jdbcType = "INTEGER"/>
|
||||
<result property = "introduction" column = "introduction" jdbcType = "VARCHAR"/>
|
||||
<result property = "createTime" column = "create_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "updateTime" column = "update_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "isDeleted" column = "is_deleted" jdbcType = "INTEGER"/>
|
||||
</resultMap>
|
||||
<!-- 所有列的SQL片段 -->
|
||||
<sql id="Base_Column_List">
|
||||
id,username,create_time,update_time
|
||||
</sql>
|
||||
<select id = "selectByPhone" resultType = "top.crushtj.xiaoyishu.auth.domain.entity.UserEntity">
|
||||
SELECT id, password
|
||||
FROM t_user
|
||||
WHERE phone = #{phone}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<?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 = "top.crushtj.xiaoyishu.auth.domain.mappers.UserRoleRelMapper">
|
||||
|
||||
<resultMap type = "top.crushtj.xiaoyishu.auth.domain.entity.UserRoleRelEntity" id = "UserRoleRelMap">
|
||||
<result property = "id" column = "id" jdbcType = "INTEGER"/>
|
||||
<result property = "userId" column = "user_id" jdbcType = "INTEGER"/>
|
||||
<result property = "roleId" column = "role_id" jdbcType = "INTEGER"/>
|
||||
<result property = "createTime" column = "create_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "updateTime" column = "update_time" jdbcType = "TIMESTAMP"/>
|
||||
<result property = "isDeleted" column = "is_deleted" jdbcType = "INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,34 @@
|
||||
package top.crushtj.xiaoyishu.auth.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title LoginTypeEnum
|
||||
* @date 2026/01/18 20:15
|
||||
* @description 登录类型枚举
|
||||
*/
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LoginTypeEnum {
|
||||
// 验证码
|
||||
VERIFICATION_CODE(1),
|
||||
// 密码
|
||||
PASSWORD(2);
|
||||
|
||||
private final Integer value;
|
||||
|
||||
public static LoginTypeEnum valueOf(Integer code) {
|
||||
for (LoginTypeEnum loginTypeEnum : LoginTypeEnum.values()) {
|
||||
if (Objects.equals(code, loginTypeEnum.getValue())) {
|
||||
return loginTypeEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,13 @@ import top.crushtj.framework.common.exception.BaseExceptionInterface;
|
||||
@AllArgsConstructor
|
||||
public enum ResponseCodeEnum implements BaseExceptionInterface {
|
||||
// -------- 通用异常状态码 --------
|
||||
SYSTEM_ERROR("AUTH-10000", "系统错误"), PARAM_NOT_VALID("AUTH-10001", "参数错误"), // -------- 验证码异常状态码 --------
|
||||
SYSTEM_ERROR("AUTH-10000", "系统错误"),
|
||||
PARAM_NOT_VALID("AUTH-10001", "参数错误"), // -------- 验证码异常状态码 --------
|
||||
VERIFICATION_CODE_SEND_FREQUENTLY("AUTH-20000", "请求太频繁,请3分钟后再试"),
|
||||
SMS_SEND_FAILED("AUTH-20001", "短信发送失败,请稍后再试"),
|
||||
SMS_SEND_TIMEOUT("AUTH-20002", "短信发送超时,请稍后再试");
|
||||
SMS_SEND_TIMEOUT("AUTH-20002", "短信发送超时,请稍后再试"),
|
||||
VERIFICATION_CODE_ERROR("AUTH-20003", "验证码错误"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package top.crushtj.xiaoyishu.auth.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @title User
|
||||
* @description 测试用户类
|
||||
* @date 2025/11/26
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class User implements Serializable {
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long id;
|
||||
@NotBlank(message = "用户名称不能为空")
|
||||
private String name;
|
||||
private Integer age;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package top.crushtj.xiaoyishu.auth.model.vo.user;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import top.crushtj.framework.common.validator.PhoneNumber;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserVo
|
||||
* @date 2026/01/18 20:13
|
||||
* @description 用户登录参数
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserLoginReqVO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -2349922278492431614L;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@NotBlank(message = "手机号不能为空")
|
||||
@PhoneNumber
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 登录类型:手机号验证码,或者是账号密码
|
||||
*/
|
||||
@NotNull(message = "登录类型不能为空")
|
||||
private Integer type;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package top.crushtj.xiaoyishu.auth.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import top.crushtj.framework.common.response.Response;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.UserEntity;
|
||||
import top.crushtj.xiaoyishu.auth.model.vo.user.UserLoginReqVO;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserService
|
||||
* @date 2026-01-18 20:09:57
|
||||
* @description 用户表(t_user)表服务接口
|
||||
*/
|
||||
|
||||
public interface UserService extends IService<UserEntity> {
|
||||
|
||||
/**
|
||||
* 登录或注册
|
||||
*
|
||||
* @param userLoginReqVO 登录或注册参数
|
||||
* @return 登录结果
|
||||
*/
|
||||
Response<String> loginOrRegister(UserLoginReqVO userLoginReqVO);
|
||||
}
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package top.crushtj.xiaoyishu.auth.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
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 top.crushtj.framework.common.exception.BizException;
|
||||
import top.crushtj.framework.common.response.Response;
|
||||
import top.crushtj.framework.common.utils.MaskUtils;
|
||||
import top.crushtj.xiaoyishu.auth.constant.RedisKeyConstants;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.UserEntity;
|
||||
import top.crushtj.xiaoyishu.auth.domain.mappers.UserMapper;
|
||||
import top.crushtj.xiaoyishu.auth.enums.LoginTypeEnum;
|
||||
import top.crushtj.xiaoyishu.auth.enums.ResponseCodeEnum;
|
||||
import top.crushtj.xiaoyishu.auth.model.vo.user.UserLoginReqVO;
|
||||
import top.crushtj.xiaoyishu.auth.service.UserService;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title UserServiceImpl
|
||||
* @date 2026-01-18 20:09:58
|
||||
* @description 用户表(t_user)表服务实现类
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Service("userService")
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public Response<String> loginOrRegister(UserLoginReqVO userLoginReqVO) {
|
||||
String phone = userLoginReqVO.getPhone();
|
||||
Integer type = userLoginReqVO.getType();
|
||||
Long userId = null;
|
||||
LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);
|
||||
switch (loginTypeEnum) {
|
||||
case PASSWORD -> {
|
||||
String password = userLoginReqVO.getPassword();
|
||||
// 密码登录
|
||||
|
||||
}
|
||||
case VERIFICATION_CODE -> {
|
||||
String verificationCode = userLoginReqVO.getCode();
|
||||
// 验证码登录
|
||||
// 校验入参验证码是否为空
|
||||
if (StringUtils.isBlank(verificationCode)) {
|
||||
return Response.failure(ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode(), "验证码不能为空");
|
||||
}
|
||||
|
||||
// 构建验证码 Redis Key
|
||||
String key = RedisKeyConstants.buildVerificationCodeKey(phone);
|
||||
// 查询存储在 Redis 中该用户的登录验证码
|
||||
String sentCode = (String)redisTemplate.opsForValue().get(key);
|
||||
|
||||
// 判断用户提交的验证码,与 Redis 中的验证码是否一致
|
||||
if (!StringUtils.equals(verificationCode, sentCode)) {
|
||||
throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
|
||||
}
|
||||
|
||||
// 通过手机号查询记录
|
||||
UserEntity userEntity = userMapper.selectByPhone(phone);
|
||||
|
||||
log.info("==> 用户是否注册, phone: {}, userId: {}", MaskUtils.maskMobile(phone), userEntity.getId());
|
||||
|
||||
// 判断是否注册
|
||||
if (Objects.isNull(userEntity)) {
|
||||
// 若此用户还没有注册,系统自动注册该用户
|
||||
// todo 自动注册用户逻辑
|
||||
|
||||
} else {
|
||||
// 已注册,则获取其用户 ID
|
||||
userId = userEntity.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Response.success("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Description: 初始化权限数据-权限管理未开发,用于测试
|
||||
INSERT INTO `t_permission` (`id`, `parent_id`, `name`, `type`, `menu_url`, `menu_icon`, `sort`,
|
||||
`permission_key`, `status`, `create_time`, `update_time`, `is_deleted`)
|
||||
VALUES (1, 0, '发布笔记', 3, '', '', 1, 'app:note:publish', 1, NOW(), NOW(), b'0');
|
||||
INSERT INTO `t_permission` (`id`, `parent_id`, `name`, `type`, `menu_url`, `menu_icon`, `sort`,
|
||||
`permission_key`, `status`, `create_time`, `update_time`, `is_deleted`)
|
||||
VALUES (2, 0, '发布评论', 3, '', '', 2, 'app:comment:publish', 1, NOW(), NOW(), b'0');
|
||||
|
||||
INSERT INTO `t_role` (`id`, `role_name`, `role_key`, `status`, `sort`, `remark`, `create_time`, `update_time`,
|
||||
`is_deleted`)
|
||||
VALUES (1, '普通用户', 'common_user', 1, 1, '', NOW(), NOW(), b'0');
|
||||
|
||||
INSERT INTO `t_role_permission_rel` (`id`, `role_id`, `permission_id`, `create_time`, `update_time`, `is_deleted`)
|
||||
VALUES (1, 1, 1, NOW(), NOW(), b'0');
|
||||
INSERT INTO `t_role_permission_rel` (`id`, `role_id`, `permission_id`, `create_time`, `update_time`, `is_deleted`)
|
||||
VALUES (2, 1, 2, NOW(), NOW(), b'0');
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package top.crushtj.xiaoyishu.auth;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.UserEntity;
|
||||
import top.crushtj.xiaoyishu.auth.domain.mappers.UserMapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @title XiaoyiAuthApplicationTests
|
||||
* @description 测试类
|
||||
* @date 2025/11/20
|
||||
*/
|
||||
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
class XiaoyiAuthApplicationTests {
|
||||
|
||||
@Resource
|
||||
UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInsert() {
|
||||
UserEntity user =
|
||||
UserEntity.builder().username("刑加一").createTime(LocalDateTime.now()).updateTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
userMapper.insert(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryTest() {
|
||||
LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserEntity::getUsername, "刑加一");
|
||||
queryWrapper.orderByDesc(UserEntity::getCreateTime);
|
||||
queryWrapper.last("limit 1");
|
||||
UserEntity user = userMapper.selectOne(queryWrapper);
|
||||
log.info("查询结果:{}", user);
|
||||
}
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package top.crushtj.framework.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title DeleteEnum
|
||||
* @date 2026/01/18 21:15
|
||||
* @description 删除标记
|
||||
*/
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DeleteEnum {
|
||||
YES(true),
|
||||
NO(false);
|
||||
|
||||
private final Boolean value;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package top.crushtj.framework.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title StatusEnum
|
||||
* @date 2026/01/18
|
||||
* @description 状态
|
||||
*/
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum StatusEnum {
|
||||
ENABLED(1),
|
||||
DISABLED(0);
|
||||
|
||||
private final Integer value;
|
||||
}
|
||||
Reference in New Issue
Block a user