diff --git a/pluto-interface/pom.xml b/pluto-interface/pom.xml index 8eb49f511081edb714e0e765695dccb630e0289e..89d77e957f1b5e2988827d4cd082c28681045fa7 100644 --- a/pluto-interface/pom.xml +++ b/pluto-interface/pom.xml @@ -6,6 +6,7 @@ <groupId>de.itvsh.ozg.pluto</groupId> <artifactId>pluto-interface</artifactId> <version>0.24.0-SNAPSHOT</version> + <name>Pluto Interface</name> <description>Interface (gRPC) for Pluto Server</description> diff --git a/pluto-server/pom.xml b/pluto-server/pom.xml index 099275d17b573d74b86cd0de8dc179855a78cd1c..c81aed5faeecd886c0e126d1f8ccbab7860b3281 100644 --- a/pluto-server/pom.xml +++ b/pluto-server/pom.xml @@ -14,6 +14,7 @@ <groupId>de.itvsh.ozg.pluto</groupId> <artifactId>pluto-server</artifactId> <version>0.24.0-SNAPSHOT</version> + <name>Pluto Server</name> <description>Server Implementierung des VorgangManagers (Pluto)</description> diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java index cf86b7f1fb81d32dfb0c78ecd800b97241be9bbe..5db571ced9cee628a54298b689372e8b0ee6acf7 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java @@ -19,7 +19,6 @@ import com.mongodb.client.gridfs.GridFSBuckets; import com.mongodb.client.gridfs.model.GridFSUploadOptions; import de.itvsh.kop.common.errorhandling.TechnicalException; -import de.itvsh.ozg.mail.postfach.PostfachMail; import io.mongock.api.annotations.ChangeUnit; import io.mongock.api.annotations.Execution; import io.mongock.api.annotations.RollbackExecution; @@ -67,7 +66,7 @@ public class M001_MigrateMailServiceAttachmentsToGridFs { // NOSONAR @SuppressWarnings("unchecked") private List<String> getAttachmentIds(Document attachedItem) { - return (List<String>) attachedItem.get(ATTACHED_ITEM, Document.class).get(PostfachMail.FIELD_ATTACHMENTS); + return (List<String>) attachedItem.get(ATTACHED_ITEM, Document.class).get("attachments"); } private void doMigration(final MongoTemplate template, GridFSBucket gridFs, String attachment) { diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java index aa797f49cdbc2f3673b17a01b43a3e4bc1ab89ae..0842a3f5a4bb2fd5b77d3fdd47cd5939af6e84e7 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java @@ -36,7 +36,7 @@ public class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs { // NOSON private static final String FILES_FIELD = "files"; static final String CLIENT = "client"; - static final String CLIENT_VALUE = "goofy"; + static final String CLIENT_VALUE = "eingangManager"; static final String CONTENT_TYPE = "contentType"; static final String FILE_FIELD_NAME = "fieldName"; static final String ATTACHMENT_FIELD_NAME_VALUE = "vorgangAttachment"; @@ -57,7 +57,6 @@ public class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs { // NOSON getAttachments(vorgang).stream().flatMap(attachment -> getFiles(attachment).stream()) .filter(Objects::nonNull) .forEach(file -> doMigration(template, gridFsBucket, file, vorgang, ATTACHMENT_FIELD_NAME_VALUE)); - getRepresentations(vorgang).stream() .forEach(file -> doMigration(template, gridFsBucket, file, vorgang, REPRESENTATION_FIELD_NAME_VALUE)); }); diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java index 33f900b7e59047d473fcb6a00c6758c77909966a..9705ecd1b77090552cc5be6f954195d2dcb330c8 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java @@ -7,7 +7,7 @@ import lombok.ToString; @Builder @Getter -@ToString(exclude = "content") +@ToString public class IncomingFile { private FileId id; @@ -15,5 +15,4 @@ public class IncomingFile { private String name; private String contentType; private long size; - private byte[] content; } diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java index 42ada77408f089a0526326e5d1fcc4740e1e9db0..735b57e08a3d4a33a6a99cf907c18783a1bb5842 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java @@ -5,10 +5,12 @@ import java.io.IOException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.MimeTypeUtils; import de.itvsh.ozg.mail.common.errorhandling.TechnicalException; +import de.itvsh.ozg.pluto.files.FileService; import de.itvsh.ozg.pluto.vorgang.Eingang; import de.itvsh.ozg.pluto.vorgang.IncomingFile; import de.itvsh.ozg.pluto.vorgang.IncomingFileGroup; @@ -21,6 +23,9 @@ import net.lingala.zip4j.model.enums.EncryptionMethod; @Service class ZipBuilderService { + @Autowired + private FileService fileService; + public ByteArrayOutputStream buildVorgangZip(Vorgang vorgang, char[] password, boolean encrypted) { return new ZipBuilder(vorgang, encrypted).buildZip(password); } @@ -89,7 +94,7 @@ class ZipBuilderService { try { zipOut.putNextEntry(buildZipParameter(fileName)); - IOUtils.write(file.getContent(), zipOut); + IOUtils.copy(fileService.getUploadedFileStream(file.getId()), zipOut); zipOut.closeEntry(); } catch (IOException e) { throw new TechnicalException("Error writing zip entry", e); diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java index 307c64faebdb20bcb835cbb31a22f0f432319019..23c9c733eb8c6302a0ccc2dc4d398a02f4234f20 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java @@ -6,9 +6,12 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.IOException; -import java.io.InputStream; +import org.apache.commons.lang3.StringUtils; +import org.bson.Document; +import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.Spy; import org.springframework.beans.factory.annotation.Autowired; @@ -20,17 +23,9 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate; import com.mongodb.client.gridfs.model.GridFSFile; import de.itvsh.kop.common.test.DataITCase; -import de.itvsh.kop.common.test.TestUtils; -import de.itvsh.ozg.pluto.files.OzgFileTestFactory; -import de.itvsh.ozg.pluto.vorgang.Eingang; -import de.itvsh.ozg.pluto.vorgang.EingangTestFactory; -import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory; -import de.itvsh.ozg.pluto.vorgang.Vorgang; -import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory; @DataITCase class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase {// NOSONAR - private static final String METADATA_VORGANG_ID = "metadata.vorgangId"; @Spy private M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs migrator = new M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs(); @@ -40,150 +35,252 @@ class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase {// NOSONAR @Autowired private GridFsTemplate gridFsTemplate; - private Vorgang migratedVorgang; - - private Vorgang notMigratedVorgang; + private ObjectId vorgangId; @BeforeEach - public void init() { - template.dropCollection(GRID_FS_FILE_COLLECTION); - template.dropCollection(VORGANG_COLLECTION); - - migratedVorgang = template.save(VorgangTestFactory.createBuilder().id(null).build()); - - Eingang eingangWithout = EingangTestFactory.createBuilder().clearAttachments().clearRepresentations().build(); - notMigratedVorgang = template.save(VorgangTestFactory.createBuilder().id(null).clearEingangs().eingang(eingangWithout).build()); - } - - @Test - void shouldHaveAttachmentFilePath() { - migrate(); - - var expectedPath = createFilePath(ATTACHMENT_FIELD_NAME_VALUE, IncomingFileTestFactory.NAME); - - var migratedPath = getMigratedAttachmentFile().getFilename(); - assertThat(migratedPath).isEqualTo(expectedPath); - } - - @Test - void shouldHaveAttachmentFileId() { - migrate(); - var attachments = getMigratedVorgang().getEingangs().get(0).getAttachments(); - var fileId = attachments.get(0).getFiles().get(0).getId().toString(); - - var migratedFileId = getMigratedAttachmentFile().getId().asObjectId().getValue().toHexString(); - assertThat(migratedFileId).isEqualTo(fileId); - } - - @Test - void shouldHaveRepresentationFilePath() { - migrate(); - - var expectedPath = createFilePath(REPRESENTATION_FIELD_NAME_VALUE, IncomingFileTestFactory.NAME); - - var migratedPath = getMigratedRepresentationFile().getFilename(); - assertThat(migratedPath).isEqualTo(expectedPath); - } - - @Test - void shouldHaveRepresentationFileId() { - migrate(); - var representations = getMigratedVorgang().getEingangs().get(0).getRepresentations(); - var fileId = representations.get(0).getId().toString(); - - var migratedFileId = getMigratedRepresentationFile().getId().asObjectId().getValue().toHexString(); - assertThat(migratedFileId).isEqualTo(fileId); - } - - @Test - void shouldHaveAttachmentMetadata() { - migrate(); - - var metadata = getMigratedAttachmentFile().getMetadata(); - assertThat(metadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE); - assertThat(metadata.getString(VORGANG_ID)).isEqualTo(migratedVorgang.getId()); - assertThat(metadata.getString(FILE_FIELD_NAME)).isEqualTo(ATTACHMENT_FIELD_NAME_VALUE); - assertThat(metadata.getString(CONTENT_TYPE)).isEqualTo(OzgFileTestFactory.CONTENT_TYPE); - assertThat(metadata.getString(FILE_NAME)).isEqualTo(IncomingFileTestFactory.NAME); - } + void init() { - @Test - void shouldHaveRepresentationMetadata() { - migrate(); - - var metadata = getMigratedRepresentationFile().getMetadata(); - assertThat(metadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE); - assertThat(metadata.getString(VORGANG_ID)).isEqualTo(migratedVorgang.getId()); - assertThat(metadata.getString(FILE_FIELD_NAME)).isEqualTo(REPRESENTATION_FIELD_NAME_VALUE); - assertThat(metadata.getString(CONTENT_TYPE)).isEqualTo(OzgFileTestFactory.CONTENT_TYPE); - assertThat(metadata.getString(FILE_NAME)).isEqualTo(IncomingFileTestFactory.NAME); - } - - @Test - void shouldHaveAttachmentContent() throws IOException { - migrate(); - - InputStream in = TestUtils.loadFile(IncomingFileTestFactory.NAME); - byte[] fileData = new byte[in.available()]; - in.read(fileData); - - var content = gridFsTemplate - .getResource(getMigratedAttachmentFile()) - .getContent().readAllBytes(); - assertThat(content).isEqualTo(fileData); - } + template.dropCollection(MigrationTestUtils.GRID_FS_FILES_COLLECTION); + template.dropCollection(MigrationTestUtils.GRID_FS_CHUNKS_COLLECTION); + template.dropCollection(MigrationTestUtils.VORGANG_COLLECTION); - private GridFSFile getMigratedAttachmentFile() { - return getGridFsFile(createFilePath(ATTACHMENT_FIELD_NAME_VALUE, getAttachmentName(migratedVorgang))); + var vorgang = template.insert(MigrationVorgangTestFactory.createVorgang(), VORGANG_COLLECTION); + vorgangId = MigrationTestUtils.getObjectId(vorgang); } @Test - void shouldHaveRepresentationContent() throws IOException { - migrate(); - - InputStream in = TestUtils.loadFile(IncomingFileTestFactory.NAME); - byte[] fileData = new byte[in.available()]; - in.read(fileData); + void shouldNotStopOnExceptionWhenMigrationASecondTime() { + doMigration(); - var content = gridFsTemplate - .getResource(getMigratedRepresentationFile()) - .getContent().readAllBytes(); - assertThat(content).isEqualTo(fileData); - } + doMigration(); - private GridFSFile getMigratedRepresentationFile() { - return getGridFsFile(createFilePath(REPRESENTATION_FIELD_NAME_VALUE, getRepresentationName(migratedVorgang))); + assertThatNoException().isThrownBy(this::doMigration); } @Test - void shouldNotDeleteAttachment() { - migrate(); + void shouldThrowException() throws IOException { + doThrow(new IOException("Test Migration Exception")).when(migrator).storeToGridFs(any(), any(), any(), any()); - assertThat(getMigratedVorgang().getEingangs().get(0).getAttachments().get(0).getFiles()).isNotEmpty(); + assertThatThrownBy(this::doMigration).isInstanceOf(IllegalStateException.class); } - @Test - void shouldNotDeleteRepresentation() { - migrate(); - - assertThat(getMigratedVorgang().getEingangs().get(0).getRepresentations()).isNotEmpty(); + @Nested + class TestAttachmentMigration { + + @Nested + class TestFirstAttachmentFile { + + private final static String NAME = MigrationAttachmentTestFactory.ATTACHMENT_FILE_NAME; + + @Test + void shouldKeepDataInVorgangAttachment() { + doMigration(); + + var attachment = getAttachment(getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME)); + assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_CONTENT_TYPE)) + .isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE); + assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_NAME)).isEqualTo(NAME); + assertThat(attachment.getLong(MigrationIncomingFileTestFactory.FIELD_SIZE)).isEqualTo(MigrationIncomingFileTestFactory.SIZE); + } + + @Test + void shouldUpdateAttachmentFileId() { + doMigration(); + + var gridFsFileId = getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME); + var attachment = getAttachment(gridFsFileId); + assertThat(gridFsFileId).isEqualTo(attachment.getString(OBJECT_ID)); + } + + @Nested + class TestCreatedGridFs { + + @Test + void shouldHaveAttachmentFilePath() { + doMigration(); + + var expectedFilename = buildAttachmentFilename(NAME); + var migratedFilename = getGridFsFile(expectedFilename).getFilename(); + assertThat(migratedFilename).isEqualTo(expectedFilename); + } + + @Test + void shouldHaveGridFsFileMetadata() { + doMigration(); + + var gridFsFile = getGridFsFile(buildAttachmentFilename(NAME)); + var metadata = gridFsFile.getMetadata(); + assertThat(metadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE); + assertThat(metadata.getString(VORGANG_ID)).isEqualTo(vorgangId.toHexString()); + assertThat(metadata.getString(FILE_FIELD_NAME)).isEqualTo(ATTACHMENT_FIELD_NAME_VALUE); + } + + @Test + void shouldHaveAttachmentContent() throws IOException { + doMigration(); + + var gridFsFileContent = getGridFsFileContent(getGridFsFile(buildAttachmentFilename(NAME))); + assertThat(gridFsFileContent).isEqualTo(MigrationIncomingFileTestFactory.CONTENT); + } + } + } + + @Nested + class TestSecondAttachmentFile { + + private final static String NAME = MigrationAttachmentTestFactory.ATTACHMENT_FILE_NAME2; + + @Test + void shouldKeepDataInVorgang() { + doMigration(); + + var attachment = getAttachment(getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME)); + assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_CONTENT_TYPE)) + .isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE); + assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_NAME)).isEqualTo(NAME); + assertThat(attachment.getLong(MigrationIncomingFileTestFactory.FIELD_SIZE)).isEqualTo(MigrationIncomingFileTestFactory.SIZE); + } + + @Test + void shouldUpdateAttachmentFileId() { + doMigration(); + + var gridFsFileId = getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME); + var attachment = getAttachment(gridFsFileId); + assertThat(gridFsFileId).isEqualTo(attachment.getString(OBJECT_ID).toString()); + } + + @Nested + class TestCreatedGridFs { + + @Test + void shouldHaveAttachmentFilePath() { + doMigration(); + + var expectedFilename = buildAttachmentFilename(NAME); + var gridFsFile = getGridFsFile(expectedFilename); + var migratedFilename = gridFsFile.getFilename(); + assertThat(migratedFilename).isEqualTo(expectedFilename); + } + + @Test + void shouldHaveGridFsFileMetadata() { + doMigration(); + + var gridFsFileMetadata = getGridFsFile(buildAttachmentFilename(NAME)).getMetadata(); + assertThat(gridFsFileMetadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE); + assertThat(gridFsFileMetadata.getString(VORGANG_ID)).isEqualTo(vorgangId.toHexString()); + assertThat(gridFsFileMetadata.getString(FILE_FIELD_NAME)).isEqualTo(ATTACHMENT_FIELD_NAME_VALUE); + } + + @Test + void shouldHaveAttachmentContent() throws IOException { + doMigration(); + + var gridFsFileContent = getGridFsFileContent(getGridFsFile(buildAttachmentFilename(NAME))); + assertThat(gridFsFileContent).isEqualTo(MigrationIncomingFileTestFactory.CONTENT); + } + } + } + + private Document getAttachment(String gridFsFileId) { + var attachments = getVorgang().getList(MigrationVorgangTestFactory.FIELD_EINGANGS, Document.class).get(0) + .getList(MigrationEingangTestFactory.FIELD_ATTACHMENTS, Document.class); + return attachments.stream() + .flatMap(oneattachment -> oneattachment.getList("files", Document.class).stream()) + .filter(attachmentFile -> StringUtils.equals(attachmentFile.getString(OBJECT_ID), gridFsFileId)) + .toList().get(0); + } } - private Vorgang getMigratedVorgang() { - return template.findOne(Query.query(Criteria.where(OBJECT_ID).is(migratedVorgang.getId())), Vorgang.class); + @Nested + class TestRepresentationMigration { + + private final static String NAME = MigrationIncomingFileTestFactory.NAME; + + @Test + void shouldKeepDataInVorgang() { + doMigration(); + + var representation = getRepresentation(getVorgang(), getIdOfCreatedGridFsFile()); + assertThat(representation.getString(MigrationIncomingFileTestFactory.FIELD_CONTENT_TYPE)) + .isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE); + assertThat(representation.getString(MigrationIncomingFileTestFactory.FIELD_NAME)).isEqualTo(NAME); + assertThat(representation.getLong(MigrationIncomingFileTestFactory.FIELD_SIZE)).isEqualTo(MigrationIncomingFileTestFactory.SIZE); + } + + @Test + void shouldUpdateRepresentationFileId() { + doMigration(); + + var gridFsFileId = getIdOfCreatedGridFsFile(); + var representation = getRepresentation(getVorgang(), gridFsFileId); + assertThat(gridFsFileId).isEqualTo(representation.getString(OBJECT_ID)); + } + + private String getIdOfCreatedGridFsFile() { + var gridFsFile = getGridFsFile(buildRepresentationFilename()); + var gridFsFileId = gridFsFile.getId().asObjectId().getValue().toHexString(); + return gridFsFileId; + } + + @Nested + class TestCreatedGridFs { + + @Test + void shouldHaveRepresentationFilePath() { + doMigration(); + + var expectedFilename = buildRepresentationFilename(); + var gridFsFile = getGridFsFile(buildRepresentationFilename()); + var migratedFilename = gridFsFile.getFilename(); + assertThat(migratedFilename).isEqualTo(expectedFilename); + } + + @Test + void shouldSetGridFsFileMetadata() { + doMigration(); + + var gridFsFile = getGridFsFile(buildRepresentationFilename()); + var metadata = gridFsFile.getMetadata(); + assertThat(metadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE); + assertThat(metadata.getString(VORGANG_ID)).isEqualTo(vorgangId.toHexString()); + assertThat(metadata.getString(FILE_FIELD_NAME)).isEqualTo(REPRESENTATION_FIELD_NAME_VALUE); + } + + @Test + void shouldHaveRepresentationContent() throws IOException { + doMigration(); + + var gridFsFileContent = getGridFsFileContent(getGridFsFile(buildRepresentationFilename())); + assertThat(gridFsFileContent).isEqualTo(MigrationIncomingFileTestFactory.CONTENT); + } + } + + private Document getRepresentation(Document vorgang, String gridFsFileId) { + var representations = vorgang.getList(MigrationVorgangTestFactory.FIELD_EINGANGS, Document.class).get(0) + .getList(MigrationEingangTestFactory.FIELD_REPRESENTATIONS, Document.class); + return representations.stream() + .filter(representationFile -> StringUtils.equals(representationFile.getString(OBJECT_ID), gridFsFileId)) + .toList().get(0); + } + + private String buildRepresentationFilename() { + return buildFilename(REPRESENTATION_FIELD_NAME_VALUE, NAME); + } } - private String getAttachmentName(Vorgang vorgang) { - return vorgang.getEingangs().get(0).getAttachments().get(0).getFiles().get(0).getName(); + private byte[] getGridFsFileContent(GridFSFile gridFsFile) throws IOException { + return gridFsTemplate.getResource(gridFsFile).getContent().readAllBytes(); } - private String getRepresentationName(Vorgang vorgang) { - return vorgang.getEingangs().get(0).getRepresentations().get(0).getName(); + private Document getVorgang() { + return template.findById(vorgangId, Document.class, VORGANG_COLLECTION); } - private String createFilePath(String fieldValue, String name) { + private String buildFilename(String fieldValue, String name) { return String.format("%s/%s/%s/%s", - migratedVorgang.getId(), + vorgangId.toHexString(), CLIENT_VALUE, fieldValue, name); @@ -193,32 +290,16 @@ class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase {// NOSONAR return gridFsTemplate.findOne(Query.query(Criteria.where(GRISFS_FILE_NAME_FIELD).is(filename))); } - @Test - void shouldNotStopOnExceptionWhenMigrationASecondTime() { - migrate(); - - migrate(); - - assertThatNoException().isThrownBy(this::migrate); - } - - @Test - void shouldThrowException() throws IOException { - doThrow(new IOException("Test")).when(migrator).storeToGridFs(any(), any(), any(), any()); - - assertThatThrownBy(this::migrate).isInstanceOf(IllegalStateException.class); + private String getIdOfCreatedGridFsFile(String fieldName, String name) { + var filename = buildFilename(fieldName, name); + return getGridFsFile(filename).getId().asObjectId().getValue().toHexString(); } - @Test - void shouldNotMigrate() { - migrate(); - - GridFSFile migratedFile = gridFsTemplate.findOne(Query.query(Criteria.where(METADATA_VORGANG_ID).is(notMigratedVorgang.getId()))); - - assertThat(migratedFile).isNull(); + private String buildAttachmentFilename(String name) { + return buildFilename(ATTACHMENT_FIELD_NAME_VALUE, name); } - private void migrate() { + private void doMigration() { migrator.migrationMethod(template); } -} +} \ No newline at end of file diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationAttachmentTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationAttachmentTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..54c5bfcf9a3cbf9323eb5598a22e31a9ea186c17 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationAttachmentTestFactory.java @@ -0,0 +1,40 @@ +package de.itvsh.ozg.pluto.common.migration; + +import java.util.List; +import java.util.UUID; + +import org.bson.Document; + +import com.thedeanda.lorem.LoremIpsum; + +class MigrationAttachmentTestFactory { + + static final String FIELD_NAME = "name"; + static final String NAME = LoremIpsum.getInstance().getName(); + static final String FIELD_FILES = "files"; + + static final String ATTACHMENT_FILE_ID = UUID.randomUUID().toString(); + static final String ATTACHMENT_FILE_NAME = LoremIpsum.getInstance().getName(); + + static final String ATTACHMENT_FILE_ID2 = UUID.randomUUID().toString(); + static final String ATTACHMENT_FILE_NAME2 = LoremIpsum.getInstance().getName(); + + static Document create() { + var incomingFileGroup = new Document(); + incomingFileGroup.put(FIELD_NAME, NAME); + incomingFileGroup.put(FIELD_FILES, List.of( + createAttachment(ATTACHMENT_FILE_ID, ATTACHMENT_FILE_NAME), + createAttachment(ATTACHMENT_FILE_ID2, ATTACHMENT_FILE_NAME2))); + + return incomingFileGroup; + } + + private static Document createAttachment(String id, String name) { + var attachmentFile = MigrationIncomingFileTestFactory.create(); + attachmentFile.remove(MigrationIncomingFileTestFactory.FIELD_ID); + attachmentFile.put(MigrationIncomingFileTestFactory.FIELD_ID, id); + attachmentFile.remove(MigrationIncomingFileTestFactory.FIELD_NAME); + attachmentFile.put(MigrationIncomingFileTestFactory.FIELD_NAME, name); + return attachmentFile; + } +} \ No newline at end of file diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9fc8efd04bec0e6c5ce1a1a9febca2c2957cd875 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangTestFactory.java @@ -0,0 +1,37 @@ +package de.itvsh.ozg.pluto.common.migration; + +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import org.bson.Document; + +class MigrationEingangTestFactory { + + static final String FIELD_ID = "_id"; + static final String ID = UUID.randomUUID().toString(); + + static final String FIELD_HEADER = "header"; + static final String FIELD_ANTRAGSTELLER = "antragsteller"; + static final String FIELD_ZUSTAENDIDGESTELLE = "zustaendigeStelle"; + static final String FIELD_REPRESENTATIONS = "representations"; + static final String FIELD_NUMBER_OF_REPRESENTATIONS = "numberOfRepresentations"; + static final String FIELD_ATTACHMENTS = "attachments"; + static final String FIELD_NUMBER_OF_ATTACHMENTS = "numberOfAttachments"; + static final String FIELD_FORMDATA = "formData"; + + static Document create() { + var eingang = new Document(); + eingang.put(FIELD_ID, ID); + eingang.put(FIELD_HEADER, new Document()); + eingang.put(FIELD_ANTRAGSTELLER, new Document()); + eingang.put(FIELD_ZUSTAENDIDGESTELLE, new Document()); + eingang.put(FIELD_ATTACHMENTS, List.of(MigrationAttachmentTestFactory.create())); + eingang.put(FIELD_NUMBER_OF_ATTACHMENTS, 2); + eingang.put(FIELD_REPRESENTATIONS, List.of(MigrationIncomingFileTestFactory.create())); + eingang.put(FIELD_NUMBER_OF_REPRESENTATIONS, 1); + eingang.put(FIELD_FORMDATA, new HashMap<String, Object>()); + + return eingang; + } +} diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationIncomingFileTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationIncomingFileTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0f2ac8c1c9d64dcf2916cdb2e44949b9a6aedf67 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationIncomingFileTestFactory.java @@ -0,0 +1,54 @@ +package de.itvsh.ozg.pluto.common.migration; + +import java.io.IOException; +import java.io.InputStream; + +import org.bson.Document; +import org.bson.types.Binary; +import org.bson.types.ObjectId; + +import de.itvsh.kop.common.test.TestUtils; + +class MigrationIncomingFileTestFactory { + static final String FIELD_ID = "_id"; + static final String ID = new ObjectId().toHexString(); + + static final String FIELD_NAME = "name"; + static final String NAME = "TestDoc.docx"; + + static final String FIELD_CONTENT_TYPE = "contentType"; + static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + + static final String FIELD_SIZE = "size"; + static final long SIZE; + + static final String FIELD_CONTENT = "content"; + static final byte[] CONTENT; + + static { + CONTENT = initContent(); + SIZE = CONTENT.length; + } + + private static byte[] initContent() { + try (InputStream in = TestUtils.loadFile(NAME)) { + byte[] fileData = new byte[in.available()]; + in.read(fileData); + + return fileData; + } catch (IOException e) { + throw new IllegalStateException("Error reading test file " + NAME); + } + } + + static Document create() { + var incomingFile = new Document(); + incomingFile.put(FIELD_ID, ID); + incomingFile.put(FIELD_NAME, NAME); + incomingFile.put(FIELD_CONTENT_TYPE, CONTENT_TYPE); + incomingFile.put(FIELD_SIZE, SIZE); + incomingFile.put(FIELD_CONTENT, new Binary(CONTENT)); + + return incomingFile; + } +} \ No newline at end of file diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationTestUtils.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationTestUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..82515fc55b8ffded5312860ea820ec1e0e5859bd --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationTestUtils.java @@ -0,0 +1,26 @@ +package de.itvsh.ozg.pluto.common.migration; + +import java.io.InputStream; + +import org.bson.Document; +import org.bson.types.ObjectId; + +class MigrationTestUtils { + + static final String FIELD_OBJECT_ID = "_id"; + static final String GRID_FS_CHUNKS_COLLECTION = "fs.chunk"; + static final String GRID_FS_FILES_COLLECTION = "fs.files"; + static final String VORGANG_COLLECTION = "vorgang"; + + static ObjectId getObjectId(Document doc) { + return doc.getObjectId(MigrationTestUtils.FIELD_OBJECT_ID); + } + + static InputStream loadFile(final String fileName) { + var stream = MigrationTestUtils.class.getClassLoader().getResourceAsStream(fileName); + if (stream == null) { + throw new RuntimeException("File '" + fileName + "' not found."); // NOSONAR + } + return stream; + } +} \ No newline at end of file diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0a5635f2449f6a981441faf777ad48b2c6481be6 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangTestFactory.java @@ -0,0 +1,41 @@ +package de.itvsh.ozg.pluto.common.migration; + +import java.util.List; + +import org.bson.Document; + +class MigrationVorgangTestFactory { + + static final String COLLECTION_NAME = "vorgang"; + + static final String FIELD_NAME = "name"; + static final String NAME = "Test Vorgang"; + + static final String FIELD_NUMMER = "nummer"; + static final String NUMMER = "2342454345654"; + + static final String FIELD_STATUS = "status"; + static final String STATUS = "NEU"; + + static final String FIELD_VERSION = "version"; + static final String VERSION = "0"; + + static final String FIELD_EINGANGS = "eingangs"; + + static final String FIELD_FORWARDINGS = "forwardings"; + + static final String FIELD_IN_CREATION = "inCreation"; + static final boolean IN_CREATION = false; + + static Document createVorgang() { + var vorgang = new Document(); + vorgang.put(FIELD_NAME, NAME); + vorgang.put(FIELD_NUMMER, NUMMER); + vorgang.put(FIELD_STATUS, STATUS); + vorgang.put(FIELD_VERSION, VERSION); + vorgang.put(FIELD_EINGANGS, List.of(MigrationEingangTestFactory.create())); + vorgang.put(FIELD_IN_CREATION, IN_CREATION); + + return vorgang; + } +} \ No newline at end of file diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java index bf34ff63c0794a54f3b38cca436a0e53fdde7a1e..fd96de3af6bf51d6afd412a3b1bdce20f77e8a42 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java @@ -180,7 +180,6 @@ class FileITCase { assertThat(attachment1.getName()).isEqualTo(IncomingFileTestFactory.NAME); assertThat(attachment1.getContentType()).isEqualTo(IncomingFileTestFactory.CONTENT_TYPE_STR); assertThat(attachment1.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); - assertThat(attachment1.getContent().toByteArray()).isEqualTo(IncomingFileTestFactory.CONTENT); } @Test @@ -192,7 +191,6 @@ class FileITCase { assertThat(representation.getName()).isEqualTo(IncomingFileTestFactory.NAME); assertThat(representation.getContentType()).isEqualTo(IncomingFileTestFactory.CONTENT_TYPE_STR); assertThat(representation.getSize()).isEqualTo(IncomingFileTestFactory.SIZE); - assertThat(representation.getContent().toByteArray()).isEqualTo(IncomingFileTestFactory.CONTENT); } private void callServiceGetFileData(GrpcGetOzgFileDataRequest request) { diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FilesRepositoryITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FilesRepositoryITCase.java index 56c5603e4f55fbb706ea12594880d7685417f9df..92a27bb0f591ef94565a785f5f715156a1d245a8 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FilesRepositoryITCase.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FilesRepositoryITCase.java @@ -126,7 +126,7 @@ class FilesRepositoryITCase { void validateGetAttachmentData() { Optional<OzgFileData> file = repository.getFileContent(IncomingFileTestFactory.ID); - assertThat(file).get().usingRecursiveComparison().isEqualTo(OzgFileDataTestFactory.create()); + assertThat(file).get().usingRecursiveComparison().isEqualTo(OzgFileDataTestFactory.createBuilder().content(null).build()); } @Test @@ -134,7 +134,7 @@ class FilesRepositoryITCase { Optional<OzgFileData> file = repository.getFileContent(IncomingFileTestFactory.ID); assertThat(file).isPresent().get().usingRecursiveComparison() - .isEqualTo(OzgFileDataTestFactory.createBuilder().name(IncomingFileTestFactory.NAME).build()); + .isEqualTo(OzgFileDataTestFactory.createBuilder().content(null).name(IncomingFileTestFactory.NAME).build()); } } } diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java index 1e49e84e64a134b032b48384a57513530d3a61c2..ecdc3a747e2b18a3fa046b1b8af8b1c691b73dda 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java @@ -36,8 +36,7 @@ public class IncomingFileTestFactory { .vendorId(VENDOR_ID) .name(NAME) .contentType(CONTENT_TYPE_STR) - .size(SIZE) - .content(CONTENT); + .size(SIZE); } public static InputStream createContentStream(int sizeInMB) { diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java index 79264c8d2f522750b0e1b4a1a60bded03a853315..c1b217f075bf4cc59b6ef195bfaaa2d36c0bd3c2 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java @@ -4,6 +4,13 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.io.ByteArrayInputStream; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -24,13 +31,20 @@ import de.itvsh.ozg.pluto.command.CommandStatus; import de.itvsh.ozg.pluto.command.GrpcCreateCommandRequestTestFactory; import de.itvsh.ozg.pluto.command.GrpcVorgangCommandService; import de.itvsh.ozg.pluto.common.solr.SolrEventListener; +import de.itvsh.ozg.pluto.files.FileId; +import de.itvsh.ozg.pluto.files.FileService; +import de.itvsh.ozg.pluto.files.OzgFileTestFactory; +import de.itvsh.ozg.pluto.files.UploadedFilesReferenceTestFactory; import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse; import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest; import de.itvsh.ozg.pluto.grpc.command.GrpcOrder; import de.itvsh.ozg.pluto.grpc.command.GrpcRedirectRequest; +import de.itvsh.ozg.pluto.vorgang.EingangTestFactory; +import de.itvsh.ozg.pluto.vorgang.IncomingFileGroupTestFactory; +import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory; import de.itvsh.ozg.pluto.vorgang.Vorgang; import de.itvsh.ozg.pluto.vorgang.Vorgang.Status; -import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory; +import de.itvsh.ozg.pluto.vorgang.VorgangService; import io.grpc.stub.StreamObserver; @DataITCase @@ -52,13 +66,19 @@ class ForwardVorgangITCase { private String vorgangId; + @Autowired + private VorgangService vorgangService; + + @Autowired + private FileService fileService; + @MockBean private StreamObserver<GrpcCommandResponse> responseObserver; @Captor private ArgumentCaptor<GrpcCommandResponse> responseCapture; @BeforeEach - void init() { + void init() throws InterruptedException, ExecutionException, TimeoutException { cleanDatabase(); prepareVorgang(); } @@ -68,11 +88,26 @@ class ForwardVorgangITCase { mongoOperations.dropCollection(Command.class); } - private void prepareVorgang() { - var vorgang = VorgangTestFactory.createBuilder().id(null).status(Status.NEU).build(); + private void prepareVorgang() throws InterruptedException, ExecutionException, TimeoutException { + Vorgang vorgang = vorgangService.startCreation(EingangTestFactory.createBuilder().clearAttachments().clearRepresentations().build()); + FileId attachmentFileId = storeFileInGridFs(vorgang); + FileId representationFileId = storeFileInGridFs(vorgang); + + var attachments = List.of(IncomingFileGroupTestFactory.createBuilder().clearFiles().file( + IncomingFileTestFactory.createBuilder().id(attachmentFileId).build()).build()); + + var representations = List.of(IncomingFileTestFactory.createBuilder().id(representationFileId).build()); + + vorgangService.finishCreation(vorgang.getId(), attachments, representations); + + this.vorgangId = vorgang.getId(); + } - var persisted = mongoOperations.save(vorgang); - this.vorgangId = persisted.getId(); + private FileId storeFileInGridFs(Vorgang vorgang) throws InterruptedException, ExecutionException, TimeoutException { + return fileService + .uploadFileStream(UploadedFilesReferenceTestFactory.createBuilder().vorgangId(vorgang.getId()).build(), + OzgFileTestFactory.create(), Optional.empty(), new ByteArrayInputStream(IncomingFileTestFactory.CONTENT)) + .get(5, TimeUnit.SECONDS); } @Nested @@ -149,7 +184,7 @@ class ForwardVorgangITCase { return GrpcCreateCommandRequestTestFactory.createBuilder() .clearOrder().setOrder(GrpcOrder.REDIRECT_VORGANG) .clearRelationId().setRelationId(vorgangId) - .clearRelationVersion().setRelationVersion(VorgangTestFactory.VERSION) + .clearRelationVersion().setRelationVersion(0) .setRedirectRequest(buildRedirectRequest()) .build(); } diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java index 71a852af7097981a6f3548b801a781ab83ccacf3..cd39bc70852870d878f98578fcd7f2561af716fd 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -20,6 +21,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.test.util.ReflectionTestUtils; +import de.itvsh.ozg.pluto.files.FileId; +import de.itvsh.ozg.pluto.files.FileService; import de.itvsh.ozg.pluto.vorgang.IncomingFileGroupTestFactory; import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory; import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory; @@ -39,8 +42,12 @@ class ZipBuilderServiceTest { @Mock private ZipOutputStream zipOut; + @Mock + private FileService fileService; + @BeforeEach void init() { + when(fileService.getUploadedFileStream(any(FileId.class))).thenReturn(new ByteArrayInputStream(IncomingFileTestFactory.CONTENT)); builder = spy(service.new ZipBuilder(VorgangTestFactory.create(), true)); ReflectionTestUtils.setField(builder, "zipOut", zipOut); diff --git a/pom.xml b/pom.xml index cf7f869c72565be4a5abb5b63063445a5f430f0f..e77eed2c6cedbc603daff7d5628829551a4c009c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,6 +6,7 @@ <groupId>de.itvsh.ozg</groupId> <artifactId>pluto</artifactId> <version>0.24.0-SNAPSHOT</version> + <name>Pluto Parent</name> <packaging>pom</packaging>