package jnpf.bizcommon.onlyoffice.service.impl; import jnpf.dmsEntity.download.model.DmsFileDownloadTicket; import jnpf.dmsEntity.preview.model.DmsWatermarkSnapshot; import jnpf.dmsEntity.preview.model.DmsFilePreviewTicket; import jnpf.exception.DataException; import jnpf.onlyoffice.DmsDownloadPdfRequest; import jnpf.util.JsonUtil; import org.junit.Test; import java.util.List; import java.util.UUID; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class DmsOnlyOfficeDownloadServiceTest { private static final UUID VERSION = UUID.randomUUID(); @Test public void preservesDownloadWatermarkSnapshotAndTicket() { DmsFileDownloadTicket ticket = ticket(); DmsWatermarkSnapshot mark = new DmsWatermarkSnapshot(); mark.setContent("REC-004"); mark.setBarcodeText("Page four"); mark.setRenderPages(List.of(4)); ticket.setWatermarks(List.of(mark, mark)); OnlyOfficeDmsPrintRenderer renderer = mock(OnlyOfficeDmsPrintRenderer.class); when(renderer.render(any(), eq("internal-source"))).thenReturn(new byte[]{1, 2}); java.util.List revoked = new java.util.ArrayList<>(); DmsOnlyOfficeDownloadService service = new DmsOnlyOfficeDownloadService(renderer, value -> JsonUtil.getObjectToString(ticket), source -> { assertEquals(ticket.getFileVersionId(), source.getFileVersionId()); assertEquals(ticket.getTenantId(), source.getTenantId()); assertEquals(ticket.getUserId(), source.getUserId()); assertEquals(ticket.getObjectName(), source.getObjectName()); assertEquals(ticket.getWatermarks(), source.getWatermarks()); assertEquals(DmsFilePreviewTicket.SCOPE, source.getScope()); assertTrue(source.getExpiresAt() <= ticket.getExpiresAt()); assertTrue(source.getExpiresAt() > System.currentTimeMillis()); return "internal-source"; }, revoked::add); assertArrayEquals(new byte[]{1, 2}, service.render(new DmsDownloadPdfRequest(VERSION, "download-ticket"))); verify(renderer).render(any(), eq("internal-source")); assertEquals(List.of("internal-source"), revoked); assertEquals(DmsFileDownloadTicket.SCOPE, ticket.getScope()); } @Test public void conversionFailureAlsoRevokesTheDelegatedTicket() { OnlyOfficeDmsPrintRenderer renderer = mock(OnlyOfficeDmsPrintRenderer.class); when(renderer.render(any(), anyString())).thenThrow(new DataException("OnlyOffice 文件转换失败")); java.util.List revoked = new java.util.ArrayList<>(); DmsOnlyOfficeDownloadService service = new DmsOnlyOfficeDownloadService(renderer, value -> JsonUtil.getObjectToString(ticket()), source -> "internal-source", revoked::add); try { service.render(new DmsDownloadPdfRequest(VERSION, "ticket")); fail("expected conversion failure"); } catch (DataException expected) { assertEquals("OnlyOffice 文件转换失败", expected.getMessage()); } assertEquals(List.of("internal-source"), revoked); } @Test public void rejectsExpiredWrongScopeWrongVersionAndNonDocxTicketsBeforeRendering() { OnlyOfficeDmsPrintRenderer renderer = mock(OnlyOfficeDmsPrintRenderer.class); for (int scenario = 0; scenario < 5; scenario++) { DmsFileDownloadTicket ticket = ticket(); switch (scenario) { case 0: ticket.setExpiresAt(System.currentTimeMillis() - 1); break; case 1: ticket.setScope("dms:onlyoffice:preview"); break; case 2: ticket.setScope("dms:onlyoffice:print"); break; case 3: ticket.setFileVersionId(UUID.randomUUID()); break; case 4: ticket.setFileName("quality.txt"); break; } DmsOnlyOfficeDownloadService service = new DmsOnlyOfficeDownloadService(renderer, value -> JsonUtil.getObjectToString(ticket), source -> { fail("invalid download must not issue source tickets"); return null; }, value -> fail("no source ticket to revoke")); try { service.render(new DmsDownloadPdfRequest(VERSION, "ticket")); fail("invalid ticket accepted"); } catch (DataException expected) { assertNotNull(expected.getMessage()); } } verifyNoInteractions(renderer); } private DmsFileDownloadTicket ticket() { DmsFileDownloadTicket ticket = new DmsFileDownloadTicket(); ticket.setScope(DmsFileDownloadTicket.SCOPE); ticket.setTenantId("tenant-1"); ticket.setUserId("user-1"); ticket.setFileVersionId(VERSION); ticket.setFileName("quality.docx"); ticket.setStoragePlatform("seaweedfs-1"); ticket.setBucketName("jnpf-dms"); ticket.setObjectPath("synthetic/"); ticket.setObjectName("quality.docx"); ticket.setExpiresAt(System.currentTimeMillis() + 60_000); return ticket; } }