From 9fd8971732065c244563b5b5063ac0fc467487ee Mon Sep 17 00:00:00 2001 From: zjw <2956131242@qq.com> Date: Wed, 15 Apr 2026 10:46:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E6=8E=A5=E5=8F=A3=E5=89=8D?= =?UTF-8?q?=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- .../com/label/controller/AuthController.java | 2 +- .../label/controller/CompanyController.java | 2 +- .../label/controller/ExportController.java | 1 + .../controller/ExtractionController.java | 2 +- .../com/label/controller/QaController.java | 2 +- .../label/controller/SourceController.java | 2 +- .../label/controller/SysConfigController.java | 1 + .../com/label/controller/TaskController.java | 2 +- .../com/label/controller/UserController.java | 2 +- .../com/label/controller/VideoController.java | 1 + .../label/interceptor/AuthInterceptor.java | 9 +- src/main/resources/application.yml | 1 - .../label/blackbox/AbstractBlackBoxTest.java | 14 +- .../blackbox/SwaggerLiveBlackBoxTest.java | 138 +++++++++--------- .../integration/AuthIntegrationTest.java | 16 +- .../integration/ExportIntegrationTest.java | 8 +- .../ExtractionApprovalIntegrationTest.java | 20 +-- .../integration/MultiTenantIsolationTest.java | 8 +- .../QaApprovalIntegrationTest.java | 18 +-- .../integration/SourceIntegrationTest.java | 12 +- .../integration/SysConfigIntegrationTest.java | 6 +- .../integration/TaskClaimConcurrencyTest.java | 2 +- .../UserManagementIntegrationTest.java | 18 +-- .../VideoCallbackIdempotencyTest.java | 4 +- .../com/label/unit/AuthInterceptorTest.java | 8 +- 26 files changed, 153 insertions(+), 148 deletions(-) diff --git a/Dockerfile b/Dockerfile index e68ef5d..399e818 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM registry.bjzgzp.com:4433/library/eclipse-temurin:21-jdk-ubi10-minimal WORKDIR /app -COPY ./target/label-backend-1.0.0-SNAPSHOT.jar /app/label-backend-1.0.0-SNAPSHOT.jar +COPY ./label-backend-1.0.0-SNAPSHOT.jar /app/label-backend-1.0.0-SNAPSHOT.jar EXPOSE 18082 diff --git a/src/main/java/com/label/controller/AuthController.java b/src/main/java/com/label/controller/AuthController.java index 42aa24f..67f1586 100644 --- a/src/main/java/com/label/controller/AuthController.java +++ b/src/main/java/com/label/controller/AuthController.java @@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.*; */ @Tag(name = "认证管理", description = "登录、退出和当前用户信息") @RestController -@RequestMapping("/api/auth") +@RequestMapping("/label/api/auth") @RequiredArgsConstructor public class AuthController { diff --git a/src/main/java/com/label/controller/CompanyController.java b/src/main/java/com/label/controller/CompanyController.java index 7bdfc90..a2cff1a 100644 --- a/src/main/java/com/label/controller/CompanyController.java +++ b/src/main/java/com/label/controller/CompanyController.java @@ -24,7 +24,7 @@ import java.util.Map; @Tag(name = "公司管理", description = "租户公司增删改查") @RestController -@RequestMapping("/api/companies") +@RequestMapping("/label/api/companies") @RequiredArgsConstructor public class CompanyController { diff --git a/src/main/java/com/label/controller/ExportController.java b/src/main/java/com/label/controller/ExportController.java index 6e88d7e..4fba660 100644 --- a/src/main/java/com/label/controller/ExportController.java +++ b/src/main/java/com/label/controller/ExportController.java @@ -23,6 +23,7 @@ import java.util.Map; */ @Tag(name = "导出管理", description = "训练样本查询、导出批次和微调任务") @RestController +@RequestMapping("/label") @RequiredArgsConstructor public class ExportController { diff --git a/src/main/java/com/label/controller/ExtractionController.java b/src/main/java/com/label/controller/ExtractionController.java index 65abec5..f833e3f 100644 --- a/src/main/java/com/label/controller/ExtractionController.java +++ b/src/main/java/com/label/controller/ExtractionController.java @@ -17,7 +17,7 @@ import java.util.Map; */ @Tag(name = "提取标注", description = "提取阶段的查看、编辑、提交和审批") @RestController -@RequestMapping("/api/extraction") +@RequestMapping("/label/api/extraction") @RequiredArgsConstructor public class ExtractionController { diff --git a/src/main/java/com/label/controller/QaController.java b/src/main/java/com/label/controller/QaController.java index 5c30b9c..90458c5 100644 --- a/src/main/java/com/label/controller/QaController.java +++ b/src/main/java/com/label/controller/QaController.java @@ -17,7 +17,7 @@ import java.util.Map; */ @Tag(name = "问答生成", description = "问答生成阶段的查看、编辑、提交和审批") @RestController -@RequestMapping("/api/qa") +@RequestMapping("/label/api/qa") @RequiredArgsConstructor public class QaController { diff --git a/src/main/java/com/label/controller/SourceController.java b/src/main/java/com/label/controller/SourceController.java index e134d7b..74d11c7 100644 --- a/src/main/java/com/label/controller/SourceController.java +++ b/src/main/java/com/label/controller/SourceController.java @@ -23,7 +23,7 @@ import org.springframework.web.multipart.MultipartFile; */ @Tag(name = "资料管理", description = "原始资料上传、查询和删除") @RestController -@RequestMapping("/api/source") +@RequestMapping("/label/api/source") @RequiredArgsConstructor public class SourceController { diff --git a/src/main/java/com/label/controller/SysConfigController.java b/src/main/java/com/label/controller/SysConfigController.java index b0d775e..be52aa8 100644 --- a/src/main/java/com/label/controller/SysConfigController.java +++ b/src/main/java/com/label/controller/SysConfigController.java @@ -22,6 +22,7 @@ import java.util.Map; */ @Tag(name = "系统配置", description = "全局和公司级系统配置管理") @RestController +@RequestMapping("/label") @RequiredArgsConstructor public class SysConfigController { diff --git a/src/main/java/com/label/controller/TaskController.java b/src/main/java/com/label/controller/TaskController.java index a63ed8a..7b7ba49 100644 --- a/src/main/java/com/label/controller/TaskController.java +++ b/src/main/java/com/label/controller/TaskController.java @@ -20,7 +20,7 @@ import java.util.Map; */ @Tag(name = "任务管理", description = "任务池、我的任务、审批队列和管理操作") @RestController -@RequestMapping("/api/tasks") +@RequestMapping("/label/api/tasks") @RequiredArgsConstructor public class TaskController { diff --git a/src/main/java/com/label/controller/UserController.java b/src/main/java/com/label/controller/UserController.java index 8e450e9..cfebfa4 100644 --- a/src/main/java/com/label/controller/UserController.java +++ b/src/main/java/com/label/controller/UserController.java @@ -28,7 +28,7 @@ import lombok.RequiredArgsConstructor; */ @Tag(name = "用户管理", description = "管理员维护公司用户") @RestController -@RequestMapping("/api/users") +@RequestMapping("/label/api/users") @RequiredArgsConstructor public class UserController { diff --git a/src/main/java/com/label/controller/VideoController.java b/src/main/java/com/label/controller/VideoController.java index 1749f51..11dfd56 100644 --- a/src/main/java/com/label/controller/VideoController.java +++ b/src/main/java/com/label/controller/VideoController.java @@ -26,6 +26,7 @@ import java.util.Map; @Tag(name = "视频处理", description = "视频处理任务创建、查询、重置和回调") @Slf4j @RestController +@RequestMapping("/label") @RequiredArgsConstructor public class VideoController { diff --git a/src/main/java/com/label/interceptor/AuthInterceptor.java b/src/main/java/com/label/interceptor/AuthInterceptor.java index aec3d43..327accb 100644 --- a/src/main/java/com/label/interceptor/AuthInterceptor.java +++ b/src/main/java/com/label/interceptor/AuthInterceptor.java @@ -28,6 +28,9 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class AuthInterceptor implements HandlerInterceptor { + private static final String API_PREFIX = "/label"; + private static final String API_ROOT = API_PREFIX + "/api/"; + private final RedisService redisService; private final ObjectMapper objectMapper; @@ -155,9 +158,9 @@ public class AuthInterceptor implements HandlerInterceptor { } private boolean isPublicPath(String path) { - return !path.startsWith("/api/") - || path.equals("/api/auth/login") - || path.equals("/api/video/callback") + return !path.startsWith(API_ROOT) + || path.equals(API_PREFIX + "/api/auth/login") + || path.equals(API_PREFIX + "/api/video/callback") || path.startsWith("/swagger-ui") || path.startsWith("/v3/api-docs"); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index bea0b1d..83a6a5c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,5 +1,4 @@ server: - port: 8080 port: 18082 spring: diff --git a/src/test/java/com/label/blackbox/AbstractBlackBoxTest.java b/src/test/java/com/label/blackbox/AbstractBlackBoxTest.java index 54cd53f..3c24fc8 100644 --- a/src/test/java/com/label/blackbox/AbstractBlackBoxTest.java +++ b/src/test/java/com/label/blackbox/AbstractBlackBoxTest.java @@ -147,7 +147,7 @@ abstract class AbstractBlackBoxTest { if (callbackSecret != null && !callbackSecret.isBlank()) { headers.set("X-Callback-Secret", callbackSecret); } - return restTemplate.exchange(url("/api/video/callback"), HttpMethod.POST, new HttpEntity<>(body, headers), Map.class); + return restTemplate.exchange(url("/label/api/video/callback"), HttpMethod.POST, new HttpEntity<>(body, headers), Map.class); } protected String login(String targetCompanyCode, String username, String password) { @@ -156,7 +156,7 @@ abstract class AbstractBlackBoxTest { "username", username, "password", password ); - ResponseEntity response = postJson("/api/auth/login", body, null); + ResponseEntity response = postJson("/label/api/auth/login", body, null); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); @SuppressWarnings("unchecked") Map data = (Map) Objects.requireNonNull(response.getBody()).get("data"); @@ -165,7 +165,7 @@ abstract class AbstractBlackBoxTest { protected Long uploadTextSource(String token) { ResponseEntity response = upload( - "/api/source/upload", + "/label/api/source/upload", token, "bb-" + runId + ".txt", "TEXT", @@ -176,7 +176,7 @@ abstract class AbstractBlackBoxTest { protected Long uploadVideoSource(String token) { ResponseEntity response = upload( - "/api/source/upload", + "/label/api/source/upload", token, "bb-" + runId + ".mp4", "VIDEO", @@ -186,7 +186,7 @@ abstract class AbstractBlackBoxTest { } protected Long createTask(Long sourceId, String taskType) { - ResponseEntity response = postJson("/api/tasks", Map.of( + ResponseEntity response = postJson("/label/api/tasks", Map.of( "sourceId", sourceId, "taskType", taskType ), adminToken); @@ -330,8 +330,8 @@ abstract class AbstractBlackBoxTest { private void detectRuntimeAuthMode() { try { - ResponseEntity adminMe = get("/api/auth/me", adminToken); - ResponseEntity reviewerMe = get("/api/auth/me", reviewerToken); + ResponseEntity adminMe = get("/label/api/auth/me", adminToken); + ResponseEntity reviewerMe = get("/label/api/auth/me", reviewerToken); if (!adminMe.getStatusCode().is2xxSuccessful() || !reviewerMe.getStatusCode().is2xxSuccessful()) { this.roleAwareAuthEnabled = false; return; diff --git a/src/test/java/com/label/blackbox/SwaggerLiveBlackBoxTest.java b/src/test/java/com/label/blackbox/SwaggerLiveBlackBoxTest.java index 6abbf69..ddfce0e 100644 --- a/src/test/java/com/label/blackbox/SwaggerLiveBlackBoxTest.java +++ b/src/test/java/com/label/blackbox/SwaggerLiveBlackBoxTest.java @@ -19,12 +19,12 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { void publicAndAuthEndpoints_shouldWork() { ResponseEntity openApi = getRaw("/v3/api-docs"); assertThat(openApi.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(openApi.getBody()).contains("/api/auth/login"); + assertThat(openApi.getBody()).contains("/label/api/auth/login"); ResponseEntity swaggerUi = getRaw("/swagger-ui.html"); assertThat(swaggerUi.getStatusCode().is2xxSuccessful() || swaggerUi.getStatusCode().is3xxRedirection()).isTrue(); - ResponseEntity login = postJson("/api/auth/login", Map.of( + ResponseEntity login = postJson("/label/api/auth/login", Map.of( "companyCode", companyCode, "username", adminUser.username(), "password", adminUser.password() @@ -35,17 +35,17 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { return; } - ResponseEntity me = get("/api/auth/me", adminToken); + ResponseEntity me = get("/label/api/auth/me", adminToken); assertSuccess(me, HttpStatus.OK); @SuppressWarnings("unchecked") Map meData = (Map) me.getBody().get("data"); assertThat(meData.get("username")).isEqualTo(adminUser.username()); assertThat(meData.get("role")).isEqualTo("ADMIN"); - ResponseEntity logout = postJson("/api/auth/logout", null, adminToken); + ResponseEntity logout = postJson("/label/api/auth/logout", null, adminToken); assertSuccess(logout, HttpStatus.OK); - ResponseEntity meAfterLogout = get("/api/auth/me", adminToken); + ResponseEntity meAfterLogout = get("/label/api/auth/me", adminToken); assertThat(meAfterLogout.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @@ -54,37 +54,37 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { void companyAndUserEndpoints_shouldWork() { requireRoleAwareAuth(); - ResponseEntity companyList = get("/api/companies?page=1&pageSize=20", adminToken); + ResponseEntity companyList = get("/label/api/companies?page=1&pageSize=20", adminToken); assertSuccess(companyList, HttpStatus.OK); String extraCompanyCode = ("EXT" + runId).toUpperCase(); String extraCompanyName = "扩展公司-" + runId; - ResponseEntity createCompany = postJson("/api/companies", Map.of( + ResponseEntity createCompany = postJson("/label/api/companies", Map.of( "companyName", extraCompanyName, "companyCode", extraCompanyCode ), adminToken); assertSuccess(createCompany, HttpStatus.CREATED); Long extraCompanyId = dataId(createCompany); - ResponseEntity updateCompany = putJson("/api/companies/" + extraCompanyId, Map.of( + ResponseEntity updateCompany = putJson("/label/api/companies/" + extraCompanyId, Map.of( "companyName", extraCompanyName + "-改", "companyCode", extraCompanyCode ), adminToken); assertSuccess(updateCompany, HttpStatus.OK); - ResponseEntity companyStatus = putJson("/api/companies/" + extraCompanyId + "/status", + ResponseEntity companyStatus = putJson("/label/api/companies/" + extraCompanyId + "/status", Map.of("status", "DISABLED"), adminToken); assertSuccess(companyStatus, HttpStatus.OK); - ResponseEntity deleteCompany = delete("/api/companies/" + extraCompanyId, adminToken); + ResponseEntity deleteCompany = delete("/label/api/companies/" + extraCompanyId, adminToken); assertSuccess(deleteCompany, HttpStatus.OK); - ResponseEntity userList = get("/api/users?page=1&pageSize=20", adminToken); + ResponseEntity userList = get("/label/api/users?page=1&pageSize=20", adminToken); assertSuccess(userList, HttpStatus.OK); String username = "bb_user_" + UUID.randomUUID().toString().substring(0, 8); String password = "BbUser@123"; - ResponseEntity createUser = postJson("/api/users", Map.of( + ResponseEntity createUser = postJson("/label/api/users", Map.of( "username", username, "password", password, "realName", "黑盒用户", @@ -93,7 +93,7 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { assertSuccess(createUser, HttpStatus.OK); Long userId = dataId(createUser); - ResponseEntity updateUser = putJson("/api/users/" + userId, Map.of( + ResponseEntity updateUser = putJson("/label/api/users/" + userId, Map.of( "realName", "黑盒用户-改", "password", "BbUser@456" ), adminToken); @@ -101,21 +101,21 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { String userToken = login(companyCode, username, "BbUser@456"); - ResponseEntity beforeRoleChange = get("/api/tasks/pending-review", userToken); + ResponseEntity beforeRoleChange = get("/label/api/tasks/pending-review", userToken); assertThat(beforeRoleChange.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - ResponseEntity updateRole = putJson("/api/users/" + userId + "/role", + ResponseEntity updateRole = putJson("/label/api/users/" + userId + "/role", Map.of("role", "REVIEWER"), adminToken); assertSuccess(updateRole, HttpStatus.OK); - ResponseEntity afterRoleChange = get("/api/tasks/pending-review", userToken); + ResponseEntity afterRoleChange = get("/label/api/tasks/pending-review", userToken); assertThat(afterRoleChange.getStatusCode()).isEqualTo(HttpStatus.OK); - ResponseEntity updateStatus = putJson("/api/users/" + userId + "/status", + ResponseEntity updateStatus = putJson("/label/api/users/" + userId + "/status", Map.of("status", "DISABLED"), adminToken); assertSuccess(updateStatus, HttpStatus.OK); - ResponseEntity meAfterDisable = get("/api/auth/me", userToken); + ResponseEntity meAfterDisable = get("/label/api/auth/me", userToken); assertThat(meAfterDisable.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @@ -125,51 +125,51 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { requireRoleAwareAuth(); Long disposableSourceId = uploadTextSource(uploaderToken); - ResponseEntity deleteDisposable = delete("/api/source/" + disposableSourceId, adminToken); + ResponseEntity deleteDisposable = delete("/label/api/source/" + disposableSourceId, adminToken); assertSuccess(deleteDisposable, HttpStatus.OK); Long sourceId = uploadTextSource(uploaderToken); - ResponseEntity uploaderList = get("/api/source/list?page=1&pageSize=20", uploaderToken); + ResponseEntity uploaderList = get("/label/api/source/list?page=1&pageSize=20", uploaderToken); assertSuccess(uploaderList, HttpStatus.OK); assertThat(responseContainsId(uploaderList, sourceId)).isTrue(); - ResponseEntity adminList = get("/api/source/list?page=1&pageSize=20", adminToken); + ResponseEntity adminList = get("/label/api/source/list?page=1&pageSize=20", adminToken); assertSuccess(adminList, HttpStatus.OK); assertThat(responseContainsId(adminList, sourceId)).isTrue(); - ResponseEntity sourceDetail = get("/api/source/" + sourceId, adminToken); + ResponseEntity sourceDetail = get("/label/api/source/" + sourceId, adminToken); assertSuccess(sourceDetail, HttpStatus.OK); Long taskId = createTask(sourceId, "EXTRACTION"); - ResponseEntity pool = get("/api/tasks/pool?page=1&pageSize=20", annotatorToken); + ResponseEntity pool = get("/label/api/tasks/pool?page=1&pageSize=20", annotatorToken); assertSuccess(pool, HttpStatus.OK); assertThat(responseContainsId(pool, taskId)).isTrue(); - ResponseEntity allTasks = get("/api/tasks?page=1&pageSize=20&taskType=EXTRACTION", adminToken); + ResponseEntity allTasks = get("/label/api/tasks?page=1&pageSize=20&taskType=EXTRACTION", adminToken); assertSuccess(allTasks, HttpStatus.OK); assertThat(responseContainsId(allTasks, taskId)).isTrue(); - ResponseEntity taskDetail = get("/api/tasks/" + taskId, annotatorToken); + ResponseEntity taskDetail = get("/label/api/tasks/" + taskId, annotatorToken); assertSuccess(taskDetail, HttpStatus.OK); - ResponseEntity claim = postJson("/api/tasks/" + taskId + "/claim", null, annotatorToken); + ResponseEntity claim = postJson("/label/api/tasks/" + taskId + "/claim", null, annotatorToken); assertSuccess(claim, HttpStatus.OK); - ResponseEntity mine = get("/api/tasks/mine?page=1&pageSize=20", annotatorToken); + ResponseEntity mine = get("/label/api/tasks/mine?page=1&pageSize=20", annotatorToken); assertSuccess(mine, HttpStatus.OK); assertThat(responseContainsId(mine, taskId)).isTrue(); - ResponseEntity unclaim = postJson("/api/tasks/" + taskId + "/unclaim", null, annotatorToken); + ResponseEntity unclaim = postJson("/label/api/tasks/" + taskId + "/unclaim", null, annotatorToken); assertSuccess(unclaim, HttpStatus.OK); Long sourceId2 = uploadTextSource(uploaderToken); Long taskId2 = createTask(sourceId2, "EXTRACTION"); - ResponseEntity claimTask2 = postJson("/api/tasks/" + taskId2 + "/claim", null, annotatorToken); + ResponseEntity claimTask2 = postJson("/label/api/tasks/" + taskId2 + "/claim", null, annotatorToken); assertSuccess(claimTask2, HttpStatus.OK); - ResponseEntity reassign = putJson("/api/tasks/" + taskId2 + "/reassign", + ResponseEntity reassign = putJson("/label/api/tasks/" + taskId2 + "/reassign", Map.of("userId", annotator2User.id()), adminToken); assertSuccess(reassign, HttpStatus.OK); assertThat(claimedByOfTask(taskId2)).isEqualTo(annotator2User.id()); @@ -180,10 +180,10 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { void extractionQaConfigAndExportEndpoints_shouldWork() { requireRoleAwareAuth(); - ResponseEntity listConfig = get("/api/config", adminToken); + ResponseEntity listConfig = get("/label/api/config", adminToken); assertSuccess(listConfig, HttpStatus.OK); - ResponseEntity updateConfig = putJson("/api/config/model_default", + ResponseEntity updateConfig = putJson("/label/api/config/model_default", Map.of("value", "glm-4-blackbox-" + runId, "description", "黑盒测试默认模型"), adminToken); assertSuccess(updateConfig, HttpStatus.OK); @@ -191,89 +191,89 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { Long sourceId = uploadTextSource(uploaderToken); Long extractionTaskId = createTask(sourceId, "EXTRACTION"); - assertSuccess(postJson("/api/tasks/" + extractionTaskId + "/claim", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/tasks/" + extractionTaskId + "/claim", null, annotatorToken), HttpStatus.OK); - ResponseEntity extractionGet = get("/api/extraction/" + extractionTaskId, annotatorToken); + ResponseEntity extractionGet = get("/label/api/extraction/" + extractionTaskId, annotatorToken); assertSuccess(extractionGet, HttpStatus.OK); - ResponseEntity extractionPut = putJson("/api/extraction/" + extractionTaskId, + ResponseEntity extractionPut = putJson("/label/api/extraction/" + extractionTaskId, "{\"items\":[{\"label\":\"entity\",\"text\":\"北京\"}]}", annotatorToken); assertSuccess(extractionPut, HttpStatus.OK); - ResponseEntity extractionSubmit = postJson("/api/extraction/" + extractionTaskId + "/submit", null, annotatorToken); + ResponseEntity extractionSubmit = postJson("/label/api/extraction/" + extractionTaskId + "/submit", null, annotatorToken); assertSuccess(extractionSubmit, HttpStatus.OK); - ResponseEntity pendingExtraction = get("/api/tasks/pending-review?page=1&pageSize=20&taskType=EXTRACTION", reviewerToken); + ResponseEntity pendingExtraction = get("/label/api/tasks/pending-review?page=1&pageSize=20&taskType=EXTRACTION", reviewerToken); assertSuccess(pendingExtraction, HttpStatus.OK); assertThat(responseContainsId(pendingExtraction, extractionTaskId)).isTrue(); - ResponseEntity extractionReject = postJson("/api/extraction/" + extractionTaskId + "/reject", + ResponseEntity extractionReject = postJson("/label/api/extraction/" + extractionTaskId + "/reject", Map.of("reason", "黑盒驳回一次"), reviewerToken); assertSuccess(extractionReject, HttpStatus.OK); - ResponseEntity reclaim = postJson("/api/tasks/" + extractionTaskId + "/reclaim", null, annotatorToken); + ResponseEntity reclaim = postJson("/label/api/tasks/" + extractionTaskId + "/reclaim", null, annotatorToken); assertSuccess(reclaim, HttpStatus.OK); - assertSuccess(putJson("/api/extraction/" + extractionTaskId, + assertSuccess(putJson("/label/api/extraction/" + extractionTaskId, "{\"items\":[{\"label\":\"entity\",\"text\":\"上海\"}]}", annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/extraction/" + extractionTaskId + "/submit", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/extraction/" + extractionTaskId + "/submit", null, annotatorToken), HttpStatus.OK); - ResponseEntity extractionApprove = postJson("/api/extraction/" + extractionTaskId + "/approve", null, reviewerToken); + ResponseEntity extractionApprove = postJson("/label/api/extraction/" + extractionTaskId + "/approve", null, reviewerToken); assertSuccess(extractionApprove, HttpStatus.OK); Long qaTaskId = latestTaskId(sourceId, "QA_GENERATION"); assertThat(qaTaskId).isNotNull(); - assertSuccess(postJson("/api/tasks/" + qaTaskId + "/claim", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/tasks/" + qaTaskId + "/claim", null, annotatorToken), HttpStatus.OK); - ResponseEntity qaGet = get("/api/qa/" + qaTaskId, annotatorToken); + ResponseEntity qaGet = get("/label/api/qa/" + qaTaskId, annotatorToken); assertSuccess(qaGet, HttpStatus.OK); - ResponseEntity qaPut = putJson("/api/qa/" + qaTaskId, + ResponseEntity qaPut = putJson("/label/api/qa/" + qaTaskId, Map.of("items", List.of(Map.of("question", "北京在哪里", "answer", "中国"))), annotatorToken); assertSuccess(qaPut, HttpStatus.OK); - ResponseEntity qaSubmit = postJson("/api/qa/" + qaTaskId + "/submit", null, annotatorToken); + ResponseEntity qaSubmit = postJson("/label/api/qa/" + qaTaskId + "/submit", null, annotatorToken); assertSuccess(qaSubmit, HttpStatus.OK); - ResponseEntity pendingQa = get("/api/tasks/pending-review?page=1&pageSize=20&taskType=QA_GENERATION", reviewerToken); + ResponseEntity pendingQa = get("/label/api/tasks/pending-review?page=1&pageSize=20&taskType=QA_GENERATION", reviewerToken); assertSuccess(pendingQa, HttpStatus.OK); assertThat(responseContainsId(pendingQa, qaTaskId)).isTrue(); - ResponseEntity qaApprove = postJson("/api/qa/" + qaTaskId + "/approve", null, reviewerToken); + ResponseEntity qaApprove = postJson("/label/api/qa/" + qaTaskId + "/approve", null, reviewerToken); assertSuccess(qaApprove, HttpStatus.OK); - ResponseEntity samples = get("/api/training/samples?page=1&pageSize=20&sampleType=TEXT", adminToken); + ResponseEntity samples = get("/label/api/training/samples?page=1&pageSize=20&sampleType=TEXT", adminToken); assertSuccess(samples, HttpStatus.OK); Long datasetId = latestApprovedDatasetId(sourceId); - ResponseEntity createBatch = postJson("/api/export/batch", + ResponseEntity createBatch = postJson("/label/api/export/batch", Map.of("sampleIds", List.of(datasetId)), adminToken); assertSuccess(createBatch, HttpStatus.CREATED); Long batchId = dataId(createBatch); - ResponseEntity exportList = get("/api/export/list?page=1&pageSize=20", adminToken); + ResponseEntity exportList = get("/label/api/export/list?page=1&pageSize=20", adminToken); assertSuccess(exportList, HttpStatus.OK); assertThat(responseContainsId(exportList, batchId)).isTrue(); - ResponseEntity exportStatus = get("/api/export/" + batchId + "/status", adminToken); + ResponseEntity exportStatus = get("/label/api/export/" + batchId + "/status", adminToken); assertSuccess(exportStatus, HttpStatus.OK); // 第二条链路覆盖 QA reject Long sourceId2 = uploadTextSource(uploaderToken); Long extractionTaskId2 = createTask(sourceId2, "EXTRACTION"); - assertSuccess(postJson("/api/tasks/" + extractionTaskId2 + "/claim", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/extraction/" + extractionTaskId2 + "/submit", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/extraction/" + extractionTaskId2 + "/approve", null, reviewerToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/tasks/" + extractionTaskId2 + "/claim", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/extraction/" + extractionTaskId2 + "/submit", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/extraction/" + extractionTaskId2 + "/approve", null, reviewerToken), HttpStatus.OK); Long qaTaskId2 = latestTaskId(sourceId2, "QA_GENERATION"); - assertSuccess(postJson("/api/tasks/" + qaTaskId2 + "/claim", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/qa/" + qaTaskId2 + "/submit", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/tasks/" + qaTaskId2 + "/claim", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/qa/" + qaTaskId2 + "/submit", null, annotatorToken), HttpStatus.OK); - ResponseEntity qaReject = postJson("/api/qa/" + qaTaskId2 + "/reject", + ResponseEntity qaReject = postJson("/label/api/qa/" + qaTaskId2 + "/reject", Map.of("reason", "黑盒问答驳回"), reviewerToken); assertSuccess(qaReject, HttpStatus.OK); } @@ -287,36 +287,36 @@ class SwaggerLiveBlackBoxTest extends AbstractBlackBoxTest { Long sourceId = uploadTextSource(uploaderToken); Long extractionTaskId = createTask(sourceId, "EXTRACTION"); - assertSuccess(postJson("/api/tasks/" + extractionTaskId + "/claim", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/extraction/" + extractionTaskId + "/submit", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/extraction/" + extractionTaskId + "/approve", null, reviewerToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/tasks/" + extractionTaskId + "/claim", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/extraction/" + extractionTaskId + "/submit", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/extraction/" + extractionTaskId + "/approve", null, reviewerToken), HttpStatus.OK); Long qaTaskId = latestTaskId(sourceId, "QA_GENERATION"); - assertSuccess(postJson("/api/tasks/" + qaTaskId + "/claim", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/qa/" + qaTaskId + "/submit", null, annotatorToken), HttpStatus.OK); - assertSuccess(postJson("/api/qa/" + qaTaskId + "/approve", null, reviewerToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/tasks/" + qaTaskId + "/claim", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/qa/" + qaTaskId + "/submit", null, annotatorToken), HttpStatus.OK); + assertSuccess(postJson("/label/api/qa/" + qaTaskId + "/approve", null, reviewerToken), HttpStatus.OK); Long datasetId = latestApprovedDatasetId(sourceId); - ResponseEntity createBatch = postJson("/api/export/batch", + ResponseEntity createBatch = postJson("/label/api/export/batch", Map.of("sampleIds", List.of(datasetId)), adminToken); assertSuccess(createBatch, HttpStatus.CREATED); Long batchId = dataId(createBatch); - ResponseEntity finetune = postJson("/api/export/" + batchId + "/finetune", null, adminToken); + ResponseEntity finetune = postJson("/label/api/export/" + batchId + "/finetune", null, adminToken); assertSuccess(finetune, HttpStatus.OK); Long videoSourceId = uploadVideoSource(uploaderToken); - ResponseEntity createVideoJob = postJson("/api/video/process", + ResponseEntity createVideoJob = postJson("/label/api/video/process", Map.of("sourceId", videoSourceId, "jobType", "FRAME_EXTRACT", "params", "{\"frameInterval\":30}"), adminToken); assertSuccess(createVideoJob, HttpStatus.OK); Long jobId = dataId(createVideoJob); - ResponseEntity getVideoJob = get("/api/video/jobs/" + jobId, adminToken); + ResponseEntity getVideoJob = get("/label/api/video/jobs/" + jobId, adminToken); assertSuccess(getVideoJob, HttpStatus.OK); Long failedJobId = insertFailedVideoJob(videoSourceId); - ResponseEntity resetJob = postJson("/api/video/jobs/" + failedJobId + "/reset", null, adminToken); + ResponseEntity resetJob = postJson("/label/api/video/jobs/" + failedJobId + "/reset", null, adminToken); assertSuccess(resetJob, HttpStatus.OK); Long callbackJobId = insertPendingVideoJob(videoSourceId); diff --git a/src/test/java/com/label/integration/AuthIntegrationTest.java b/src/test/java/com/label/integration/AuthIntegrationTest.java index 3964778..86b6155 100644 --- a/src/test/java/com/label/integration/AuthIntegrationTest.java +++ b/src/test/java/com/label/integration/AuthIntegrationTest.java @@ -21,8 +21,8 @@ import static org.assertj.core.api.Assertions.assertThat; * 1. 正确密码登录 → 返回 token * 2. 错误密码登录 → 401 * 3. 不存在的公司代码 → 401 - * 4. 有效 Token 访问 /api/auth/me → 200,返回用户信息 - * 5. 主动退出后,原 Token 访问 /api/auth/me → 401 + * 4. 有效 Token 访问 /label/api/auth/me → 200,返回用户信息 + * 5. 主动退出后,原 Token 访问 /label/api/auth/me → 401 * * 测试数据来自 init.sql 种子(DEMO 公司 / admin / admin123) */ @@ -74,7 +74,7 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { assertThat(token).isNotBlank(); ResponseEntity response = restTemplate.exchange( - baseUrl("/api/auth/me"), + baseUrl("/label/api/auth/me"), HttpMethod.GET, bearerRequest(token), Map.class); @@ -92,7 +92,7 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { @DisplayName("无 Token 访问 /api/auth/me → 401") void me_withNoToken_returns401() { ResponseEntity response = restTemplate.getForEntity( - baseUrl("/api/auth/me"), String.class); + baseUrl("/label/api/auth/me"), String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @@ -106,7 +106,7 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { // 确认登录有效 ResponseEntity meResponse = restTemplate.exchange( - baseUrl("/api/auth/me"), + baseUrl("/label/api/auth/me"), HttpMethod.GET, bearerRequest(token), Map.class); @@ -114,7 +114,7 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { // 退出 ResponseEntity logoutResponse = restTemplate.exchange( - baseUrl("/api/auth/logout"), + baseUrl("/label/api/auth/logout"), HttpMethod.POST, bearerRequest(token), Map.class); @@ -122,7 +122,7 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { // 退出后再访问 /me → 401 ResponseEntity meAfterLogout = restTemplate.exchange( - baseUrl("/api/auth/me"), + baseUrl("/label/api/auth/me"), HttpMethod.GET, bearerRequest(token), Map.class); @@ -137,7 +137,7 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { req.setCompanyCode(companyCode); req.setUsername(username); req.setPassword(password); - return restTemplate.postForEntity(baseUrl("/api/auth/login"), req, Map.class); + return restTemplate.postForEntity(baseUrl("/label/api/auth/login"), req, Map.class); } /** 登录并提取 token 字符串;失败时返回 null */ diff --git a/src/test/java/com/label/integration/ExportIntegrationTest.java b/src/test/java/com/label/integration/ExportIntegrationTest.java index 6be8c30..453c2de 100644 --- a/src/test/java/com/label/integration/ExportIntegrationTest.java +++ b/src/test/java/com/label/integration/ExportIntegrationTest.java @@ -109,7 +109,7 @@ public class ExportIntegrationTest extends AbstractIntegrationTest { Map.of("sampleIds", List.of(approvedDatasetId)), headers); ResponseEntity response = restTemplate.exchange( - baseUrl("/api/export/batch"), HttpMethod.POST, req, Map.class); + baseUrl("/label/api/export/batch"), HttpMethod.POST, req, Map.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); } @@ -126,7 +126,7 @@ public class ExportIntegrationTest extends AbstractIntegrationTest { Map.of("sampleIds", List.of()), headers); ResponseEntity response = restTemplate.exchange( - baseUrl("/api/export/batch"), HttpMethod.POST, req, Map.class); + baseUrl("/label/api/export/batch"), HttpMethod.POST, req, Map.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(response.getBody().get("code")).isEqualTo("EMPTY_SAMPLES"); @@ -143,7 +143,7 @@ public class ExportIntegrationTest extends AbstractIntegrationTest { Map.of("sampleIds", List.of(approvedDatasetId, pendingDatasetId)), headers); ResponseEntity response = restTemplate.exchange( - baseUrl("/api/export/batch"), HttpMethod.POST, req, Map.class); + baseUrl("/label/api/export/batch"), HttpMethod.POST, req, Map.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(response.getBody().get("code")).isEqualTo("INVALID_SAMPLES"); @@ -153,7 +153,7 @@ public class ExportIntegrationTest extends AbstractIntegrationTest { @DisplayName("查询已审批样本列表 → 200,包含 APPROVED 样本") void listSamples_adminOnly_returns200() { ResponseEntity response = restTemplate.exchange( - baseUrl("/api/training/samples"), + baseUrl("/label/api/training/samples"), HttpMethod.GET, bearerRequest(ADMIN_TOKEN), Map.class); diff --git a/src/test/java/com/label/integration/ExtractionApprovalIntegrationTest.java b/src/test/java/com/label/integration/ExtractionApprovalIntegrationTest.java index 7fa9d52..7458a29 100644 --- a/src/test/java/com/label/integration/ExtractionApprovalIntegrationTest.java +++ b/src/test/java/com/label/integration/ExtractionApprovalIntegrationTest.java @@ -68,13 +68,13 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { // 1. 标注员领取任务 ResponseEntity claimResp = restTemplate.exchange( - baseUrl("/api/tasks/" + taskId + "/claim"), + baseUrl("/label/api/tasks/" + taskId + "/claim"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(claimResp.getStatusCode()).isEqualTo(HttpStatus.OK); // 2. 标注员提交标注 ResponseEntity submitResp = restTemplate.exchange( - baseUrl("/api/extraction/" + taskId + "/submit"), + baseUrl("/label/api/extraction/" + taskId + "/submit"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(submitResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -82,7 +82,7 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { // 注:ExtractionApprovedEventListener(@TransactionalEventListener AFTER_COMMIT) // 在同一线程中同步执行,HTTP 响应返回前已完成后续处理 ResponseEntity approveResp = restTemplate.exchange( - baseUrl("/api/extraction/" + taskId + "/approve"), + baseUrl("/label/api/extraction/" + taskId + "/approve"), HttpMethod.POST, bearerRequest(reviewerToken), Map.class); assertThat(approveResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -127,7 +127,7 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { String reviewerToken = loginAndGetToken("DEMO", "reviewer01", "review123"); ResponseEntity resp = restTemplate.exchange( - baseUrl("/api/extraction/" + taskId + "/approve"), + baseUrl("/label/api/extraction/" + taskId + "/approve"), HttpMethod.POST, bearerRequest(reviewerToken), Map.class); assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); @@ -147,9 +147,9 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { String reviewerToken = loginAndGetToken("DEMO", "reviewer01", "review123"); // 1. 标注员领取并提交 - restTemplate.exchange(baseUrl("/api/tasks/" + taskId + "/claim"), + restTemplate.exchange(baseUrl("/label/api/tasks/" + taskId + "/claim"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); - restTemplate.exchange(baseUrl("/api/extraction/" + taskId + "/submit"), + restTemplate.exchange(baseUrl("/label/api/extraction/" + taskId + "/submit"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); // 2. 审核员驳回(驳回原因必填) @@ -160,7 +160,7 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { Map.of("reason", "实体识别有误,请重新标注"), rejectHeaders); ResponseEntity rejectResp = restTemplate.exchange( - baseUrl("/api/extraction/" + taskId + "/reject"), + baseUrl("/label/api/extraction/" + taskId + "/reject"), HttpMethod.POST, rejectReq, Map.class); assertThat(rejectResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -171,7 +171,7 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { // 3. 标注员重领任务(REJECTED → IN_PROGRESS) ResponseEntity reclaimResp = restTemplate.exchange( - baseUrl("/api/tasks/" + taskId + "/reclaim"), + baseUrl("/label/api/tasks/" + taskId + "/reclaim"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(reclaimResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -182,7 +182,7 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { // 4. 标注员再次提交(IN_PROGRESS → SUBMITTED) ResponseEntity resubmitResp = restTemplate.exchange( - baseUrl("/api/extraction/" + taskId + "/submit"), + baseUrl("/label/api/extraction/" + taskId + "/submit"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(resubmitResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -200,7 +200,7 @@ public class ExtractionApprovalIntegrationTest extends AbstractIntegrationTest { req.setUsername(username); req.setPassword(password); ResponseEntity response = restTemplate.postForEntity( - baseUrl("/api/auth/login"), req, Map.class); + baseUrl("/label/api/auth/login"), req, Map.class); if (!response.getStatusCode().is2xxSuccessful()) { return null; } diff --git a/src/test/java/com/label/integration/MultiTenantIsolationTest.java b/src/test/java/com/label/integration/MultiTenantIsolationTest.java index 91c7f71..ea23f6c 100644 --- a/src/test/java/com/label/integration/MultiTenantIsolationTest.java +++ b/src/test/java/com/label/integration/MultiTenantIsolationTest.java @@ -109,7 +109,7 @@ public class MultiTenantIsolationTest extends AbstractIntegrationTest { @DisplayName("公司 A 只能查看本公司资料,看不到公司 B 的资料") void sourceList_companyA_cannotSeeCompanyBData() { ResponseEntity resp = restTemplate.exchange( - baseUrl("/api/source/list?page=1&pageSize=50"), + baseUrl("/label/api/source/list?page=1&pageSize=50"), HttpMethod.GET, bearerRequest(TOKEN_A), Map.class); @@ -133,7 +133,7 @@ public class MultiTenantIsolationTest extends AbstractIntegrationTest { @DisplayName("公司 B 只能查看本公司资料,看不到公司 A 的资料") void sourceList_companyB_cannotSeeCompanyAData() { ResponseEntity resp = restTemplate.exchange( - baseUrl("/api/source/list?page=1&pageSize=50"), + baseUrl("/label/api/source/list?page=1&pageSize=50"), HttpMethod.GET, bearerRequest(TOKEN_B), Map.class); @@ -157,14 +157,14 @@ public class MultiTenantIsolationTest extends AbstractIntegrationTest { headersA.setContentType(MediaType.APPLICATION_JSON); restTemplate.exchange( - baseUrl("/api/config/model_default"), + baseUrl("/label/api/config/model_default"), HttpMethod.PUT, new HttpEntity<>(Map.of("value", "glm-4-plus"), headersA), Map.class); // 公司 B 查询配置列表 ResponseEntity respB = restTemplate.exchange( - baseUrl("/api/config"), + baseUrl("/label/api/config"), HttpMethod.GET, bearerRequest(TOKEN_B), Map.class); diff --git a/src/test/java/com/label/integration/QaApprovalIntegrationTest.java b/src/test/java/com/label/integration/QaApprovalIntegrationTest.java index 9b18b1c..30413bd 100644 --- a/src/test/java/com/label/integration/QaApprovalIntegrationTest.java +++ b/src/test/java/com/label/integration/QaApprovalIntegrationTest.java @@ -78,19 +78,19 @@ public class QaApprovalIntegrationTest extends AbstractIntegrationTest { // 但 TaskController.getPool 只给 ANNOTATOR 显示 EXTRACTION/UNCLAIMED // QA 任务由 ANNOTATOR 直接领取(不经过任务池) ResponseEntity claimResp = restTemplate.exchange( - baseUrl("/api/tasks/" + taskId + "/claim"), + baseUrl("/label/api/tasks/" + taskId + "/claim"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(claimResp.getStatusCode()).isEqualTo(HttpStatus.OK); // 提交 QA 结果 ResponseEntity submitResp = restTemplate.exchange( - baseUrl("/api/qa/" + taskId + "/submit"), + baseUrl("/label/api/qa/" + taskId + "/submit"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(submitResp.getStatusCode()).isEqualTo(HttpStatus.OK); // 审批通过 ResponseEntity approveResp = restTemplate.exchange( - baseUrl("/api/qa/" + taskId + "/approve"), + baseUrl("/label/api/qa/" + taskId + "/approve"), HttpMethod.POST, bearerRequest(reviewerToken), Map.class); assertThat(approveResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -120,9 +120,9 @@ public class QaApprovalIntegrationTest extends AbstractIntegrationTest { String reviewerToken = loginAndGetToken("DEMO", "reviewer01", "review123"); // 领取并提交 - restTemplate.exchange(baseUrl("/api/tasks/" + taskId + "/claim"), + restTemplate.exchange(baseUrl("/label/api/tasks/" + taskId + "/claim"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); - restTemplate.exchange(baseUrl("/api/qa/" + taskId + "/submit"), + restTemplate.exchange(baseUrl("/label/api/qa/" + taskId + "/submit"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); // 驳回(驳回原因必填) @@ -133,7 +133,7 @@ public class QaApprovalIntegrationTest extends AbstractIntegrationTest { Map.of("reason", "问题描述不准确,请修改"), headers); ResponseEntity rejectResp = restTemplate.exchange( - baseUrl("/api/qa/" + taskId + "/reject"), + baseUrl("/label/api/qa/" + taskId + "/reject"), HttpMethod.POST, rejectReq, Map.class); assertThat(rejectResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -155,13 +155,13 @@ public class QaApprovalIntegrationTest extends AbstractIntegrationTest { // 标注员重领任务 ResponseEntity reclaimResp = restTemplate.exchange( - baseUrl("/api/tasks/" + taskId + "/reclaim"), + baseUrl("/label/api/tasks/" + taskId + "/reclaim"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(reclaimResp.getStatusCode()).isEqualTo(HttpStatus.OK); // 再次提交 ResponseEntity resubmitResp = restTemplate.exchange( - baseUrl("/api/qa/" + taskId + "/submit"), + baseUrl("/label/api/qa/" + taskId + "/submit"), HttpMethod.POST, bearerRequest(annotatorToken), Map.class); assertThat(resubmitResp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -179,7 +179,7 @@ public class QaApprovalIntegrationTest extends AbstractIntegrationTest { req.setUsername(username); req.setPassword(password); ResponseEntity response = restTemplate.postForEntity( - baseUrl("/api/auth/login"), req, Map.class); + baseUrl("/label/api/auth/login"), req, Map.class); if (!response.getStatusCode().is2xxSuccessful()) { return null; } diff --git a/src/test/java/com/label/integration/SourceIntegrationTest.java b/src/test/java/com/label/integration/SourceIntegrationTest.java index 71a8950..025f48a 100644 --- a/src/test/java/com/label/integration/SourceIntegrationTest.java +++ b/src/test/java/com/label/integration/SourceIntegrationTest.java @@ -68,7 +68,7 @@ public class SourceIntegrationTest extends AbstractIntegrationTest { @DisplayName("无 Token 访问上传接口 → 401") void upload_withoutToken_returns401() { ResponseEntity response = restTemplate.postForEntity( - baseUrl("/api/source/upload"), null, String.class); + baseUrl("/label/api/source/upload"), null, String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @@ -76,7 +76,7 @@ public class SourceIntegrationTest extends AbstractIntegrationTest { @DisplayName("UPLOADER 访问列表接口(无数据)→ 200,items 为空") void list_uploaderWithNoData_returnsEmptyList() { ResponseEntity response = restTemplate.exchange( - baseUrl("/api/source/list"), + baseUrl("/label/api/source/list"), HttpMethod.GET, bearerRequest(UPLOADER_TOKEN), Map.class); @@ -94,7 +94,7 @@ public class SourceIntegrationTest extends AbstractIntegrationTest { @DisplayName("ADMIN 访问列表接口(无数据)→ 200,items 为空") void list_adminWithNoData_returnsEmptyList() { ResponseEntity response = restTemplate.exchange( - baseUrl("/api/source/list"), + baseUrl("/label/api/source/list"), HttpMethod.GET, bearerRequest(ADMIN_TOKEN), Map.class); @@ -110,7 +110,7 @@ public class SourceIntegrationTest extends AbstractIntegrationTest { @DisplayName("删除不存在的资料 → 404") void delete_nonExistentSource_returns404() { ResponseEntity response = restTemplate.exchange( - baseUrl("/api/source/9999"), + baseUrl("/label/api/source/9999"), HttpMethod.DELETE, bearerRequest(ADMIN_TOKEN), Map.class); @@ -122,7 +122,7 @@ public class SourceIntegrationTest extends AbstractIntegrationTest { @DisplayName("非 ADMIN 删除资料 → 403 Forbidden") void delete_byUploader_returns403() { ResponseEntity response = restTemplate.exchange( - baseUrl("/api/source/9999"), + baseUrl("/label/api/source/9999"), HttpMethod.DELETE, bearerRequest(UPLOADER_TOKEN), Map.class); @@ -145,7 +145,7 @@ public class SourceIntegrationTest extends AbstractIntegrationTest { assertThat(sourceId).isNotNull(); ResponseEntity response = restTemplate.exchange( - baseUrl("/api/source/" + sourceId), + baseUrl("/label/api/source/" + sourceId), HttpMethod.DELETE, bearerRequest(ADMIN_TOKEN), Map.class); diff --git a/src/test/java/com/label/integration/SysConfigIntegrationTest.java b/src/test/java/com/label/integration/SysConfigIntegrationTest.java index 2eb6984..b861dd5 100644 --- a/src/test/java/com/label/integration/SysConfigIntegrationTest.java +++ b/src/test/java/com/label/integration/SysConfigIntegrationTest.java @@ -67,7 +67,7 @@ public class SysConfigIntegrationTest extends AbstractIntegrationTest { // 查询配置列表 ResponseEntity listResp = restTemplate.exchange( - baseUrl("/api/config"), + baseUrl("/label/api/config"), HttpMethod.GET, bearerRequest(ADMIN_TOKEN), Map.class); @@ -99,7 +99,7 @@ public class SysConfigIntegrationTest extends AbstractIntegrationTest { void globalConfig_usedWhenNoCompanyOverride() { // 不设置公司专属,直接查询列表 ResponseEntity listResp = restTemplate.exchange( - baseUrl("/api/config"), + baseUrl("/label/api/config"), HttpMethod.GET, bearerRequest(ADMIN_TOKEN), Map.class); @@ -170,7 +170,7 @@ public class SysConfigIntegrationTest extends AbstractIntegrationTest { : Map.of("value", value); return restTemplate.exchange( - baseUrl("/api/config/" + key), + baseUrl("/label/api/config/" + key), HttpMethod.PUT, new HttpEntity<>(body, headers), Map.class); diff --git a/src/test/java/com/label/integration/TaskClaimConcurrencyTest.java b/src/test/java/com/label/integration/TaskClaimConcurrencyTest.java index cbfbb77..fa65e44 100644 --- a/src/test/java/com/label/integration/TaskClaimConcurrencyTest.java +++ b/src/test/java/com/label/integration/TaskClaimConcurrencyTest.java @@ -97,7 +97,7 @@ public class TaskClaimConcurrencyTest extends AbstractIntegrationTest { HttpEntity request = new HttpEntity<>(headers); ResponseEntity response = restTemplate.exchange( - baseUrl("/api/tasks/" + taskId + "/claim"), + baseUrl("/label/api/tasks/" + taskId + "/claim"), HttpMethod.POST, request, Map.class); if (response.getStatusCode() == HttpStatus.OK) { diff --git a/src/test/java/com/label/integration/UserManagementIntegrationTest.java b/src/test/java/com/label/integration/UserManagementIntegrationTest.java index 439984e..bf8ce31 100644 --- a/src/test/java/com/label/integration/UserManagementIntegrationTest.java +++ b/src/test/java/com/label/integration/UserManagementIntegrationTest.java @@ -47,7 +47,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { headers.setContentType(MediaType.APPLICATION_JSON); ResponseEntity createResp = restTemplate.exchange( - baseUrl("/api/users"), + baseUrl("/label/api/users"), HttpMethod.POST, new HttpEntity<>(Map.of( "username", uniqueUsername, @@ -68,7 +68,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { // 3. 验证:ANNOTATOR 无法访问待审批队列(REVIEWER 专属)→ 403 ResponseEntity beforeRoleChange = restTemplate.exchange( - baseUrl("/api/tasks/pending-review"), + baseUrl("/label/api/tasks/pending-review"), HttpMethod.GET, bearerRequest(userToken), Map.class); @@ -76,7 +76,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { // 4. ADMIN 变更角色为 REVIEWER ResponseEntity roleResp = restTemplate.exchange( - baseUrl("/api/users/" + newUserId + "/role"), + baseUrl("/label/api/users/" + newUserId + "/role"), HttpMethod.PUT, new HttpEntity<>(Map.of("role", "REVIEWER"), headers), Map.class); @@ -84,7 +84,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { // 5. 验证:同一 Token 下次请求立即具有 REVIEWER 权限 → 200 ResponseEntity afterRoleChange = restTemplate.exchange( - baseUrl("/api/tasks/pending-review"), + baseUrl("/label/api/tasks/pending-review"), HttpMethod.GET, bearerRequest(userToken), Map.class); @@ -106,7 +106,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { headers.setContentType(MediaType.APPLICATION_JSON); ResponseEntity createResp = restTemplate.exchange( - baseUrl("/api/users"), + baseUrl("/label/api/users"), HttpMethod.POST, new HttpEntity<>(Map.of( "username", uniqueUsername, @@ -127,7 +127,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { // 3. 验证 Token 有效 ResponseEntity meResp = restTemplate.exchange( - baseUrl("/api/auth/me"), + baseUrl("/label/api/auth/me"), HttpMethod.GET, bearerRequest(userToken), Map.class); @@ -135,7 +135,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { // 4. ADMIN 禁用账号 ResponseEntity disableResp = restTemplate.exchange( - baseUrl("/api/users/" + newUserId + "/status"), + baseUrl("/label/api/users/" + newUserId + "/status"), HttpMethod.PUT, new HttpEntity<>(Map.of("status", "DISABLED"), headers), Map.class); @@ -143,7 +143,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { // 5. 验证:禁用后,现有 Token 立即失效 → 401 ResponseEntity meAfterDisable = restTemplate.exchange( - baseUrl("/api/auth/me"), + baseUrl("/label/api/auth/me"), HttpMethod.GET, bearerRequest(userToken), Map.class); @@ -160,7 +160,7 @@ public class UserManagementIntegrationTest extends AbstractIntegrationTest { req.setUsername(username); req.setPassword(password); ResponseEntity response = restTemplate.postForEntity( - baseUrl("/api/auth/login"), req, Map.class); + baseUrl("/label/api/auth/login"), req, Map.class); if (!response.getStatusCode().is2xxSuccessful()) { return null; } diff --git a/src/test/java/com/label/integration/VideoCallbackIdempotencyTest.java b/src/test/java/com/label/integration/VideoCallbackIdempotencyTest.java index 8cc07ff..21e4802 100644 --- a/src/test/java/com/label/integration/VideoCallbackIdempotencyTest.java +++ b/src/test/java/com/label/integration/VideoCallbackIdempotencyTest.java @@ -147,7 +147,7 @@ public class VideoCallbackIdempotencyTest extends AbstractIntegrationTest { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer " + ADMIN_TOKEN); ResponseEntity resp = restTemplate.exchange( - baseUrl("/api/video/jobs/" + jobId + "/reset"), + baseUrl("/label/api/video/jobs/" + jobId + "/reset"), HttpMethod.POST, new HttpEntity<>(headers), Map.class); @@ -175,7 +175,7 @@ public class VideoCallbackIdempotencyTest extends AbstractIntegrationTest { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return restTemplate.exchange( - baseUrl("/api/video/callback"), + baseUrl("/label/api/video/callback"), HttpMethod.POST, new HttpEntity<>(body, headers), Map.class); diff --git a/src/test/java/com/label/unit/AuthInterceptorTest.java b/src/test/java/com/label/unit/AuthInterceptorTest.java index 932dca7..73b775c 100644 --- a/src/test/java/com/label/unit/AuthInterceptorTest.java +++ b/src/test/java/com/label/unit/AuthInterceptorTest.java @@ -50,7 +50,7 @@ class AuthInterceptorTest { "username", "admin" )); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/test/admin"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/label/api/test/admin"); request.addHeader("Authorization", "Bearer valid-token"); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -76,7 +76,7 @@ class AuthInterceptorTest { "username", "admin" )); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/test/reviewer"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/label/api/test/reviewer"); request.addHeader("Authorization", "Bearer admin-token"); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -95,7 +95,7 @@ class AuthInterceptorTest { "username", "annotator" )); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/test/reviewer"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/label/api/test/reviewer"); request.addHeader("Authorization", "Bearer annotator-token"); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -107,7 +107,7 @@ class AuthInterceptorTest { @DisplayName("缺少 Token 时返回 401") void missingTokenReturnsUnauthorized() throws Exception { ReflectionTestUtils.setField(interceptor, "authEnabled", true); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/test/admin"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/label/api/test/admin"); MockHttpServletResponse response = new MockHttpServletResponse(); assertThat(interceptor.preHandle(request, response, handler("adminOnly"))).isFalse();