From a5a23a6b52af2b15eac0496f6821c08b28030c46 Mon Sep 17 00:00:00 2001 From: Chaos Date: Mon, 24 Nov 2025 17:10:01 +0800 Subject: [PATCH] feat(auth): add user profile to auth token response - Add jwt configuration in application.yaml - Include user profile information in authentication response - Implement user profile response DTO with role mapping - Fix typo in UserProfileService interface and implementation class names - Add pagination support for user list endpoint - Configure MyBatis Plus interceptor for MariaDB - Add MyBatis Plus JSQLParser dependency - Implement page-based user retrieval with role information - Remove obsolete MyBatis configuration class - Update controller to use paginated user data - Replace manual user conversion with constructor mapping - Rename UserProfileServcie to UserProfileService consistently --- chaos_api_data/pom.xml | 6 ++- .../chaos_api/config/MyBatisPlusConfig.java | 9 ---- .../cn/nopj/chaos_api/mapper/UserMapper.java | 28 ++++++++++++ .../dto/response/AuthTokenResponse.java | 2 +- .../dto/response/UserProfileResponse.java | 13 ++++++ ...leServcie.java => UserProfileService.java} | 12 +++++- ...eImpl.java => UserProfileServiceImpl.java} | 43 +++++++------------ .../chaos_api/config/MybatisPlusConfig.java | 21 +++++++++ .../chaos_api/controller/UserController.java | 19 ++++---- .../service/impl/AuthServiceImpl.java | 8 ++++ .../src/main/resources/application.yaml | 1 + pom.xml | 7 +++ 12 files changed, 121 insertions(+), 48 deletions(-) delete mode 100644 chaos_api_data/src/main/java/cn/nopj/chaos_api/config/MyBatisPlusConfig.java rename chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/{UserProfileServcie.java => UserProfileService.java} (86%) rename chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/{UserProfileServcieImpl.java => UserProfileServiceImpl.java} (80%) create mode 100644 chaos_api_web/src/main/java/cn/nopj/chaos_api/config/MybatisPlusConfig.java diff --git a/chaos_api_data/pom.xml b/chaos_api_data/pom.xml index bd564aa..970deeb 100644 --- a/chaos_api_data/pom.xml +++ b/chaos_api_data/pom.xml @@ -48,7 +48,11 @@ org.mariadb.jdbc mariadb-java-client - 3.5.4 + + + + com.baomidou + mybatis-plus-jsqlparser \ No newline at end of file diff --git a/chaos_api_data/src/main/java/cn/nopj/chaos_api/config/MyBatisPlusConfig.java b/chaos_api_data/src/main/java/cn/nopj/chaos_api/config/MyBatisPlusConfig.java deleted file mode 100644 index e0bfb09..0000000 --- a/chaos_api_data/src/main/java/cn/nopj/chaos_api/config/MyBatisPlusConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.nopj.chaos_api.config; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@MapperScan("cn.nopj.chaos_api.mapper") -public class MyBatisPlusConfig { -} 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 0e1ad35..4e4ac09 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 @@ -3,6 +3,8 @@ 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 com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.*; import org.springframework.transaction.annotation.Transactional; @@ -99,4 +101,30 @@ public interface UserMapper extends BaseMapper { many = @Many(select = "findRolesByUserId")) }) User findUserWithRolesByUsername(String username); + /** + * 分页查询用户,并携带角色信息 + * MyBatis-Plus 会自动处理 Page 参数进行物理分页 + * @param page 分页对象 + * @param keyword 搜索关键词 (可选) + * @return 分页后的用户列表 (包含角色) + */ + @Select(""" + + """) + @Results({ + @Result(id = true, property = "id", column = "id"), + @Result(property = "username", column = "username"), + @Result(property = "nickname", column = "nickname"), + @Result(property = "roles", column = "id", + many = @Many(select = "findRolesByUserId")) + }) + IPage selectPageWithRoles(Page page, @Param("keyword") String keyword); } \ No newline at end of file diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/AuthTokenResponse.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/AuthTokenResponse.java index b9d01b3..5f3d864 100644 --- a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/AuthTokenResponse.java +++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/AuthTokenResponse.java @@ -3,8 +3,8 @@ package cn.nopj.chaos_api.dto.response; import lombok.Data; @Data - public class AuthTokenResponse { private String tokenHead; private String token; + private UserProfileResponse userProfile; } diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserProfileResponse.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserProfileResponse.java index ea6d41c..e64eb05 100644 --- a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserProfileResponse.java +++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/response/UserProfileResponse.java @@ -1,5 +1,6 @@ package cn.nopj.chaos_api.dto.response; +import cn.nopj.chaos_api.domain.entity.User; import lombok.Data; import java.util.List; @@ -10,4 +11,16 @@ public class UserProfileResponse { private String username; private String nickname; private List roles; + + public UserProfileResponse(User user) { + this.id = user.getId(); + this.username = user.getUsername(); + this.nickname = user.getNickname(); + this.roles = user.getRoles().stream().map(role -> { + RoleResponse roleResponse = new RoleResponse(); + roleResponse.setId(role.getId()); + roleResponse.setName(role.getName()); + return roleResponse; + }).toList(); + } } diff --git a/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserProfileServcie.java b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserProfileService.java similarity index 86% rename from chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserProfileServcie.java rename to chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserProfileService.java index 46e3602..4a0a10f 100644 --- a/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserProfileServcie.java +++ b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/UserProfileService.java @@ -2,6 +2,7 @@ package cn.nopj.chaos_api.service; import cn.nopj.chaos_api.dto.request.UserProfileUpdateRequest; import cn.nopj.chaos_api.dto.response.UserProfileResponse; +import com.baomidou.mybatisplus.core.metadata.IPage; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; @@ -12,7 +13,7 @@ import java.util.List; * * @author nopj */ -public interface UserProfileServcie { +public interface UserProfileService { /** * 设置用户密码 @@ -80,4 +81,13 @@ public interface UserProfileServcie { * @return 处理结果 */ UserProfileResponse updateUserProfile(String username, UserProfileUpdateRequest request); + + /** + * 获取所有用户信息 + * + * @param pageNum 页码 + * @param pageSize 页大小 + * @return 所有用户信息 + */ + IPage getAllUsers(Integer pageNum, Integer pageSize); } diff --git a/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserProfileServcieImpl.java b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserProfileServiceImpl.java similarity index 80% rename from chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserProfileServcieImpl.java rename to chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserProfileServiceImpl.java index 7b04a9d..1d99e02 100644 --- a/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserProfileServcieImpl.java +++ b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/UserProfileServiceImpl.java @@ -7,7 +7,9 @@ import cn.nopj.chaos_api.dto.request.UserProfileUpdateRequest; import cn.nopj.chaos_api.dto.response.RoleResponse; import cn.nopj.chaos_api.dto.response.UserProfileResponse; import cn.nopj.chaos_api.mapper.UserMapper; -import cn.nopj.chaos_api.service.UserProfileServcie; +import cn.nopj.chaos_api.service.UserProfileService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; @@ -18,7 +20,7 @@ import java.util.List; @Slf4j @Service -public class UserProfileServcieImpl implements UserProfileServcie { +public class UserProfileServiceImpl implements UserProfileService { @Autowired private PasswordEncoder passwordEncoder; @Autowired @@ -47,7 +49,7 @@ public class UserProfileServcieImpl implements UserProfileServcie { throw new RuntimeException("获取所有用户信息失败"); } - return allUserWithRoles.stream().map(this::userConverterUserinfo).toList(); + return allUserWithRoles.stream().map(UserProfileResponse::new).toList(); } @Override @@ -91,7 +93,7 @@ public class UserProfileServcieImpl implements UserProfileServcie { if (user == null) { throw new BizException(ErrorCode.USER_NOT_EXISTS); } - return userConverterUserinfo(user); + return new UserProfileResponse(user); } @Override @@ -108,7 +110,7 @@ public class UserProfileServcieImpl implements UserProfileServcie { if (i == 0) { throw new BizException(ErrorCode.USER_UPDATE_NICKNAME_FAILED); } - return userConverterUserinfo(user); + return new UserProfileResponse(user); } @Override @@ -123,7 +125,7 @@ public class UserProfileServcieImpl implements UserProfileServcie { if (i == 0) { throw new BizException(ErrorCode.USER_UPDATE_NICKNAME_FAILED); } - return userConverterUserinfo(user); + return new UserProfileResponse(user); } @Override @@ -148,30 +150,17 @@ public class UserProfileServcieImpl implements UserProfileServcie { if (i == 0) { throw new BizException(ErrorCode.USER_UPDATE_PROFILE_FAILED); } - return userConverterUserinfo(user); + return new UserProfileResponse(user); + } + + @Override + public IPage getAllUsers(Integer pageNum, Integer pageSize) { + Page page = new Page<>(pageNum, pageSize); + IPage userPage = userMapper.selectPageWithRoles(page, null); + return userPage.convert(UserProfileResponse::new); } - /** - * User 转 UserinfoResponse - * @param user 用户 - * @return 用户信息 - */ - private UserProfileResponse userConverterUserinfo(User user) { - UserProfileResponse userProfileResponse = new UserProfileResponse(); - userProfileResponse.setId(user.getId()); - userProfileResponse.setUsername(user.getUsername()); - userProfileResponse.setNickname(user.getNickname()); - userProfileResponse.setRoles( - user.getRoles().stream().map(role -> { - RoleResponse roleResponse = new RoleResponse(); - roleResponse.setId(role.getId()); - roleResponse.setName(role.getName()); - return roleResponse; - }).toList() - ); - return userProfileResponse; - } diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/MybatisPlusConfig.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/MybatisPlusConfig.java new file mode 100644 index 0000000..d9a0147 --- /dev/null +++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/MybatisPlusConfig.java @@ -0,0 +1,21 @@ +package cn.nopj.chaos_api.config; + + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@MapperScan("cn.nopj.chaos_api.mapper") +public class MybatisPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MARIADB)); + return interceptor; + } +} 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 92ff7aa..e50522a 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 @@ -7,7 +7,8 @@ import cn.nopj.chaos_api.dto.request.UpdateUsernameRequest; import cn.nopj.chaos_api.dto.request.UserProfileUpdateRequest; import cn.nopj.chaos_api.dto.response.UserProfileResponse; import cn.nopj.chaos_api.model.ApiResult; -import cn.nopj.chaos_api.service.UserProfileServcie; +import cn.nopj.chaos_api.service.UserProfileService; +import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; @@ -26,7 +27,7 @@ import java.util.List; @RequestMapping("/api/user") public class UserController { @Autowired - private UserProfileServcie userProfileServcie; + private UserProfileService userProfileService; /** * 获取所有用户信息 @@ -34,8 +35,8 @@ public class UserController { */ @PreAuthorize("hasAuthority('admin')") @GetMapping("/all") - ApiResult> getAllUsers(){ - return ApiResult.success(userProfileServcie.getAllUsers()); + ApiResult> getAllUsers(@RequestParam(defaultValue = "1" , name = "pageNum") Integer pageNum, @RequestParam(defaultValue = "10", name="pageSize") Integer pageSize){ + return ApiResult.success(userProfileService.getAllUsers(pageNum, pageSize)); } /** @@ -46,7 +47,7 @@ public class UserController { @PreAuthorize("hasAuthority('admin')") @PutMapping("/setUserPassword") ApiResult setUserPassword(@RequestBody @Validated SetUserPasswordRequest request){ - userProfileServcie.setUserPassword(request.getUserId(), request.getPassword()); + userProfileService.setUserPassword(request.getUserId(), request.getPassword()); return ApiResult.success("用户密码修改成功"); } @@ -57,7 +58,7 @@ public class UserController { */ @PutMapping("/updateUsername") ApiResult updateUsername(@RequestAttribute("currentUsername") String username,@RequestBody @Validated UpdateUsernameRequest request){ - userProfileServcie.updateUsername(username, request.getUsername()); + userProfileService.updateUsername(username, request.getUsername()); return ApiResult.success("用户名更新成功"); } @@ -68,7 +69,7 @@ public class UserController { */ @GetMapping("/profile") ApiResult getCurrentUserProfile(@RequestAttribute("currentUsername") String username){ - return ApiResult.success(userProfileServcie.findUserWithRoles(username)); + return ApiResult.success(userProfileService.findUserWithRoles(username)); } /** @@ -79,7 +80,7 @@ public class UserController { */ @PatchMapping("/profile") ApiResult getUserInfo(@RequestAttribute("currentUsername") String username, @RequestBody @Validated UserProfileUpdateRequest request){ - return ApiResult.success(userProfileServcie.updateUserProfile(username,request)); + return ApiResult.success(userProfileService.updateUserProfile(username,request)); } /** @@ -89,6 +90,6 @@ public class UserController { @PreAuthorize("hasAuthority('admin')") @PutMapping("/{userId}/nickname") ApiResult setNickname(@PathVariable Long userId, @RequestBody @Validated SetUserNicknameRequest request){ - return ApiResult.success(userProfileServcie.setUserNickname(userId,request.getNickname())); + return ApiResult.success(userProfileService.setUserNickname(userId,request.getNickname())); } } 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 23a2b00..d7ebdaa 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 @@ -6,6 +6,7 @@ import cn.nopj.chaos_api.common.exceotion.BizException; import cn.nopj.chaos_api.domain.entity.Role; import cn.nopj.chaos_api.domain.entity.User; import cn.nopj.chaos_api.dto.response.AuthTokenResponse; +import cn.nopj.chaos_api.dto.response.UserProfileResponse; import cn.nopj.chaos_api.mapper.RoleMapper; import cn.nopj.chaos_api.mapper.UserMapper; import cn.nopj.chaos_api.service.AuthService; @@ -79,9 +80,16 @@ public class AuthServiceImpl implements AuthService { if (!userDetails.isEnabled()) { throw new BizException(ErrorCode.USER_NOT_ENABLED); } + + User user = userMapper.findUserWithRolesByUsername(username); + UserProfileResponse userProfileResponse = new UserProfileResponse(user); + AuthTokenResponse res = new AuthTokenResponse(); res.setToken(jwtTokenUtil.generateToken(userDetails)); res.setTokenHead(tokenHead); + res.setUserProfile(userProfileResponse); + + return res; }catch (BadCredentialsException | InternalAuthenticationServiceException e) { diff --git a/chaos_api_web/src/main/resources/application.yaml b/chaos_api_web/src/main/resources/application.yaml index 94f8dd8..4e0cb16 100644 --- a/chaos_api_web/src/main/resources/application.yaml +++ b/chaos_api_web/src/main/resources/application.yaml @@ -35,6 +35,7 @@ mybatis-plus: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + jwt: tokenHeader: Authorization tokenHead: Chaos diff --git a/pom.xml b/pom.xml index 6a7bf69..1bc6b78 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,13 @@ spring-context 6.2.13 + + + + com.baomidou + mybatis-plus-jsqlparser + 3.5.14 + \ No newline at end of file