fix(file): require Firstleg for PDA evidence access
This commit is contained in:
+2
-2
@@ -21,7 +21,7 @@ public class PlatformLoadingEvidenceController {
|
||||
@Resource private LoadingEvidenceService service;
|
||||
|
||||
@PostMapping(value = "/{containerBookingId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PreAuthorize("hasAnyAuthority('platform:firstleg:inbound:loading:edit','platform:firstleg:pda:work')")
|
||||
@PreAuthorize("hasAuthority('platform:firstleg:inbound:loading:edit')")
|
||||
public ApiResponse<LoadingEvidenceService.UploadResult> upload(
|
||||
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable long containerBookingId,
|
||||
@RequestParam String evidenceType, @RequestPart("file") MultipartFile file) {
|
||||
@@ -30,7 +30,7 @@ public class PlatformLoadingEvidenceController {
|
||||
}
|
||||
|
||||
@GetMapping("/{containerBookingId}/{fileId}")
|
||||
@PreAuthorize("hasAnyAuthority('platform:firstleg:inbound:loading:view','platform:firstleg:pda:work')")
|
||||
@PreAuthorize("hasAuthority('platform:firstleg:inbound:loading:view')")
|
||||
public ResponseEntity<byte[]> download(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@PathVariable long containerBookingId, @PathVariable long fileId) {
|
||||
requirePlatform(user); requirePositive(containerBookingId, fileId);
|
||||
|
||||
@@ -13,11 +13,11 @@ paths:
|
||||
/api/platform/v1/files/loading-evidence/{containerBookingId}:
|
||||
post:
|
||||
tags: [LoadingEvidence]
|
||||
summary: 平台或PDA上传柜级装柜证据
|
||||
description: 不接受客户ID或入仓单ID;同一文件不得跨containerBookingId复用。
|
||||
x-required-any-permission:
|
||||
- platform:firstleg:inbound:loading:edit
|
||||
- platform:firstleg:pda:work
|
||||
summary: Admin上传柜级装柜证据
|
||||
description: >-
|
||||
仅Admin装柜证据维护权限可直连;国内PDA禁止直连File,必须先调用Firstleg任务证据接口。
|
||||
不接受客户ID或入仓单ID;同一文件不得跨containerBookingId复用。
|
||||
x-required-permission: platform:firstleg:inbound:loading:edit
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/ContainerBookingId'
|
||||
- $ref: '#/components/parameters/EvidenceType'
|
||||
@@ -39,11 +39,11 @@ paths:
|
||||
/api/platform/v1/files/loading-evidence/{containerBookingId}/{fileId}:
|
||||
get:
|
||||
tags: [LoadingEvidence]
|
||||
summary: 平台或PDA下载柜级装柜证据
|
||||
description: 必须同时命中平台所有权、containerBookingId、fileId、LOADING_*类型和ACTIVE状态;响应禁止缓存。
|
||||
x-required-any-permission:
|
||||
- platform:firstleg:inbound:loading:view
|
||||
- platform:firstleg:pda:work
|
||||
summary: Admin下载柜级装柜证据
|
||||
description: >-
|
||||
仅Admin装柜证据读取权限可直连;国内PDA必须经Firstleg任务、仓库和操作者校验后,由Firstleg使用内部服务令牌下载。
|
||||
文件必须同时命中平台所有权、containerBookingId、fileId、五类LOADING业务类型和ACTIVE状态;响应禁止缓存。
|
||||
x-required-permission: platform:firstleg:inbound:loading:view
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/ContainerBookingId'
|
||||
- $ref: '#/components/parameters/FileId'
|
||||
|
||||
@@ -20,7 +20,10 @@ class LoadingEvidenceFileContractTest {
|
||||
.contains("description: 物理containerBookingId")
|
||||
.contains("LOADING_PHOTO_STEP_1", "LOADING_PHOTO_STEP_2", "LOADING_PHOTO_STEP_3",
|
||||
"LOADING_PHOTO_STEP_4", "LOADING_SEAL")
|
||||
.contains("x-required-any-permission:", "platform:firstleg:pda:work", "Cache-Control固定no-store")
|
||||
.contains("x-required-permission: platform:firstleg:inbound:loading:edit")
|
||||
.contains("x-required-permission: platform:firstleg:inbound:loading:view")
|
||||
.contains("国内PDA禁止直连File", "Cache-Control固定no-store")
|
||||
.doesNotContain("platform:firstleg:pda:work")
|
||||
.doesNotContain("/{tenantId}/{inboundId}", "businessId=inboundId");
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -5,6 +5,8 @@ import com.baiyue.common.security.AuthenticatedUser;
|
||||
import com.baiyue.file.service.LoadingEvidenceService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -45,6 +47,21 @@ class PlatformLoadingEvidenceControllerTest {
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("平台端身份");
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformEndpointsExcludePdaWorkPermission() throws Exception {
|
||||
var upload = PlatformLoadingEvidenceController.class.getMethod("upload", AuthenticatedUser.class,
|
||||
long.class, String.class, MultipartFile.class);
|
||||
var download = PlatformLoadingEvidenceController.class.getMethod("download", AuthenticatedUser.class,
|
||||
long.class, long.class);
|
||||
|
||||
assertThat(upload.getAnnotation(PreAuthorize.class).value())
|
||||
.isEqualTo("hasAuthority('platform:firstleg:inbound:loading:edit')")
|
||||
.doesNotContain("pda:work");
|
||||
assertThat(download.getAnnotation(PreAuthorize.class).value())
|
||||
.isEqualTo("hasAuthority('platform:firstleg:inbound:loading:view')")
|
||||
.doesNotContain("pda:work");
|
||||
}
|
||||
|
||||
private static AuthenticatedUser platform() {
|
||||
return new AuthenticatedUser(7L, 0L, 0L, 7L, "operator", "PLATFORM", "PDA", Set.of());
|
||||
}
|
||||
|
||||
@@ -61,4 +61,10 @@ class LoadingEvidenceServiceTest {
|
||||
assertThat(metadata.tenantId()).isZero();
|
||||
assertThat(metadata.businessId()).isEqualTo("20");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsFileWhenContainerBookingDoesNotMatch() {
|
||||
assertThatThrownBy(() -> service.validate(21, 30))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("装柜证据文件不存在");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user