Uh oh!
There was an error while loading. Please reload this page.
satoken鉴权 - #3
Merged
Merged
Conversation
New test suites: - JdbcUserAccountRepositoryTests: 13 tests covering all CRUD operations, null handling, and error paths with H2 in-memory database - AuthServiceTests: 13 unit tests for login/loginByGithub/logout/currentUser using Mockito with mockStatic for Sa-Token isolation - OAuthControllerIntegrationTests: 4 tests covering GitHub OAuth redirect URL validation and callback failure paths Infrastructure fixes: - AbstractWebIntegrationTest: add @SpringBootTest(properties) override to prevent SPRING_DATASOURCE_URL env var from overriding H2 test config - BackendApplicationTests: same H2 override fix for context load test - test-schema.sql: add missing avatar_url, email, github_id columns that JdbcUserAccountRepository.ROW_MAPPER reads Production bug fixes revealed by tests: - SaTokenPermissionImpl: implement StpInterface so @SaCheckPermission annotations can resolve permissions from the database (was always 403) - GlobalExceptionHandler: use e.getPermission() instead of e.getCode() in handleNotPermissionException (getCode() returned -1, not the permission) Pre-existing test fixes: - AuthControllerIntegrationTests: update expected Sa-Token error messages from old generic message to current specific messages ("未提供 Token") - UserCenterControllerIntegrationTests: fix stale URL paths (/users instead of /api/user-center/users) and update expected permission error messages - OpenAiStreamControllerIntegrationTests: update for renamed DTO field (message -> messages), fix asyncDispatch pattern for StreamingResponseBody, and align stub gateway with OpenAI API format expected by relayEvents() Result: 78/78 tests pass (was 40/78 with 36 errors + 2 failures baseline) https://claude.ai/code/session_016Z9qEQdrSXSTAhCp1YMgnk
Root causes and fixes: 1. SaTokenPermissionImpl (NEW) - Without StpInterface, Sa-Token returns empty permissions for all users, causing every @SaCheckPermission check to unconditionally fail with 403. - loginId must be parsed via toString() first: Sa-Token serializes it as String internally even when StpUtil.login(Long) was called. 2. GlobalExceptionHandler - NotPermissionException.getCode() returns the integer scene code (-1), not the permission string. Fixed to getPermission() which returns the actual missing permission name (e.g. "user:center:read"). 3. AbstractWebIntegrationTest + BackendApplicationTests - SPRING_DATASOURCE_URL env var (pointing to Neon PostgreSQL) has higher Spring priority than application-test.properties, causing H2 context load failure. Fixed via @SpringBootTest(properties) which overrides all env vars. - JustAuth UrlValidator rejects localhost redirect URIs; overridden with a syntactically valid placeholder URL. 4. AuthControllerIntegrationTests - Sa-Token NOT_TOKEN scenario now maps to "未提供 Token", not the old generic "未登录或登录状态已失效" message. 5. UserCenterControllerIntegrationTests - All URLs updated: /api/user-center/* paths were removed; current routes are /auth/me, /users, /users/{id}, /users/{id}/authorization. - Permission error message updated to match GlobalExceptionHandler output: "拒绝访问: 缺少权限 [<permission>]". 6. OpenAiStreamControllerIntegrationTests - DTO field renamed: message (String) -> messages (List), aligning with Vercel AI SDK payload format. - Async test uses asyncDispatch two-step pattern (required for StreamingResponseBody); polling getContentAsString() never sees data. - Stub returns OpenAI SSE format choices[0].delta.content so relayEvents() can extract the text and emit Vercel Stream prefix "0:". All 78 tests now pass. https://claude.ai/code/session_016Z9qEQdrSXSTAhCp1YMgnk
Contributor
There was a problem hiding this comment.
Pull request overview
该 PR 主要将用户中心鉴权体系从 Spring Security/JWT 迁移到 Sa-Token,并新增 JustAuth GitHub OAuth 登录链路;同时对 OpenAI 流式接口进行改造以适配前端 Vercel AI SDK 的流格式,并同步更新数据库字段、路由与测试/部署配置。
Changes:
- 引入 Sa-Token + 权限加载实现(StpInterface),替换 Spring Security 注解与当前用户解析逻辑,并调整路由前缀(去掉 context-path /api/v1)。
- 增加 JustAuth GitHub OAuth:新增 OAuthController、AuthService GitHub 登录/自动注册、用户表补充 GitHub 资料字段。
- 重构 OpenAI 流式转发:DTO 从 message→messages,Gateway 改为 /chat/completions,Service 改为输出 Vercel stream data 格式,并更新相关测试。
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/test/resources/test-schema.sql | 测试库 user_accounts 增加 GitHub 资料字段列 |
| src/test/java/com/involutionhell/backend/usercenter/service/AuthServiceTests.java | 覆盖账号密码与 GitHub 登录的 AuthService 单测 |
| src/test/java/com/involutionhell/backend/usercenter/repository/JdbcUserAccountRepositoryTests.java | 覆盖 insert/updateProfile 等仓储集成测试 |
| src/test/java/com/involutionhell/backend/usercenter/model/UserAccountTests.java | 适配 UserAccount 新字段的模型单测 |
| src/test/java/com/involutionhell/backend/usercenter/controller/UserCenterControllerIntegrationTests.java | 修正用户中心接口路径与权限错误消息断言 |
| src/test/java/com/involutionhell/backend/usercenter/controller/OAuthControllerIntegrationTests.java | 新增 OAuthController 集成测试 |
| src/test/java/com/involutionhell/backend/usercenter/controller/AuthControllerIntegrationTests.java | 修正 AuthController 路径与匿名错误消息断言 |
| src/test/java/com/involutionhell/backend/support/AbstractWebIntegrationTest.java | 集成测试基类:强制 H2 + 覆盖 JustAuth redirect-uri |
| src/test/java/com/involutionhell/backend/openai/service/OpenAiStreamServiceTests.java | 更新 OpenAiStreamService 单测为 OutputStream 流式输出 |
| src/test/java/com/involutionhell/backend/openai/service/HttpOpenAiStreamGatewayTests.java | Gateway 测试适配 /chat/completions 与 messages payload |
| src/test/java/com/involutionhell/backend/openai/controller/OpenAiStreamControllerIntegrationTests.java | 改用 asyncDispatch 验证 StreamingResponseBody 输出 |
| src/test/java/com/involutionhell/backend/common/error/GlobalExceptionHandlerTests.java | 从 Spring Security 异常切换到 Sa-Token 异常断言 |
| src/test/java/com/involutionhell/backend/BackendApplicationTests.java | 冒烟测试显式覆盖数据源与 JustAuth 配置 |
| src/main/resources/schema.sql | 生产 schema 为 user_accounts 增加 GitHub 资料字段 |
| src/main/resources/application.properties | 去掉 context-path;默认禁用 schema init;加入 JustAuth + Sa-Token 配置 |
| src/main/java/com/involutionhell/backend/usercenter/service/UserCenterService.java | currentUser 改用 StpUtil;新增 createUser/updateProfile |
| src/main/java/com/involutionhell/backend/usercenter/service/AuthService.java | 账号密码登录改为 Sa-Token;新增 GitHub 登录/注册逻辑 |
| src/main/java/com/involutionhell/backend/usercenter/repository/UserAccountRepository.java | 新增 insert/updateProfile 仓储接口 |
| src/main/java/com/involutionhell/backend/usercenter/repository/JdbcUserAccountRepository.java | RowMapper/insert/updateProfile 支持新字段 |
| src/main/java/com/involutionhell/backend/usercenter/model/UserAccount.java | 用户模型新增 avatarUrl/email/githubId 字段 |
| src/main/java/com/involutionhell/backend/usercenter/HealthTestController.java | 修正 Controller 映射方式为 @RequestMapping |
| src/main/java/com/involutionhell/backend/usercenter/dto/UserView.java | UserView 暴露 GitHub 资料字段 |
| src/main/java/com/involutionhell/backend/usercenter/controller/UserCenterController.java | 路由改为 /users + @SaCheckPermission |
| src/main/java/com/involutionhell/backend/usercenter/controller/OAuthController.java | 新增 JustAuth GitHub OAuth 发起/回调处理 |
| src/main/java/com/involutionhell/backend/usercenter/controller/AuthController.java | 路由改为 /auth + @SaCheckLogin |
| src/main/java/com/involutionhell/backend/usercenter/config/SecurityConfig.java | 暂时注释 Spring Security 配置(迁移中) |
| src/main/java/com/involutionhell/backend/openai/service/OpenAiStreamService.java | 以 OutputStream 输出 Vercel stream data 格式并转译 delta.content |
| src/main/java/com/involutionhell/backend/openai/service/HttpOpenAiStreamGateway.java | /chat/completions 请求构造 + 配置告警 |
| src/main/java/com/involutionhell/backend/openai/dto/OpenAiStreamRequest.java | DTO 改为 messages 列表 + @NotEmpty 校验 |
| src/main/java/com/involutionhell/backend/openai/controller/OpenAiStreamController.java | 控制器改为 StreamingResponseBody + TEXT_PLAIN 输出 |
| src/main/java/com/involutionhell/backend/common/error/GlobalExceptionHandler.java | 增加 Sa-Token 异常处理与更细粒度消息 |
| src/main/java/com/involutionhell/backend/common/config/SaTokenPermissionImpl.java | 新增 StpInterface 实现加载角色/权限 |
| src/main/java/com/involutionhell/backend/common/config/SaTokenConfigure.java | 新增 SaInterceptor 全局登录拦截规则 |
| README.md | 更新默认接口入口与示例调用路径 |
| pom.xml | 引入 JustAuth/Hutool 与 Sa-Token;暂时注释 Security 依赖 |
| docs/dev1.md | 新增开发参考文档(端点、ID 体系、Sa-Token 流程) |
| docker-compose.yml | 更新容器健康检查路径 |
| Caddyfile | 更新 reverse_proxy health_uri 路径 |
| .github/workflows/deploy.yml | 更新部署后健康检查路径 |
| .env.example | 调整 SQL init 默认值与 Actuator show-details 建议 |
| .editorconfig | 新增仓库 editorconfig 规范 |
Comments suppressed due to low confidence (1)
src/main/java/com/involutionhell/backend/common/error/GlobalExceptionHandler.java:101
- handleUnexpected() 里直接 exception.printStackTrace() 会把堆栈输出到 stdout/stderr,生产环境中不易聚合、也可能造成日志噪声。建议改为使用日志框架记录(例如 Logger.error("...", exception)),并按环境配置日志级别/是否打印堆栈。
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Void>> handleUnexpected(Exception exception) {
exception.printStackTrace(); // 建议在开发阶段打印堆栈,生产环境应使用日志框架
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.fail("服务器内部错误"));
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern; |
There was a problem hiding this comment.
这里引入了 redirectedUrlPattern 但文件内未使用,会导致 Java 编译失败(unused import)。建议删除该 static import,或改用它来做重定向 URL 的断言。
Suggested change
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern; |
Removed all <h3>, <h4>, <p>, <ul>, <li>, <ol> tags from Javadoc blocks. Rewrote everything in plain Chinese as a developer would naturally write it. https://claude.ai/code/session_016Z9qEQdrSXSTAhCp1YMgnk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.