diff --git a/pom.xml b/pom.xml index 9c9267d..3ba6100 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,12 @@ sa-token-spring-boot3-starter ${sa-token.version} + + + cn.dev33 + sa-token-redis-jackson + ${sa-token.version} + org.fusesource.jansi diff --git a/xiaoyi-auth/pom.xml b/xiaoyi-auth/pom.xml index aaca05d..d1544ad 100644 --- a/xiaoyi-auth/pom.xml +++ b/xiaoyi-auth/pom.xml @@ -64,6 +64,10 @@ cn.dev33 sa-token-spring-boot3-starter + + cn.dev33 + sa-token-redis-jackson + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RedisKeyConstants.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RedisKeyConstants.java index 2f60fc2..3be0606 100644 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RedisKeyConstants.java +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RedisKeyConstants.java @@ -19,9 +19,15 @@ 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 - * + * * @param phone 手机号 * @return 验证码 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; + } + } diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RoleConstants.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RoleConstants.java new file mode 100644 index 0000000..2ba624b --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/constant/RoleConstants.java @@ -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; +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/controller/TestController.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/controller/TestController.java deleted file mode 100644 index 1e0a44d..0000000 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/controller/TestController.java +++ /dev/null @@ -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 testController() { - return Response.success(User.builder().id(1L).name("ayi").age(18).createTime(LocalDateTime.now()).build()); - } - - @PostMapping("/test2") - @ApiOperationLog(description = "测试接口2") - public Response 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(); - } - -} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/controller/UserController.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/controller/UserController.java new file mode 100644 index 0000000..ca64f25 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/controller/UserController.java @@ -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 loginOrRegister(@RequestBody @Validated UserLoginReqVO userLoginReqVO) { + return userService.loginOrRegister(userLoginReqVO); + } +} + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/PermissionEntity.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/PermissionEntity.java new file mode 100644 index 0000000..1cb3a29 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/PermissionEntity.java @@ -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; + +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/RoleEntity.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/RoleEntity.java new file mode 100644 index 0000000..7e29833 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/RoleEntity.java @@ -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; + +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/RolePermissionRelEntity.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/RolePermissionRelEntity.java new file mode 100644 index 0000000..44e5051 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/RolePermissionRelEntity.java @@ -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; + +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserEntity.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserEntity.java index 01eebe8..0104496 100644 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserEntity.java +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserEntity.java @@ -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; + } diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserRoleRelEntity.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserRoleRelEntity.java new file mode 100644 index 0000000..001ecfc --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/entity/UserRoleRelEntity.java @@ -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; + +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/PermissionMapper.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/PermissionMapper.java new file mode 100644 index 0000000..c2266a4 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/PermissionMapper.java @@ -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 { + +} + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/RoleMapper.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/RoleMapper.java new file mode 100644 index 0000000..77b6d4a --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/RoleMapper.java @@ -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 { + +} + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/RolePermissionRelMapper.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/RolePermissionRelMapper.java new file mode 100644 index 0000000..c975274 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/RolePermissionRelMapper.java @@ -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 { + +} + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserMapper.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserMapper.java index 25058f9..b8292d2 100644 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserMapper.java +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserMapper.java @@ -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 selectByPhone(@Param("phone") String phone); } diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserRoleRelMapper.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserRoleRelMapper.java new file mode 100644 index 0000000..57fd697 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappers/UserRoleRelMapper.java @@ -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 { + +} + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/PermissionMapping.xml b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/PermissionMapping.xml new file mode 100644 index 0000000..19e8acd --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/PermissionMapping.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/RoleMapping.xml b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/RoleMapping.xml new file mode 100644 index 0000000..cbff99d --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/RoleMapping.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/RolePermissionRelMapping.xml b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/RolePermissionRelMapping.xml new file mode 100644 index 0000000..1f8c670 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/RolePermissionRelMapping.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserMapping.xml b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserMapping.xml index d4da605..21ab9d6 100644 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserMapping.xml +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserMapping.xml @@ -1,16 +1,27 @@ - + - - - - - - - - - id,username,create_time,update_time - + + + + + + + + + + + + + + + + + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserRoleRelMapping.xml b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserRoleRelMapping.xml new file mode 100644 index 0000000..048a945 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/domain/mappings/UserRoleRelMapping.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/LoginTypeEnum.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/LoginTypeEnum.java new file mode 100644 index 0000000..a38dfaa --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/LoginTypeEnum.java @@ -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; + } +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/ResponseCodeEnum.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/ResponseCodeEnum.java index 096307b..99e8661 100644 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/ResponseCodeEnum.java +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/enums/ResponseCodeEnum.java @@ -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", "验证码错误"), + ; /** * 错误码 diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/model/vo/User.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/model/vo/User.java deleted file mode 100644 index 32ffa8b..0000000 --- a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/model/vo/User.java +++ /dev/null @@ -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; - -} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/model/vo/user/UserLoginReqVO.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/model/vo/user/UserLoginReqVO.java new file mode 100644 index 0000000..5471da7 --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/model/vo/user/UserLoginReqVO.java @@ -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; +} diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/service/UserService.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/service/UserService.java new file mode 100644 index 0000000..c1041ea --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/service/UserService.java @@ -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 { + + /** + * 登录或注册 + * + * @param userLoginReqVO 登录或注册参数 + * @return 登录结果 + */ + Response loginOrRegister(UserLoginReqVO userLoginReqVO); +} + diff --git a/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/service/impl/UserServiceImpl.java b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..6e90d5e --- /dev/null +++ b/xiaoyi-auth/src/main/java/top/crushtj/xiaoyishu/auth/service/impl/UserServiceImpl.java @@ -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 implements UserService { + @Resource + private UserMapper userMapper; + @Resource + private RedisTemplate redisTemplate; + + @Override + public Response 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(""); + } +} + diff --git a/xiaoyi-auth/src/main/resources/scripts/initData.sql b/xiaoyi-auth/src/main/resources/scripts/initData.sql new file mode 100644 index 0000000..19115a3 --- /dev/null +++ b/xiaoyi-auth/src/main/resources/scripts/initData.sql @@ -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'); + diff --git a/xiaoyi-auth/src/test/java/top/crushtj/xiaoyishu/auth/XiaoyiAuthApplicationTests.java b/xiaoyi-auth/src/test/java/top/crushtj/xiaoyishu/auth/XiaoyiAuthApplicationTests.java deleted file mode 100644 index 6b2885b..0000000 --- a/xiaoyi-auth/src/test/java/top/crushtj/xiaoyishu/auth/XiaoyiAuthApplicationTests.java +++ /dev/null @@ -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 queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(UserEntity::getUsername, "刑加一"); - queryWrapper.orderByDesc(UserEntity::getCreateTime); - queryWrapper.last("limit 1"); - UserEntity user = userMapper.selectOne(queryWrapper); - log.info("查询结果:{}", user); - } - -} diff --git a/xiaoyi-framework/xiaoyi-common/src/main/java/top/crushtj/framework/common/enums/DeleteEnum.java b/xiaoyi-framework/xiaoyi-common/src/main/java/top/crushtj/framework/common/enums/DeleteEnum.java new file mode 100644 index 0000000..7e63eb4 --- /dev/null +++ b/xiaoyi-framework/xiaoyi-common/src/main/java/top/crushtj/framework/common/enums/DeleteEnum.java @@ -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; +} diff --git a/xiaoyi-framework/xiaoyi-common/src/main/java/top/crushtj/framework/common/enums/StatusEnum.java b/xiaoyi-framework/xiaoyi-common/src/main/java/top/crushtj/framework/common/enums/StatusEnum.java new file mode 100644 index 0000000..2182667 --- /dev/null +++ b/xiaoyi-framework/xiaoyi-common/src/main/java/top/crushtj/framework/common/enums/StatusEnum.java @@ -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; +}