forked from jsl/video_editing_poc
I continued with the security-review step from the plan and tightened the API contract so internal storage locations no longer leak out of normal responses.
Changes: - src/main/java/org/example/videoclips/application/VideoAssetService.java:401 no longer exposes sourceObjectKey on asset reads or objectKey on clip listings. - src/main/java/org/example/videoclips/processing/ClipProcessor.java:64 now records a sanitized SOURCE_MATERIALIZED event message instead of logging the worker-local path. - src/test/java/org/example/videoclips/api/VideoAssetControllerTest.java:67 now asserts those fields are absent and that job events do not contain uploads/ or tmp/.
This commit is contained in:
parent
73070824df
commit
0d45f898f7
|
|
@ -405,7 +405,6 @@ public class VideoAssetService {
|
|||
response.put("contentType", asset.contentType());
|
||||
response.put("contentLengthBytes", asset.contentLengthBytes());
|
||||
response.put("clipProfile", asset.clipProfile());
|
||||
response.put("sourceObjectKey", asset.sourceObjectKey());
|
||||
response.put("status", asset.status().name());
|
||||
response.put("uploadId", asset.uploadId());
|
||||
response.put("sourceDurationSeconds", asset.sourceDurationSeconds());
|
||||
|
|
@ -417,7 +416,6 @@ public class VideoAssetService {
|
|||
private Map<String, Object> toClipResponse(Clip clip) {
|
||||
return Map.of(
|
||||
"clipId", clip.id(),
|
||||
"objectKey", clip.objectKey(),
|
||||
"clipIndex", clip.clipIndex(),
|
||||
"startSeconds", clip.startSeconds(),
|
||||
"durationSeconds", clip.durationSeconds(),
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class ClipProcessor {
|
|||
}
|
||||
localInputPath = Path.of(properties.getFfmpeg().getInputDirectory()).resolve(asset.sourceObjectKey());
|
||||
objectStoragePort.materializeSourceObject(asset.sourceObjectKey(), localInputPath);
|
||||
recordEvent(jobId, "SOURCE_MATERIALIZED", "Source object staged to " + localInputPath);
|
||||
recordEvent(jobId, "SOURCE_MATERIALIZED", "Source object staged to worker input storage");
|
||||
generatedClips = videoClipperPort.generateClips(
|
||||
jobId,
|
||||
asset.id(),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
|
|||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.isOneOf;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
|
|
@ -65,7 +67,7 @@ class VideoAssetControllerTest {
|
|||
mockMvc.perform(get("/v1/video-assets/{assetId}", assetId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.assetId").value(assetId))
|
||||
.andExpect(jsonPath("$.sourceObjectKey").value("uploads/" + uploadId + "/source"))
|
||||
.andExpect(jsonPath("$.sourceObjectKey").doesNotExist())
|
||||
.andExpect(jsonPath("$.status").value("UPLOADED"));
|
||||
|
||||
mockMvc.perform(get("/v1/video-assets/{assetId}/upload-session", assetId))
|
||||
|
|
@ -121,11 +123,16 @@ class VideoAssetControllerTest {
|
|||
mockMvc.perform(get("/v1/clip-jobs/{jobId}/clips", jobId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.clips.length()", greaterThanOrEqualTo(3)))
|
||||
.andExpect(jsonPath("$.clips[0].objectKey").exists());
|
||||
.andExpect(jsonPath("$.clips[0].objectKey").doesNotExist());
|
||||
|
||||
mockMvc.perform(get("/v1/clip-jobs/{jobId}/events", jobId))
|
||||
MvcResult eventsResult = mockMvc.perform(get("/v1/clip-jobs/{jobId}/events", jobId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.events.length()", greaterThanOrEqualTo(1)));
|
||||
.andExpect(jsonPath("$.events.length()", greaterThanOrEqualTo(1)))
|
||||
.andReturn();
|
||||
|
||||
String eventsBody = eventsResult.getResponse().getContentAsString();
|
||||
assertFalse(eventsBody.contains("uploads/"));
|
||||
assertFalse(eventsBody.contains("tmp/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -220,18 +227,19 @@ class VideoAssetControllerTest {
|
|||
|
||||
String clipsResponse = mockMvc.perform(get("/v1/clip-jobs/{jobId}/clips", jobId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.clips[0].objectKey").doesNotExist())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getContentAsString();
|
||||
|
||||
String clipId = JsonTestHelper.read(clipsResponse, "$.clips[0].clipId");
|
||||
String objectKey = JsonTestHelper.read(clipsResponse, "$.clips[0].objectKey");
|
||||
|
||||
mockMvc.perform(post("/v1/clips/{clipId}/download-url", clipId)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.clipId").value(clipId))
|
||||
.andExpect(jsonPath("$.url").value(org.hamcrest.Matchers.containsString(objectKey)));
|
||||
.andExpect(jsonPath("$.downloadUrl").exists())
|
||||
.andExpect(jsonPath("$.expiresAt").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue