fix(file): bind loading evidence to cabinet
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package com.baiyue.file.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class LoadingEvidenceFileContractTest {
|
||||
@Test
|
||||
void freezesPhysicalContainerOwnershipWithoutInboundCompatibilityPath() throws Exception {
|
||||
String yaml = Files.readString(Path.of("src/main/resources/openapi/loading-evidence-v1.yaml"));
|
||||
|
||||
assertThat(yaml)
|
||||
.contains("/api/platform/v1/files/loading-evidence/{containerBookingId}:")
|
||||
.contains("/internal/file/v1/loading-evidence/{containerBookingId}:")
|
||||
.contains("ownerScope: {type: string, enum: [PLATFORM]}")
|
||||
.contains("tenantId: {type: string, enum: ['0']}")
|
||||
.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")
|
||||
.doesNotContain("/{tenantId}/{inboundId}", "businessId=inboundId");
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -21,32 +21,32 @@ class InternalLoadingEvidenceControllerTest {
|
||||
@Resource InternalLoadingEvidenceController controller;
|
||||
|
||||
@Test void downloadsOwnedEvidenceBehindInternalToken() {
|
||||
when(service.download(81L, 91L, 101L)).thenReturn(
|
||||
when(service.download(91L, 101L)).thenReturn(
|
||||
new LoadingEvidenceService.Download("door.jpg", "image/jpeg", new byte[]{1, 2, 3}));
|
||||
|
||||
var response = controller.download("internal-token", 81L, 91L, 101L);
|
||||
var response = controller.download("internal-token", 91L, 101L);
|
||||
|
||||
assertThat(response.getBody()).containsExactly(1, 2, 3);
|
||||
assertThat(response.getHeaders().getContentType().toString()).isEqualTo("image/jpeg");
|
||||
assertThat(response.getHeaders().getCacheControl()).contains("no-store");
|
||||
verify(service).download(81L, 91L, 101L);
|
||||
verify(service).download(91L, 101L);
|
||||
}
|
||||
|
||||
@Test void rejectsInvalidTokenBeforeReadingEvidence() {
|
||||
assertThatThrownBy(() -> controller.download("wrong", 81L, 91L, 101L))
|
||||
assertThatThrownBy(() -> controller.download("wrong", 91L, 101L))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("凭证无效");
|
||||
verifyNoInteractions(service);
|
||||
}
|
||||
|
||||
@Test void fallsBackForInvalidOrNonImageContentTypes() {
|
||||
when(service.download(81L, 91L, 101L)).thenReturn(
|
||||
when(service.download(91L, 101L)).thenReturn(
|
||||
new LoadingEvidenceService.Download("door.jpg", "not a/media/type", new byte[]{1}));
|
||||
when(service.download(81L, 91L, 102L)).thenReturn(
|
||||
when(service.download(91L, 102L)).thenReturn(
|
||||
new LoadingEvidenceService.Download("door.txt", "text/plain", new byte[]{2}));
|
||||
|
||||
assertThat(controller.download("internal-token", 81L, 91L, 101L).getHeaders().getContentType())
|
||||
assertThat(controller.download("internal-token", 91L, 101L).getHeaders().getContentType())
|
||||
.isEqualTo(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM);
|
||||
assertThat(controller.download("internal-token", 81L, 91L, 102L).getHeaders().getContentType())
|
||||
assertThat(controller.download("internal-token", 91L, 102L).getHeaders().getContentType())
|
||||
.isEqualTo(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
}
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.baiyue.file.controller;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
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 java.util.Set;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class PlatformLoadingEvidenceControllerTest {
|
||||
private final LoadingEvidenceService service = mock(LoadingEvidenceService.class);
|
||||
private final PlatformLoadingEvidenceController controller = new PlatformLoadingEvidenceController();
|
||||
|
||||
PlatformLoadingEvidenceControllerTest() throws Exception {
|
||||
var field = PlatformLoadingEvidenceController.class.getDeclaredField("service");
|
||||
field.setAccessible(true);
|
||||
field.set(controller, service);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uploadsPlatformOwnedContainerEvidence() {
|
||||
var file = new MockMultipartFile("file", "door.jpg", "image/jpeg", new byte[]{1});
|
||||
when(service.upload(91L, 7L, "PHOTO_STEP_1", file)).thenReturn(
|
||||
new LoadingEvidenceService.UploadResult(101L, "PLATFORM", 0L,
|
||||
"LOADING_PHOTO_STEP_1", "91", "door.jpg", "image/jpeg", 1L));
|
||||
|
||||
var response = controller.upload(platform(), 91L, "PHOTO_STEP_1", file);
|
||||
|
||||
assertThat(response.data()).extracting(LoadingEvidenceService.UploadResult::ownerScope,
|
||||
LoadingEvidenceService.UploadResult::tenantId, LoadingEvidenceService.UploadResult::businessId)
|
||||
.containsExactly("PLATFORM", 0L, "91");
|
||||
verify(service).upload(91L, 7L, "PHOTO_STEP_1", file);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsMerchantBeforeAccessingContainerEvidence() {
|
||||
assertThatThrownBy(() -> controller.download(merchant(), 91L, 101L))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("平台端身份");
|
||||
}
|
||||
|
||||
private static AuthenticatedUser platform() {
|
||||
return new AuthenticatedUser(7L, 0L, 0L, 7L, "operator", "PLATFORM", "PDA", Set.of());
|
||||
}
|
||||
|
||||
private static AuthenticatedUser merchant() {
|
||||
return new AuthenticatedUser(8L, 88L, 88L, 8L, "merchant", "MERCHANT", "WEB", Set.of());
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class LoadingEvidenceServiceTest {
|
||||
@@ -28,24 +29,36 @@ class LoadingEvidenceServiceTest {
|
||||
@Test
|
||||
void uploadsEvidenceWithDedicatedBusinessType() {
|
||||
var multipart = new MockMultipartFile("file", "step.jpg", "image/jpeg", new byte[]{1});
|
||||
when(storage.storeLoading(10, 20, multipart)).thenReturn(new MeasurementImageStorage.Stored(
|
||||
"loading-evidence/10/20/a.jpg", Path.of("a.jpg"), "image/jpeg", 1, "hash", "step.jpg"));
|
||||
var result = service.upload(10, 20, 7, "PHOTO_STEP_2", multipart);
|
||||
when(storage.storeLoading(0, 20, multipart)).thenReturn(new MeasurementImageStorage.Stored(
|
||||
"loading-evidence/0/20/a.jpg", Path.of("a.jpg"), "image/jpeg", 1, "hash", "step.jpg"));
|
||||
var result = service.upload(20, 7, "PHOTO_STEP_2", multipart);
|
||||
assertThat(result.businessType()).isEqualTo("LOADING_PHOTO_STEP_2");
|
||||
verify(files).insert(any(FileObjectEntity.class));
|
||||
assertThat(result.ownerScope()).isEqualTo("PLATFORM");
|
||||
assertThat(result.tenantId()).isZero();
|
||||
assertThat(result.businessId()).isEqualTo("20");
|
||||
var object = ArgumentCaptor.forClass(FileObjectEntity.class);
|
||||
verify(files).insert(object.capture());
|
||||
assertThat(object.getValue()).extracting(FileObjectEntity::getTenantId,
|
||||
FileObjectEntity::getBusinessId, FileObjectEntity::getBucketName)
|
||||
.containsExactly(0L, "20", "loading-evidence");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsUnknownEvidenceType() {
|
||||
var multipart = new MockMultipartFile("file", "x.jpg", "image/jpeg", new byte[]{1});
|
||||
assertThatThrownBy(() -> service.upload(10, 20, 7, "UNKNOWN", multipart)).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> service.upload(20, 7, "UNKNOWN", multipart)).isInstanceOf(BizException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatesTenantBoundFile() {
|
||||
FileObjectEntity object = new FileObjectEntity();
|
||||
object.setId(30L); object.setOriginalName("seal.jpg"); object.setBusinessType("LOADING_SEAL"); object.setContentType("image/jpeg");
|
||||
object.setId(30L); object.setTenantId(0L); object.setBusinessId("20");
|
||||
object.setOriginalName("seal.jpg"); object.setBusinessType("LOADING_SEAL"); object.setContentType("image/jpeg");
|
||||
when(files.selectOne(any(Wrapper.class))).thenReturn(object);
|
||||
assertThat(service.validate(10, 20, 30).fileId()).isEqualTo(30L);
|
||||
var metadata = service.validate(20, 30);
|
||||
assertThat(metadata.fileId()).isEqualTo(30L);
|
||||
assertThat(metadata.ownerScope()).isEqualTo("PLATFORM");
|
||||
assertThat(metadata.tenantId()).isZero();
|
||||
assertThat(metadata.businessId()).isEqualTo("20");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user