diff --git a/chaos_api_common/pom.xml b/chaos_api_common/pom.xml
index 7f56791..155cd5d 100644
--- a/chaos_api_common/pom.xml
+++ b/chaos_api_common/pom.xml
@@ -29,5 +29,21 @@
com.alibaba.fastjson2
fastjson2
+
+ org.springframework
+ spring-context
+ compile
+
+
+ cn.nopj
+ chaos_api_domain
+ 1.0-SNAPSHOT
+ compile
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
\ No newline at end of file
diff --git a/chaos_api_common/src/main/java/cn/nopj/chaos_api/common/constants/ErrorCode.java b/chaos_api_common/src/main/java/cn/nopj/chaos_api/common/constants/ErrorCode.java
new file mode 100644
index 0000000..1c2b0fd
--- /dev/null
+++ b/chaos_api_common/src/main/java/cn/nopj/chaos_api/common/constants/ErrorCode.java
@@ -0,0 +1,54 @@
+package cn.nopj.chaos_api.common.constants;
+
+import lombok.Getter;
+
+/**
+ * 全局错误码枚举(HTTP状态码 + 业务错误码)
+ * 规范:
+ * - 4xx: 客户端错误
+ * - 5xx: 服务端错误
+ * - 业务码分段:
+ * 100-199: 用户相关
+ * 200-299: 帖子/评论相关
+ * 300-399: 系统/第三方服务
+ */
+@Getter
+public enum ErrorCode {
+ // ================== 用户相关 (100-199) ==================
+ USERNAME_EXISTS(409, "USER-101", "用户名已存在"),
+ USERNAME_FORMAT_ERROR(400, "USER-102", "用户名需5-20位字母数字组合"),
+ USERNAME_PATTERN_INVALID( 400, "USER-103" , "用户名格式无效,必须由字母、数字、下划线" ),
+ PASSWORD_FORMAT_ERROR(400, "USER-104", "密码需6-20位字符组合"),
+ USER_NOT_EXISTS(404, "USER-104", "用户不存在"),
+ USER_ID_INVALID(400, "USER-105", "用户ID无效"),
+ USER_NOT_LOGIN(401, "USER-105", "请先登录"),
+ USER_BANNED(403, "USER-106", "账号已被封禁"),
+ EMAIL_EXISTS(409, "USER-107", "邮箱已注册"),
+ EMAIL_FORMAT_ERROR(400, "USER-108", "邮箱格式无效"),
+ PHONE_EXISTS(409, "USER-109", "手机号已注册"),
+ PHONE_FORMAT_ERROR(400, "USER-110", "手机号格式无效"),
+
+ // ================== 论坛内容相关 (200-299) ==================
+ POST_NOT_FOUND(404, "POST-201", "帖子不存在"),
+ POST_DELETED(410, "POST-202", "帖子已被删除"),
+ POST_TITLE_EMPTY(400, "POST-203", "标题不能为空"),
+ POST_CONTENT_EMPTY(400, "POST-204", "内容不能为空"),
+ COMMENT_NOT_FOUND(404, "POST-205", "评论不存在"),
+ COMMENT_TOO_LONG(400, "POST-206", "评论超过500字限制"),
+
+ // ================== 系统/第三方 (300-399) ==================
+ CAPTCHA_ERROR(400, "SYS-301", "验证码错误"),
+ SMS_SEND_FAILED(500, "SYS-302", "短信发送失败"),
+ FILE_UPLOAD_FAILED(500, "SYS-303", "文件上传失败"),
+ RATE_LIMIT_EXCEEDED(429, "SYS-304", "操作过于频繁"), ;
+
+ private final int httpStatus;
+ private final String code; // 业务错误码(领域-编号)
+ private final String message;
+
+ ErrorCode(int httpStatus, String code, String message) {
+ this.httpStatus = httpStatus;
+ this.code = code;
+ this.message = message;
+ }
+}
\ No newline at end of file
diff --git a/chaos_api_common/src/main/java/cn/nopj/chaos_api/common/exceotion/BizException.java b/chaos_api_common/src/main/java/cn/nopj/chaos_api/common/exceotion/BizException.java
new file mode 100644
index 0000000..3528d24
--- /dev/null
+++ b/chaos_api_common/src/main/java/cn/nopj/chaos_api/common/exceotion/BizException.java
@@ -0,0 +1,14 @@
+package cn.nopj.chaos_api.common.exceotion;
+
+import cn.nopj.chaos_api.common.constants.ErrorCode;
+import lombok.Getter;
+
+@Getter
+public class BizException extends RuntimeException{
+ public final ErrorCode errorCode;
+
+ public BizException(ErrorCode errorCode) {
+ super(errorCode.getMessage());
+ this.errorCode = errorCode;
+ }
+}
diff --git a/chaos_api_common/src/main/java/cn/nopj/chaos_api/converter/UserConverter.java b/chaos_api_common/src/main/java/cn/nopj/chaos_api/converter/UserConverter.java
new file mode 100644
index 0000000..99deed4
--- /dev/null
+++ b/chaos_api_common/src/main/java/cn/nopj/chaos_api/converter/UserConverter.java
@@ -0,0 +1,22 @@
+package cn.nopj.chaos_api.converter;
+
+
+import cn.nopj.chaos_api.domain.entity.User;
+import cn.nopj.chaos_api.dto.request.AuthRegisterRequest;
+import org.springframework.stereotype.Component;
+
+@Component
+public class UserConverter {
+ public User convert(AuthRegisterRequest request){
+ User user = new User();
+ user.setUsername(request.getUsername());
+ user.setPassword(request.getPassword());
+ user.setEnabled(true);
+ user.setAccountNonExpired(true);
+ user.setCredentialsNonExpired(true);
+ user.setAccountNonLocked(true);
+ user.setCreateTime(java.time.LocalDateTime.now());
+ user.setUpdateTime(java.time.LocalDateTime.now());
+ return user;
+ }
+}
diff --git a/chaos_api_data/src/main/java/cn/nopj/chaos_api/mapper/UserMapper.java b/chaos_api_data/src/main/java/cn/nopj/chaos_api/mapper/UserMapper.java
index 3322d0e..da780ae 100644
--- a/chaos_api_data/src/main/java/cn/nopj/chaos_api/mapper/UserMapper.java
+++ b/chaos_api_data/src/main/java/cn/nopj/chaos_api/mapper/UserMapper.java
@@ -1,10 +1,9 @@
package cn.nopj.chaos_api.mapper;
+import cn.nopj.chaos_api.domain.entity.Role;
import cn.nopj.chaos_api.domain.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.*;
import java.util.List;
@@ -37,4 +36,51 @@ public interface UserMapper extends BaseMapper {
*/
@Select("INSERT INTO t_user_role (user_id, role_id) VALUES (#{userId}, #{roleId})")
void insertUserRole(@Param("userId") Long id, @Param("roleId") Long i);
+
+ /**
+ * 根据用户名查询用户信息
+ * @param username 用户名
+ */
+ @Select("SELECT * FROM t_user WHERE username = #{username}")
+ User selectByUsername(String username);
+
+
+
+ /**
+ * 根据用户ID查询用户信息和角色信息
+ */
+ @Select("SELECT * FROM t_user WHERE id = #{id}")
+ @Results({
+ @Result(property = "roles", column = "id",
+ many = @Many(select = "findRolesByUserId"))
+ })
+ User findUserWithRoles(Long id);
+
+
+ /**
+ * 查询所有用户信息
+ * @return 所有用户信息
+ **/
+ @Select("""
+ SELECT * FROM t_user
+ """)
+ @Results({
+ @Result(id = true, property = "id", column = "id"),
+ @Result(property = "username", column = "username"),
+ @Result(property = "roles", column = "id",
+ many = @Many(select = "findRolesByUserId"))
+ })
+ List findAllUserWithRoles();
+
+
+ /**
+ * 根据用户ID查询角色信息
+ */
+ @Select("""
+ SELECT r.id, r.name ,r.code
+ FROM t_role r
+ JOIN t_user_role ur ON r.id = ur.role_id
+ WHERE ur.user_id = #{userId}
+ """)
+ List findRolesByUserId(@Param("userId") Long userId);
}
diff --git a/chaos_api_domain/pom.xml b/chaos_api_domain/pom.xml
index b503960..9b837d9 100644
--- a/chaos_api_domain/pom.xml
+++ b/chaos_api_domain/pom.xml
@@ -20,6 +20,10 @@
UTF-8
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
com.baomidou
mybatis-plus
@@ -29,5 +33,11 @@
lombok
provided
+
+ jakarta.validation
+ jakarta.validation-api
+ 3.0.2
+ compile
+
\ No newline at end of file
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/domain/entity/User.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/domain/entity/User.java
index 4bf12d8..fe4a36a 100644
--- a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/domain/entity/User.java
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/domain/entity/User.java
@@ -1,21 +1,57 @@
package cn.nopj.chaos_api.domain.entity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
+import java.util.List;
+
@Data
@TableName("t_user")
public class User implements Serializable {
+ /**
+ * 用户id
+ */
+ @TableId
private Long id;
+ /**
+ * 用户名称
+ */
private String username;
+ /**
+ * 密码
+ */
private String password;
+ /**
+ * 账号是否启用
+ */
private Boolean enabled;
+ /**
+ * 账号是否未过期
+ */
private Boolean accountNonExpired;
+ /**
+ * 密码是否未过期
+ */
private Boolean credentialsNonExpired;
+ /**
+ * 账号是否未锁定
+ */
private Boolean accountNonLocked;
+ /**
+ * 创建时间
+ */
private LocalDateTime createTime;
+ /**
+ * 更新时间
+ */
private LocalDateTime updateTime;
+
+ @TableField(exist = false)
+ private List roles;
}
+
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/LoginRequest.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/LoginRequest.java
deleted file mode 100644
index 76aa1ea..0000000
--- a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/LoginRequest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package cn.nopj.chaos_api.dto;
-
-import lombok.Data;
-
-/**
- * 登录请求参数
- */
-@Data
-public class LoginRequest {
- private String username;
- private String password;
-}
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/RegisterRequest.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/RegisterRequest.java
deleted file mode 100644
index b1f401d..0000000
--- a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/RegisterRequest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package cn.nopj.chaos_api.dto;
-
-import lombok.Data;
-
-/**
- * 注册请求参数
- */
-@Data
-public class RegisterRequest {
- private String username;
- private String password;
-}
\ No newline at end of file
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/AuthLoginRequest.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/AuthLoginRequest.java
new file mode 100644
index 0000000..f5bd646
--- /dev/null
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/AuthLoginRequest.java
@@ -0,0 +1,15 @@
+package cn.nopj.chaos_api.dto.request;
+
+import jakarta.validation.constraints.Pattern;
+import lombok.Data;
+
+/**
+ * 登录请求参数
+ */
+@Data
+public class AuthLoginRequest {
+ @Pattern(regexp = "^[a-zA-Z0-9_-]{5,16}$", message = "用户名需为5-16位字母、数字、_或-")
+ private String username;
+ @Pattern(regexp = "^.{8,16}$", message = "密码长度需为8-16位")
+ private String password;
+}
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/AuthRegisterRequest.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/AuthRegisterRequest.java
new file mode 100644
index 0000000..0c323d1
--- /dev/null
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/AuthRegisterRequest.java
@@ -0,0 +1,17 @@
+package cn.nopj.chaos_api.dto.request;
+
+
+import jakarta.validation.constraints.Pattern;
+import lombok.Data;
+
+/**
+ * 注册请求参数
+ */
+@Data
+public class AuthRegisterRequest {
+ @Pattern(regexp = "^[a-zA-Z0-9_-]{5,16}$", message = "用户名需为5-16位字母、数字、_或-")
+ private String username;
+ //密码不低于8位 不高于16位不限制字符
+ @Pattern(regexp = "^.{8,16}$", message = "密码长度需为8-16位")
+ private String password;
+}
\ No newline at end of file
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/SetUserPasswordRequest.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/SetUserPasswordRequest.java
new file mode 100644
index 0000000..78f7413
--- /dev/null
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/request/SetUserPasswordRequest.java
@@ -0,0 +1,13 @@
+package cn.nopj.chaos_api.dto.request;
+
+import jakarta.validation.constraints.Pattern;
+import lombok.Data;
+
+@Data
+public class SetUserPasswordRequest {
+ //用户id为数字Long类型
+ @Pattern(regexp = "^[0-9]+$", message = "用户id格式错误")
+ private String userId;
+ @Pattern(regexp = "^.{8,16}$", message = "密码长度需为8-16位")
+ private String password;
+}
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/FileUploadResponse.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/FileUploadResponse.java
similarity index 85%
rename from chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/FileUploadResponse.java
rename to chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/FileUploadResponse.java
index 501a252..af2c4a4 100644
--- a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/FileUploadResponse.java
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/FileUploadResponse.java
@@ -1,4 +1,4 @@
-package cn.nopj.chaos_api.dto;
+package cn.nopj.chaos_api.dto.response;
import lombok.Data;
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/RoleResponse.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/RoleResponse.java
new file mode 100644
index 0000000..27c5738
--- /dev/null
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/RoleResponse.java
@@ -0,0 +1,8 @@
+package cn.nopj.chaos_api.dto.response;
+
+import lombok.Data;
+@Data
+public class RoleResponse {
+ private Long id;
+ private String name;
+}
diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserinfoResponse.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserinfoResponse.java
new file mode 100644
index 0000000..2660584
--- /dev/null
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserinfoResponse.java
@@ -0,0 +1,12 @@
+package cn.nopj.chaos_api.dto.response;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class UserinfoResponse {
+ private Long id;
+ private String username;
+ private List roles;
+}
diff --git a/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java
index 192405e..cbd6e7e 100644
--- a/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java
+++ b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java
@@ -1,6 +1,8 @@
package cn.nopj.chaos_api.service;
+import cn.nopj.chaos_api.dto.response.FileUploadResponse;
+
import java.io.InputStream;
public interface ImageService {
@@ -11,5 +13,5 @@ public interface ImageService {
* @param content 文件内容
* @return 文件路径
*/
- String uploadImage(String fileName, InputStream content);
+ FileUploadResponse uploadImage(String fileName, InputStream content);
}
diff --git a/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserInfoService.java b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserInfoService.java
new file mode 100644
index 0000000..4b6ebc2
--- /dev/null
+++ b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserInfoService.java
@@ -0,0 +1,37 @@
+package cn.nopj.chaos_api.service;
+
+import cn.nopj.chaos_api.dto.response.UserinfoResponse;
+import jakarta.validation.constraints.Pattern;
+
+import java.util.List;
+
+/**
+ * 用户信息服务
+ *
+ * @author nopj
+ */
+public interface UserInfoService {
+
+ /**
+ * 设置用户密码
+ *
+ * @param id 用户id
+ * @param password 密码
+ */
+ void setUserPassword(Long id, String password);
+
+ /**
+ * 获取所有用户信息
+ *
+ * @return 所有用户信息
+ */
+ List getAllUsers();
+
+ /**
+ * 设置用户密码
+ *
+ * @param userId 用户id
+ * @param password 密码
+ */
+ void setUserPassword(@Pattern(regexp = "^[0-9]+$", message = "用户id格式错误") String userId, @Pattern(regexp = "^.{8,16}$", message = "密码长度需为8-16位") String password);
+}
diff --git a/chaos_api_service/pom.xml b/chaos_api_service/pom.xml
index 3f228a8..3643d62 100644
--- a/chaos_api_service/pom.xml
+++ b/chaos_api_service/pom.xml
@@ -50,5 +50,12 @@
spring-web
compile
+
+ org.springframework.security
+ spring-security-crypto
+ 6.5.6
+ compile
+
+
\ No newline at end of file
diff --git a/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java
index abf5924..d15fd0b 100644
--- a/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java
+++ b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java
@@ -1,5 +1,6 @@
package cn.nopj.chaos_api.service.impl;
+import cn.nopj.chaos_api.dto.response.FileUploadResponse;
import cn.nopj.chaos_api.service.ImageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -10,8 +11,8 @@ import java.io.InputStream;
@Service
public class ImageServiceImpl implements ImageService {
@Override
- public String uploadImage(String fileName, InputStream content) {
+ public FileUploadResponse uploadImage(String fileName, InputStream content) {
//todo 完成上传图片功能
- return "";
+ return new FileUploadResponse();
}
}
diff --git a/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserInfoServiceImpl.java b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserInfoServiceImpl.java
new file mode 100644
index 0000000..e0058ad
--- /dev/null
+++ b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserInfoServiceImpl.java
@@ -0,0 +1,75 @@
+package cn.nopj.chaos_api.service.impl;
+
+import cn.nopj.chaos_api.common.constants.ErrorCode;
+import cn.nopj.chaos_api.common.exceotion.BizException;
+import cn.nopj.chaos_api.domain.entity.User;
+import cn.nopj.chaos_api.dto.response.RoleResponse;
+import cn.nopj.chaos_api.dto.response.UserinfoResponse;
+import cn.nopj.chaos_api.mapper.UserMapper;
+import cn.nopj.chaos_api.service.UserInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Service
+public class UserInfoServiceImpl implements UserInfoService {
+ @Autowired
+ private PasswordEncoder passwordEncoder;
+ @Autowired
+ UserMapper userMapper;
+ @Override
+ public void setUserPassword(Long Id, String password) {
+
+ log.info("重置用户id: {}的密码", Id);
+ User user = userMapper.selectById(Id);
+ //查询用户是否存在
+
+ if (user == null) {
+ throw new BizException(ErrorCode.USER_NOT_EXISTS);
+ }
+ user.setPassword(passwordEncoder.encode(password));
+ int i = userMapper.updateById(user);
+ log.info("重置用户id: {}的密码结果: {}", Id, i);
+
+ }
+
+ @Override
+ public List getAllUsers() {
+ List allUserWithRoles = userMapper.findAllUserWithRoles();
+
+ if (allUserWithRoles == null){
+ throw new RuntimeException("获取所有用户信息失败");
+ }
+
+ return allUserWithRoles.stream().map(user -> {
+ UserinfoResponse userinfoResponse = new UserinfoResponse();
+ userinfoResponse.setId(user.getId());
+ userinfoResponse.setUsername(user.getUsername());
+ userinfoResponse.setRoles(
+ user.getRoles().stream().map(role -> {
+ RoleResponse roleResponse = new RoleResponse();
+ roleResponse.setId(role.getId());
+ roleResponse.setName(role.getName());
+ return roleResponse;
+ }).toList()
+ );
+ return userinfoResponse;
+ }).toList();
+ }
+
+ @Override
+ public void setUserPassword(String userId, String password) {
+ try{
+ Long Id = Long.parseLong(userId);
+ setUserPassword(Id, password);
+ }catch (NumberFormatException e) {
+ throw new BizException(ErrorCode.USER_ID_INVALID);
+ }
+ }
+
+
+}
diff --git a/chaos_api_web/pom.xml b/chaos_api_web/pom.xml
index 9eefc1e..5bae1e0 100644
--- a/chaos_api_web/pom.xml
+++ b/chaos_api_web/pom.xml
@@ -44,7 +44,6 @@
org.springframework.boot
spring-boot-starter-web
-
org.springframework.boot
@@ -69,7 +68,6 @@
provided
-
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/ChaosApiWebApplication.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/ChaosApiWebApplication.java
index d600772..371539c 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/ChaosApiWebApplication.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/ChaosApiWebApplication.java
@@ -1,9 +1,11 @@
package cn.nopj.chaos_api;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "cn.nopj.chaos_api")
+@Slf4j
public class ChaosApiWebApplication {
public static void main(String[] args) {
SpringApplication.run(ChaosApiWebApplication.class, args);
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java
index 363bcbe..b82542c 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java
@@ -38,10 +38,8 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
- log.info("JWT 登录授权过滤器");
String authHeader = request.getHeader(this.tokenHeader);
- log.info("authHeader: {}", authHeader);
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
String authToken = authHeader.substring(this.tokenHead.length()+1);
log.info("authToken={}", authToken);
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/AuthController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/AuthController.java
index 975ec55..83d6118 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/AuthController.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/AuthController.java
@@ -1,12 +1,13 @@
package cn.nopj.chaos_api.controller;
-import cn.nopj.chaos_api.dto.LoginRequest;
-import cn.nopj.chaos_api.dto.RegisterRequest;
+import cn.nopj.chaos_api.converter.UserConverter;
+import cn.nopj.chaos_api.dto.request.AuthLoginRequest;
+import cn.nopj.chaos_api.dto.request.AuthRegisterRequest;
import cn.nopj.chaos_api.model.ApiResult;
import cn.nopj.chaos_api.service.AuthService;
+import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -15,6 +16,11 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
+
+/**
+ * 认证控管理
+ *
+ */
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@@ -24,38 +30,34 @@ public class AuthController {
@Value("${jwt.tokenHead}")
private String tokenHead;
+ @Autowired
+ private UserConverter userConverter;
/**
* 注册
*
- * @param registerRequest 注册信息
+ * @param authRegisterRequest 注册信息
* @return 注册结果
*/
@PostMapping("/register")
- public ApiResult> register(@RequestBody RegisterRequest registerRequest) {
- if (authService.register(registerRequest) != null) {
- return ApiResult.success("注册成功");
- }
- return ApiResult.failed("用户名已存在");
+ public ApiResult> register(@Valid @RequestBody AuthRegisterRequest authRegisterRequest) {
+ return ApiResult.success(authService.register(userConverter.convert(authRegisterRequest)));
}
/**
* 登录
*
- * @param loginRequest 登录信息
+ * @param authLoginRequest 登录信息
* @return 登录结果
*/
@PostMapping("/login")
- public ApiResult> login(@RequestBody LoginRequest loginRequest) {
- try {
- String token = authService.login(loginRequest.getUsername(), loginRequest.getPassword());
+ public ApiResult> login(@RequestBody AuthLoginRequest authLoginRequest) {
- Map tokenMap = new HashMap<>();
- tokenMap.put("token", token);
- tokenMap.put("tokenHead", tokenHead);
- return ApiResult.success(tokenMap);
+ String token = authService.login(authLoginRequest.getUsername(), authLoginRequest.getPassword());
+
+ Map tokenMap = new HashMap<>();
+ tokenMap.put("token", token);
+ tokenMap.put("tokenHead", tokenHead);
+ return ApiResult.success(tokenMap);
- }catch (BadCredentialsException e){
- return ApiResult.failed(e.getMessage());
- }
}
}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/HLSController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/HLSController.java
deleted file mode 100644
index 8515fd9..0000000
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/HLSController.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package cn.nopj.chaos_api.controller;
-
-import cn.nopj.chaos_api.model.ApiResult;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@Slf4j
-@RestController
-@RequestMapping("/api/hls")
-public class HLSController {
-
- @PreAuthorize("hasAuthority('admin')")
- @GetMapping("/")
- ApiResult getHLS(){
- return ApiResult.success("HLS is radar");
- }
-}
\ No newline at end of file
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java
index bb06729..eaa84d8 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java
@@ -1,5 +1,6 @@
package cn.nopj.chaos_api.controller;
+import cn.nopj.chaos_api.dto.response.FileUploadResponse;
import cn.nopj.chaos_api.model.ApiResult;
import cn.nopj.chaos_api.service.ImageService;
import lombok.extern.slf4j.Slf4j;
@@ -9,6 +10,12 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 图片管理
+ */
@Slf4j
@RestController
@RequestMapping("/api/image")
@@ -16,9 +23,24 @@ public class ImageController {
@Autowired
private ImageService imageService;
+ /**
+ * 上传图片
+ * @param file 文件
+ * @return 上传结果
+ */
@RequestMapping("/upload")
ApiResult uploadImage(@RequestParam("file") MultipartFile file) {
- log.info("上传图片");
- return ApiResult.success("上传成功");
+ if (file.isEmpty()){
+ return ApiResult.failed("上传文件不能为空");
+ }
+ try {
+ String fileName = file.getName();
+ InputStream inputStream = file.getInputStream();
+ FileUploadResponse response = imageService.uploadImage(fileName, inputStream);
+ return ApiResult.success(response.getFileDownloadUri());
+ }catch (IOException e){
+ log.error("上传文件失败", e);
+ return ApiResult.failed("上传文件失败");
+ }
}
}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/RoleController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/RoleController.java
index 728e8af..969414b 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/RoleController.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/RoleController.java
@@ -5,6 +5,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
+/**
+ * 角色管理
+ */
@Slf4j
@RestController
public class RoleController {
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/UserController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/UserController.java
index 85a62ab..61ab936 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/UserController.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/UserController.java
@@ -1,13 +1,52 @@
package cn.nopj.chaos_api.controller;
-
+import cn.nopj.chaos_api.dto.request.SetUserPasswordRequest;
+import cn.nopj.chaos_api.dto.response.UserinfoResponse;
+import cn.nopj.chaos_api.model.ApiResult;
+import cn.nopj.chaos_api.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import java.util.List;
+/**
+ * 用户管理
+ *
+ * @author nopj
+ */
@Slf4j
@RestController
+@RequestMapping("/api/user")
public class UserController {
+ @Autowired
+ UserInfoService userInfoService;
+
+ /**
+ * 获取所有用户信息
+ * @return 所有用户信息
+ */
+ @PreAuthorize("hasAuthority('admin')")
+ @GetMapping("/all")
+ ApiResult> getAllUsers(){
+ return ApiResult.success(userInfoService.getAllUsers());
+ }
+
+ /**
+ * 设置用户密码
+ * @param request 设置用户密码请求
+ * @return 设置用户密码结果
+ */
+ @PreAuthorize("hasAuthority('admin')")
+ @RequestMapping("/setUserPassword")
+ ApiResult setUserPassword(@RequestBody SetUserPasswordRequest request){
+ userInfoService.setUserPassword(request.getUserId(), request.getPassword());
+ return ApiResult.success("用户密码修改成功");
+ }
}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/exception/GlobalExceptionHandler.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..085b00e
--- /dev/null
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/exception/GlobalExceptionHandler.java
@@ -0,0 +1,43 @@
+package cn.nopj.chaos_api.exception;
+
+import cn.nopj.chaos_api.common.exceotion.BizException;
+import cn.nopj.chaos_api.model.ApiResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.util.Objects;
+
+@Slf4j
+@RestControllerAdvice
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class GlobalExceptionHandler {
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ApiResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+ // 提取第一条错误提示
+ String errorMsg = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
+ // 返回统一的错误格式
+ return ApiResult.failed(errorMsg);
+ }
+
+ /**
+ * 处理自定义业务异常
+ */
+ @ExceptionHandler(BizException.class)
+ public ApiResult> handleBizException(BizException ex) {
+ return ApiResult.failed(ex.getErrorCode().getHttpStatus(),ex.getMessage());
+ }
+
+ /**
+ * 兜底处理:处理所有未知的 RuntimeException
+ * 防止出现 500 错误页面,给前端返回友好的提示
+ */
+ @ExceptionHandler(Exception.class)
+ public ApiResult> handleAllExceptions(Exception ex) {
+ log.error("服务器内部错误", ex);
+ return ApiResult.failed("服务器内部错误,请联系管理员");
+ }
+}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/AuthService.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/AuthService.java
index d94c502..4f4119d 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/AuthService.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/AuthService.java
@@ -1,13 +1,12 @@
package cn.nopj.chaos_api.service;
import cn.nopj.chaos_api.domain.entity.User;
-import cn.nopj.chaos_api.dto.RegisterRequest;
public interface AuthService {
/**
* 注册
*/
- User register(RegisterRequest registerRequest);
+ User register(User user);
/**
* 登录
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/AuthServiceImpl.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/AuthServiceImpl.java
index a66b6bf..d3e00b4 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/AuthServiceImpl.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/AuthServiceImpl.java
@@ -1,13 +1,13 @@
package cn.nopj.chaos_api.service.impl;
-
+import cn.nopj.chaos_api.common.constants.ErrorCode;
+import cn.nopj.chaos_api.common.exceotion.BizException;
import cn.nopj.chaos_api.domain.entity.User;
-import cn.nopj.chaos_api.dto.RegisterRequest;
import cn.nopj.chaos_api.mapper.UserMapper;
import cn.nopj.chaos_api.service.AuthService;
import cn.nopj.chaos_api.util.JwtTokenUtil;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -18,8 +18,9 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
+@Slf4j
public class AuthServiceImpl implements AuthService {
-
+
@Autowired
private UserMapper userMapper;
@@ -31,35 +32,45 @@ public class AuthServiceImpl implements AuthService {
private AuthenticationManager authenticationManager;
@Override
- public User register(RegisterRequest registerRequest) {
+ public User register(User user) {
+
// 检查用户名是否已存在
- if (userMapper.selectOne(new QueryWrapper().eq("username", registerRequest.getUsername())) != null) {
+ if (userMapper.selectByUsername(user.getUsername()) != null) {
// 在实际项目中,这里应该抛出自定义异常
- return null;
+ throw new BizException(ErrorCode.USERNAME_EXISTS);
}
- User user = new User();
- user.setUsername(registerRequest.getUsername());
// 使用 BCrypt 加密密码
- user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
+ user.setPassword(passwordEncoder.encode(user.getPassword()));
userMapper.insert(user);
// 你可以在这里为新用户分配默认角色
userMapper.insertUserRole(user.getId(), 2L);
+
return user;
}
@Override
public String login(String username, String password) {
+ // 尝试进行身份验证
+ try{
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password)
);
+
+ // 将认证结果保存在 SecurityContextHolder 中
+
SecurityContextHolder.getContext().setAuthentication(authentication);
// 获取用户详情
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
- if (!userDetails.isEnabled()){
+ if (!userDetails.isEnabled()) {
return null;
}
// 生成 JWT
return jwtTokenUtil.generateToken(userDetails);
+ }catch (Exception e){
+
+ throw new BizException(ErrorCode.USER_NOT_EXISTS);
+ }
+
}
}
\ No newline at end of file
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java
index aba8d0d..c7ab58d 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java
@@ -1,15 +1,16 @@
package cn.nopj.chaos_api.service.impl;
+import cn.nopj.chaos_api.common.constants.ErrorCode;
+import cn.nopj.chaos_api.common.exceotion.BizException;
import cn.nopj.chaos_api.domain.entity.User;
import cn.nopj.chaos_api.mapper.UserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -22,11 +23,11 @@ public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ public UserDetails loadUserByUsername(String username) {
// 1. 从数据库查询用户
User user = userMapper.selectOne(new QueryWrapper().eq("username", username));
if (user == null) {
- throw new UsernameNotFoundException("用户不存在");
+ throw new BizException(ErrorCode.USER_NOT_EXISTS);
}
// 2. 查询该用户的权限信息 (角色 + 权限)
@@ -38,6 +39,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
+
// 4. 构建并返回 Spring Security 的 User 对象
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
diff --git a/pom.xml b/pom.xml
index 5522f51..6a7bf69 100644
--- a/pom.xml
+++ b/pom.xml
@@ -119,6 +119,7 @@
logback-classic
1.5.18
+
org.springframework.boot
spring-boot-starter-amqp
@@ -130,6 +131,18 @@
spring-web
6.2.13
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ 3.5.7
+
+
+
+ org.springframework
+ spring-context
+ 6.2.13
+
\ No newline at end of file