定义 User 和 Record 接口 (#9)

* 登陆,注册,加上异常集中处理,mybatis和mybatisplus不兼容好像是

* 更新hutool依赖并移除mybatis-starter

此更改升级了hutool版本从5.8.11到5.8.26,并且移除了mybatis-spring-boot-starter依赖。这对于优化项目依赖和保持项目轻量级有好处。

* 数据库表名有点小问题

* 解决用户表映射问题以匹配实际数据库结构

之前,用户表列名在MyBatis映射中被错误地标注为`userId`和`group`,而数据库中的实际列名为`user_id`和`group`(无反引号)。此次更改通过在MyBatis注释中使用正确的列名来解决了该问题,确保了数据操作的正确执行。此外,还修正了选择语句中的列名,以确保查询能够正确执行并返回期望的结果。

* 不会测那个apifox有token怎么加进去啊

* 拦截器ok

* 允许接口文档目录的未登录访问
启用自动建表

* jwtUtils

* 权限校验1

* 管理员查看用户信息

* 816

* refactor(user): 简化控制器和实体类并调整注释格式

- 合并登录和注册请求模型,统一参数处理- 删除未使用的字段和导入语句,优化代码
-调整方法注释格式,提升可读性和一致性
- 实体类 `User` 移除 `name` 字段,避免冗余

BREAKING CHANGE: `User` 实体类移除 `name` 字段,可能影响依赖此字段的数据库查询。请确保更新相关代码以适应这一变更。

* feat(user): 完成User的接口

* feat(user): 完成Record的接口

---------

Co-authored-by: suyiiyii <suyiiyii@gmail.com>
This commit is contained in:
tortoise014 2024-08-16 01:44:20 +08:00 committed by GitHub
parent ce69219012
commit 038b7ebe8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 1073 additions and 27 deletions

View File

@ -10,7 +10,7 @@ Super Invincible Management System
5. git fetch origin && git merge origin/main: 拉取远程仓库的最新代码并合并到当前分支
6. git push origin xxx: 推送当前分支到远程仓库
7. 提 PR
8. require review: 请求review
8. require review: 请求reviewpush
9. merge: 合并 PR
10. delete: 删除分支

16
pom.xml
View File

@ -34,12 +34,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
@ -56,11 +50,21 @@
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -3,7 +3,8 @@ package top.suyiiyii.sims;
import com.tangzc.autotable.springboot.EnableAutoTable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/*@EnableAutoTable*/
@EnableAutoTable
@SpringBootApplication
public class SimsApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,24 @@
package top.suyiiyii.sims.VO;
import lombok.Data;
import top.suyiiyii.sims.entity.Role;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/15 16:04
* @PackageName:top.suyiiyii.sims.VO
* @ClassName: UserVO
* @Description: TODO
* @Version 1.0
*/
@Data
public class UserVO {
private Integer userId;
private String username;
private String grade;
private String group;
private List<String> roles; // 角色名称列表
}

View File

@ -0,0 +1,17 @@
package top.suyiiyii.sims.common;
import java.lang.annotation.*;
/**
* @Author tortoise
* @Date 2024/8/12 11:26
* @PackageName:top.suyiiyii.sims.common
* @ClassName: AuthAccess
* @Description: TODO
* @Version 1.0
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthAccess {
}

View File

@ -0,0 +1,35 @@
package top.suyiiyii.sims.common;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* @Author tortoise
* @Date 2024/8/12 11:27
* @PackageName:top.suyiiyii.sims.common
* @ClassName: InterceptorConfig
* @Description: TODO 拦截器配置
* @Version 1.0
*/
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(jwtInterceptor())
// .addPathPatterns("/**")
// .excludePathPatterns("/user/login") // 排除不需要验证的路径
// .excludePathPatterns("/user/register")
// .excludePathPatterns("/v3/api-docs/**");
super.addInterceptors(registry);
}
@Bean
public JwtInterceptor jwtInterceptor() {
return new JwtInterceptor();
}
}

View File

@ -0,0 +1,70 @@
package top.suyiiyii.sims.common;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.exception.ServiceException;
import top.suyiiyii.sims.mapper.UserMapper;
import top.suyiiyii.sims.utils.JwtUtils;
/**
* @Author tortoise
* @Date 2024/8/12 11:33
* @PackageName:top.suyiiyii.sims.common
* @ClassName: JwtInterceptor
* @Description: TODO
* @Version 1.0
*/
public class JwtInterceptor implements HandlerInterceptor {
@Resource
UserMapper userMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Authorization 头中获取 token
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
// 去除 "Bearer " 前缀
} else {
// 如果 Authorization 头中没有 token则尝试从请求参数中获取
token = request.getParameter("token");
}
// 如果不是映射到方法直接通过
if (handler instanceof HandlerMethod) {
AuthAccess annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthAccess.class);
if (annotation != null) {
return true;
}
}
// request.setAttribute();
// request.getAttribute()
// 执行认证
if (StrUtil.isBlank(token)) {
//权限错误
throw new ServiceException("401", "请登录");
}
// 获取 token 中的 user id
String userId= JwtUtils.extractUserId(token);
if (userId == null) {
throw new ServiceException("401", "请登录");
}
User user = userMapper.selectById(Integer.parseInt(userId));
if (user == null) {
throw new ServiceException("401", "请登录");
}
// 验证 token 的有效性
if (!JwtUtils.verifyToken(token, user.getPassword())) {
throw new ServiceException("401", "请登录");
}
return true;
}
}

View File

@ -0,0 +1,54 @@
package top.suyiiyii.sims.common;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import top.suyiiyii.sims.dto.CommonResponse;
/**
* @Author tortoise
* @Date 2024/8/10 21:18
* @PackageName:top.suyiiyii.sims.common
* @ClassName: Result
* @Description: 泛型结果对象
* @Version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Result<T> { // 添加类型参数 T
public static final String CODE_SUCCESS = "200";
public static final String CODE_AUTH_ERROR = "401";
public static final String CODE_SYS_ERROR = "500";
private String code;
private String msg;
private T data; // Object 改为 T
public static <T> Result<T> success() { // 添加类型参数 T 并指定返回类型
return new Result<>(CODE_SUCCESS, "success", null);
}
public static <T> Result<T> success(T data) { // 添加类型参数 T 并指定返回类型
return new Result<>(CODE_SUCCESS, "success", data);
}
public static Result<CommonResponse> msg(String msg) {
return success(CommonResponse.factory(msg));
}
public static <T> Result<T> error(String msg) { // 添加类型参数 T 并指定返回类型
return new Result<>(CODE_SYS_ERROR, msg, null);
}
public static <T> Result<T> error(String code, String msg) { // 添加类型参数 T 并指定返回类型
return new Result<>(code, msg, null);
}
public static <T> Result<T> authError(String msg) { // 添加类型参数 T 并指定返回类型
return new Result<>(CODE_AUTH_ERROR, "认证错误", null);
}
}

View File

@ -0,0 +1,47 @@
package top.suyiiyii.sims.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.suyiiyii.sims.common.Result;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.service.RoleService;
import top.suyiiyii.sims.service.UserService;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/14 13:57
* @PackageName:top.suyiiyii.sims.controller
* @ClassName: AdminController
* @Description: TODO
* @Version 1.0
*/
@RestController
@RequestMapping("/admin")
public class AdminController {
@Autowired
private RoleService roleService;
@Autowired
private UserService userService;
@GetMapping("/findAllUsersWithRoles")
public Result findAllUsersWithRoles() {
List<User> userList = roleService.findAllUsersWithRoles();
return Result.success(userList);
}
@GetMapping("/selectAll")
public Result selectAll() {
List<User> users = userService.selectAll();
return Result.success(users);
}
}
/**
request.setAttribute();lUsers();
return Result.success(userList);
}
}
**/

View File

@ -3,6 +3,7 @@ package top.suyiiyii.sims.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import top.suyiiyii.sims.common.Result;
import java.util.List;
@ -18,5 +19,9 @@ public class HelloController {
List<String> list = List.of(username,age.toString());
return list;
}
@GetMapping("/helloResult")
public Result healthz() {
return Result.success("Hello World");
}
}

View File

@ -0,0 +1,45 @@
package top.suyiiyii.sims.controller;
import org.springframework.web.bind.annotation.*;
import top.suyiiyii.sims.common.Result;
import top.suyiiyii.sims.dto.CommonResponse;
import top.suyiiyii.sims.dto.RecordDto;
import java.util.ArrayList;
import java.util.List;
@RestController
public class RecordController {
@GetMapping("/admin/record")
public Result<List<RecordDto>> adminRecord(Integer page, Integer size) {
return Result.success(new ArrayList<>());
}
@GetMapping("/record")
public Result<List<RecordDto>> record(Integer page, Integer size) {
return Result.success(new ArrayList<>());
}
@PutMapping("/admin/record/{id}")
public Result<CommonResponse> adminUpdateRecord(@PathVariable Integer id, @RequestBody RecordDto recordDto) {
return Result.msg("修改成功");
}
@DeleteMapping("/admin/record/{id}")
public Result<CommonResponse> adminDeleteRecord(@PathVariable Integer id) {
return Result.msg("删除成功");
}
@PostMapping("/admin/record")
public Result<CommonResponse> adminAddRecord(@RequestBody RecordDto recordDto) {
return Result.msg("添加成功");
}
}

View File

@ -0,0 +1,109 @@
package top.suyiiyii.sims.controller;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import top.suyiiyii.sims.common.AuthAccess;
import top.suyiiyii.sims.common.Result;
import top.suyiiyii.sims.dto.CommonResponse;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.exception.ServiceException;
import top.suyiiyii.sims.service.RoleService;
import top.suyiiyii.sims.service.UserService;
/**
* @Author tortoise
* @Date 2024/8/10 22:25
* @PackageName:top.suyiiyii.sims.controller
* @ClassName: UserController
* @Description: TODO
* @Version 1.0
*/
@Slf4j
@RestController
//@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@Autowired
RoleService roleService;
@AuthAccess
@GetMapping("/")
public Result hello() {
return Result.success("success");
}
@PostMapping("/user/login")
public Result<LoginResponse> login(@RequestBody LoginRequest request) {
log.info("login request:{}", request);
if (StrUtil.isBlank(request.getUsername()) || StrUtil.isBlank(request.getPassword())) {
return Result.error("用户名或密码不能为空");
}
User user = userService.login(request.getUsername(), request.getPassword());
return Result.success(new LoginResponse());
}
@PostMapping("/user/register")
public Result<CommonResponse> register(@RequestBody RegisterRequest request) {
log.info("register request:{}", request);
if (StrUtil.isBlank(request.getUsername()) || StrUtil.isBlank(request.getPassword())) {
return Result.error("用户名或密码不能为空");
}
if (request.getPassword() == null || request.getPassword().length() < 3) {
throw new ServiceException("密码长度不能小于3位");
}
userService.register(new User());
return Result.success(CommonResponse.factory("注册成功"));
}
@DeleteMapping("/admin/user/{id}")
public Result<CommonResponse> adminDelete(@PathVariable Integer id) {
log.info("delete request:{}", id);
// userService.deleteUser(user.getId());
return Result.success(CommonResponse.factory("删除成功"));
}
@GetMapping("/admin/user/{id}")
public Result<User> adminGetById(@PathVariable Integer id) {
log.info("selectById request:{}", id);
User user = userService.selectById(id);
return Result.success(user);
}
@Data
public static class RegisterRequest {
private String username;
private String password;
private String email;
private String grade;
private String group;
}
@Data
public static class LoginRequest {
public String username;
public String password;
}
@Data
public static class LoginResponse {
public String token;
}
}

View File

@ -0,0 +1,16 @@
package top.suyiiyii.sims.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CommonResponse {
String message;
public static CommonResponse factory(String message) {
return new CommonResponse(message);
}
}

View File

@ -0,0 +1,42 @@
package top.suyiiyii.sims.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RecordDto {
private Integer id;
// 用户ID
private Integer userId;
// 奖惩类型
private String type;
// 奖惩类别ID
private Integer categoryId;
// 奖惩日期
private LocalDateTime date;
// 奖惩内容
private String content;
// 奖惩原因
private String reason;
// 奖惩金额
private Double amount;
// 奖惩备注
private String remark;
// 是否撤销
private Boolean isRevoked;
// 撤销日期
private LocalDateTime revokeDate;
// 撤销原因
private String revokeReason;
// 撤销备注
private String revokeRemark;
// 操作人ID
private Integer operatorUserId;
// 最近一次更新时间
private LocalDateTime lastUpdateTime;
}

View File

@ -0,0 +1,21 @@
package top.suyiiyii.sims.dto;
import lombok.Data;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/15 15:36
* @PackageName:top.suyiiyii.sims.dto
* @ClassName: UserDto
* @Description: TODO
* @Version 1.0
*/
@Data
public class UserDto {
private Long userId;
private String username;
private List<String> roles; // 角色名称列表
private List<String> permissions; // 权限列表
}

View File

@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author tortoise
@ -16,7 +18,10 @@ import lombok.Data;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class Attachment {
@TableId("id")
private Integer id;
private Integer recordId;
// 文件路径

View File

@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author tortoise
@ -16,8 +18,10 @@ import lombok.Data;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class HierarchyRelation {
@TableId("id")
private Integer id;
// 上级用户ID

View File

@ -1,7 +1,10 @@
package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@ -15,7 +18,10 @@ import java.time.LocalDateTime;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class Notification {
@TableId("id")
private Integer id;
private String title;
private String content;

View File

@ -3,7 +3,11 @@ package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @Author tortoise
@ -15,12 +19,28 @@ import lombok.Data;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class Permissions {
@TableId("id")
private Integer id;
//权限id
private Integer permissionId;
private String path;
// 权限描述
private String description;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Permissions that = (Permissions) o;
return Objects.equals(path, that.path);
}
@Override
public int hashCode() {
return Objects.hash(path);
}
}

View File

@ -1,10 +1,10 @@
package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@ -12,14 +12,16 @@ import java.time.LocalDateTime;
* @Author tortoise
* @Date 2024/8/9 14:04
* @PackageName:top.suyiiyii.sims.entity
* @ClassName: RewardPunishmentRecord
* @ClassName: Record
* @Description: TODO
* @Version 1.0
*/
@Data
@Table
public class RewardPunishmentRecord {
@AllArgsConstructor
@NoArgsConstructor
public class Record {
@TableId("id")
private Integer id;
// 用户ID
private Integer userId;

View File

@ -1,7 +1,10 @@
package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@ -15,8 +18,10 @@ import java.time.LocalDateTime;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class RevokeRequest {
@TableId("id")
private Integer id;
private Integer recordId;
private Integer userId;

View File

@ -1,7 +1,10 @@
package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@ -15,8 +18,10 @@ import java.time.LocalDateTime;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class RevokedRecord {
@TableId("id")
private Integer id;
// 被撤销的奖惩记录ID
private Integer recordId;

View File

@ -3,7 +3,9 @@ package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author tortoise
@ -15,8 +17,10 @@ import lombok.Data;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class RewardPunishmentCategory {
@TableId("id")
private Integer id;
private Integer categoryId;

View File

@ -3,20 +3,24 @@ package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author tortoise
* @Date 2024/8/9 14:02
* @PackageName:top.suyiiyii.sims.entity
* @ClassName: Role
* @ClassName: RoleMapper
* @Description: TODO
* @Version 1.0
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class Role {
@TableId("id")
private Integer id;
private Integer roleId;
//管理员普通用户组员组长队长

View File

@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.security.Permission;
@ -18,8 +20,11 @@ import java.security.Permission;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class RolePermission {
private Integer rolePermissionId;
@TableId("id")
private Integer id;
private Integer roleId;
private Integer permissionId;
}

View File

@ -1,10 +1,13 @@
package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* @Author tortoise
@ -16,14 +19,19 @@ import lombok.Data;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId("id")
private Integer id;
private Integer userId;
private Integer studentId;
private String username;
private String password;
private String name;
private String email;
private String grade;
private String group;
@TableField(exist = false)
private String token;
@TableField(exist = false)
private Set<Permissions> permissions;
}

View File

@ -3,7 +3,9 @@ package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author tortoise
@ -15,8 +17,10 @@ import lombok.Data;
*/
@Data
@Table
@AllArgsConstructor
@NoArgsConstructor
public class UserRole {
@TableId("id")
private Integer id;
private Integer userId;
private Integer roleId;

View File

@ -0,0 +1,23 @@
package top.suyiiyii.sims.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import top.suyiiyii.sims.common.Result;
/**
* @Author tortoise
* @Date 2024/8/11 1:38
* @PackageName:top.suyiiyii.sims.exception
* @ClassName: GlobalException
* @Description: TODO
* @Version 1.0
*/
@ControllerAdvice
public class GlobalException {
@ExceptionHandler(ServiceException.class)
@ResponseBody
public Result ServiceException(ServiceException e){
return Result.error(e.getCode(),e.getMessage());
}
}

View File

@ -0,0 +1,25 @@
package top.suyiiyii.sims.exception;
import lombok.Getter;
/**
* @Author tortoise
* @Date 2024/8/11 1:38
* @PackageName:top.suyiiyii.sims.exception
* @ClassName: ServiceException
* @Description: TODO
* @Version 1.0
*/
@Getter
public class ServiceException extends RuntimeException{
public final String code;
public ServiceException(String msg){
super(msg);
this.code = "500";
}
public ServiceException(String code ,String msg){
super(msg);
this.code = code;
}
}

View File

@ -0,0 +1,25 @@
package top.suyiiyii.sims.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import top.suyiiyii.sims.entity.Permissions;
import top.suyiiyii.sims.entity.RolePermission;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/14 16:14
* @PackageName:top.suyiiyii.sims.mapper
* @ClassName: PermissionsMapper
* @Description: TODO
* @Version 1.0
*/
@Mapper
public interface PermissionsMapper {
@Select("SELECT * FROM role_permission WHERE role_id = #{id}")
List<RolePermission> getRolePerminsionByRoleId(Integer id);
@Select("SELECT * FROM permissions WHERE permission_id = #{permissionId}")
Permissions selectById(Integer permissionId);
}

View File

@ -0,0 +1,58 @@
package top.suyiiyii.sims.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import lombok.Data;
import org.apache.ibatis.annotations.*;
import top.suyiiyii.sims.entity.Permissions;
import top.suyiiyii.sims.entity.Role;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.entity.UserRole;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/14 14:13
* @PackageName:top.suyiiyii.sims.mapper
* @ClassName: RoleMapper
* @Description: TODO
* @Version 1.0
*/
@Mapper
public interface RoleMapper {
@Insert("INSERT INTO role(name) VALUES(#{name}")
void addRole(String name);
@Delete("DELETE FROM role WHERE name=#{name}")
void deleteRole(String name);
@Update("UPDATE role SET name=#{newName} WHERE name=#{name}")
void updateRole(String name, String newName);
/**
* @author: tortoise
* @date: 2024/8/14 14:23
* @Description: TODO 查询用户信息
* @param
* @return: java.util.List<top.suyiiyii.sims.entity.User>
*/
@Select("SELECT u.username, u.name, u.userId, r.role_name " +
"FROM user u " +
"LEFT JOIN user_role ur ON u.user_id = ur.user_id " +
"LEFT JOIN role r ON ur.role_id = r.role_id")
@Results({
@Result(property = "username", column = "username"),
@Result(property = "name", column = "name"),
@Result(property = "userId", column = "userId"),
@Result(property = "group", column = "group"),
@Result(property = "roles", column = "role_name", many = @Many(select = "selectRolesByUser"))
})
List<User> selectAllUsersWithRoles();
// 根据用户ID查询角色
@Select("SELECT role_id, role_name " +
"FROM role " +
"WHERE role_id IN " +
"(SELECT role_id FROM user_role WHERE user_id = #{user_id})")
List<UserRole> selectRolesById(@Param("user_id") int id);
@Select("SELECT role_name FROM role WHERE role_id=#{roleId}")
List<String> selectRoleNamesByRoleId(Integer roleId);
}

View File

@ -0,0 +1,77 @@
package top.suyiiyii.sims.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.*;
import top.suyiiyii.sims.entity.Role;
import top.suyiiyii.sims.entity.User;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/10 22:21
* @PackageName:top.suyiiyii.sims.mapper
* @ClassName: UserMapper
* @Description: TODO
* @Version 1.0
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
/**
* 添加新用户
* @param user 新用户对象
* @return 影响的行数
*/
@Insert("insert INTO user (id,user_id, username, password, name, email, `group`) VALUES (#{id},#{userId}, #{username}, #{password}, #{name}, #{email}, #{group})")
int addUser(User user);
/**
* 根据ID删除用户
* @param id 用户ID
* @return 影响的行数
*/
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteUser(Integer id);
/**
* 更新用户信息
* @param user 更新后的用户对象
* @return 影响的行数
*/
@Update("UPDATE user SET " +
"user_id = #{userId}, " +
"username = #{username}, " +
"name = #{name}, " +
"email = #{email}, " +
"`group` = #{group} " +
"WHERE id = #{id}")
int updateUser(User user);
/**
* 根据ID查询用户信息
* @param id 用户ID
* @return 用户对象
*/
@Select("SELECT id, user_id, username, password, name, email, `group` from user WHERE id = #{Id}")
User selectByUserId(Integer userId);
/**
* 根据iD查询用户信息
* @param
* @return 用户对象
*/
@Select("SELECT id, user_id, username, password, name, email, `group` from user WHERE id = #{Id}")
User selectById(Integer Id);
/**
* 查询所有用户信息
* @return 用户列表
*/
@Select("SELECT id, user_id, username, password, name, email,grade, `group` FROM user")
List<User> selectAll();
@Select("select * from user where username = #{username}")
User selectByUserName(@Param("username") String username);
@Update("update user set password = #{password} where username = #{username}")
void updatePassword(User user);
}

View File

@ -0,0 +1,49 @@
package top.suyiiyii.sims.service;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.suyiiyii.sims.entity.Role;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.entity.UserRole;
import top.suyiiyii.sims.mapper.RoleMapper;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/14 14:14
* @PackageName:top.suyiiyii.sims.service
* @ClassName: RoleService
* @Description: TODO
* @Version 1.0
*/
@Service
public class RoleService {
@Autowired
RoleMapper roleMapper;
public void addRole(String name){
roleMapper.addRole(name);
}
public void deleteRole(String name){
roleMapper.deleteRole(name);
}
public void updateRole(String name,String newName){
roleMapper.updateRole(name,newName);
}
public List<User> findAllUsersWithRoles(){
return roleMapper.selectAllUsersWithRoles();
}
/**
* @author: tortoise
* @date: 2024/8/14 14:39
* @Description: TODO 查看自己身份
* @param Id
* @return: java.util.List<top.suyiiyii.sims.entity.Role>
*/
List<UserRole> selectRolesById(int id){
return roleMapper.selectRolesById(id);
}
}

View File

@ -0,0 +1,142 @@
package top.suyiiyii.sims.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.suyiiyii.sims.VO.UserVO;
import top.suyiiyii.sims.entity.*;
import top.suyiiyii.sims.exception.ServiceException;
import top.suyiiyii.sims.mapper.PermissionsMapper;
import top.suyiiyii.sims.mapper.RoleMapper;
import top.suyiiyii.sims.mapper.UserMapper;
import top.suyiiyii.sims.utils.JwtUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* @Author tortoise
* @Date 2024/8/10 22:22
* @PackageName:top.suyiiyii.sims.service
* @ClassName: UserService
* @Description: TODO
* @Version 1.0
*/
@Service
public class UserService {
@Autowired
UserMapper userMapper;
@Autowired
RoleMapper roleMapper;
@Autowired
PermissionsMapper permissionsMapper;
public void addUser(User user) {
userMapper.addUser(user);
}
public User selectById(int id) {
return userMapper.selectById(id);
}
public void updateUser(User user) {
userMapper.updateUser(user);
}
public void deleteUser(int id) {
userMapper.deleteUser(id);
}
public List<User> selectAll() {
return userMapper.selectAll();
}
//TODO:返回一个DTO,用户基本信息
public User login(String username, String password) {
User dbUser = userMapper.selectByUserName(username);
if (dbUser == null) {
throw new ServiceException("账号不存在");
}
if (!dbUser.getPassword().equals(password)) {
throw new ServiceException("密码或用户名错误");
}
HashSet<Permissions> permissionsSet = new HashSet<>();
Integer id = dbUser.getId();
List<UserRole> UserRoles = roleMapper.selectRolesById(id);
for (UserRole userRole : UserRoles) {
//根据roleid找所有permissionId
List<RolePermission> rolePerminsion = permissionsMapper.getRolePerminsionByRoleId(userRole.getRoleId());
for (RolePermission rolePermission : rolePerminsion) {
Integer permissionId = rolePermission.getPermissionId();
//根据permissionId找permission
Permissions permissions = permissionsMapper.selectById(permissionId);
permissionsSet.add(permissions);
}
}
dbUser.setPermissions(permissionsSet);
String token = JwtUtils.createToken(dbUser.getId().toString(), dbUser.getPassword());
dbUser.setToken(token);
return dbUser;
}
public User register(User user) {
User dbUser = userMapper.selectByUserId(user.getStudentId());
if (user.getUsername() == null || user.getUsername().equals("")) {
throw new ServiceException("用户名不能为空");
}
if (dbUser != null) {
throw new ServiceException("账号已经存在");
}
if (user.getStudentId() == null || user.getStudentId().equals("")) {
throw new ServiceException("用户id不能为空");
}
if( user.getPassword() == null || user.getPassword().equals("")) {
throw new ServiceException("密码不能为空");
}
if (user.getEmail() == null || user.getEmail().equals("")) {
throw new ServiceException("邮箱不能为空");
}
if (user.getGroup() == null || user.getGroup().equals("")) {
throw new ServiceException("组别不能为空");
}
userMapper.addUser(user);
return user;
}
public User selectByUsername(String username) {
return userMapper.selectByUserName(username);
}
public void updatePassword(User user) {
userMapper.updatePassword(user);
}
public List<UserVO> findAllUsers(){
List<User> users = userMapper.selectAll();
List<UserVO> userVOS = new ArrayList<>();
for (User user : users) {
UserVO userVO = new UserVO();
userVO.setUserId(user.getId());
userVO.setUsername(user.getUsername());
userVO.setGrade(user.getGrade());
userVO.setGroup(user.getGroup());
userVO.setRoles(new ArrayList<>());
Integer id = user.getId();
List<UserRole> userRoles = roleMapper.selectRolesById(id);
for (UserRole userRole : userRoles) {
Integer roleId = userRole.getRoleId();
// 获取一个角色的名称列表
List<String> roleNameList = roleMapper.selectRoleNamesByRoleId(roleId);
// 累加角色名称到用户的角色列表中
userVO.getRoles().addAll(roleNameList);
}
userVOS.add(userVO);
}
return userVOS;
}
}

View File

@ -0,0 +1,85 @@
package top.suyiiyii.sims.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.mapper.UserMapper;
import java.util.Date;
/**
* @Author tortoise
* @Date 2024/8/12 11:44
* @PackageName:top.suyiiyii.sims.utils
* @ClassName: JwtUtils
* @Description: TODO
* @Version 1.0
*/
@Component
public class JwtUtils {
private static UserMapper staticUserMapper;
@Resource
UserMapper userMapper;
@PostConstruct
public void setUserService() {
staticUserMapper=userMapper;
}
/**
* @author: tortoise
* @date: 2024/8/1 15:12
* @Description: 生成token
* @param userId
* @param sign
* @return: java.lang.String
*/
public static String createToken(String userId, String sign) {
return JWT.create()
.withAudience(userId)
.withExpiresAt(DateUtil.offsetHour(new Date(), 2))
.sign(Algorithm.HMAC256(sign));
// 设置令牌过期时间为2小时
}
public static User getCurrentUser() {
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
if (StrUtil.isNotBlank(token)) {
String userId = JWT.decode(token).getAudience().get(0);
return staticUserMapper.selectById(Integer.valueOf(userId));
}
} catch (Exception e) {
return null;
}
return null;
}
// 验证 JWT 令牌
public static boolean verifyToken(String token, String secret) {
try {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(secret)).build(); // 创建 JWT 验证器
jwtVerifier.verify(token); // 验证令牌
return true;
} catch (JWTDecodeException e) {
// 处理异常或记录日志
return false;
}
}
public static String extractUserId(String token) {
try {
return JWT.decode(token).getAudience().get(0); // token 中提取用户ID
} catch (JWTDecodeException e) {
// 处理异常或记录日志
return null;
}
}
}