diff --git a/src/main/java/de/ozgcloud/admin/migration/M001_CreateEmptyPostfachIfMissing.java b/src/main/java/de/ozgcloud/admin/migration/M001_CreateEmptyPostfachIfMissing.java new file mode 100644 index 0000000000000000000000000000000000000000..ba8c8aced8b1d2bf25bd3bd39d8e5c6c18799520 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/migration/M001_CreateEmptyPostfachIfMissing.java @@ -0,0 +1,25 @@ +package de.ozgcloud.admin.migration; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; +import org.springframework.data.mongodb.core.MongoTemplate; + +@ChangeUnit(id = "2024-02-20 17:00:00 OZG-4948-OZG-5058", order = "M001", author = "lmonnerjahn", runAlways = true) +public class M001_CreateEmptyPostfachIfMissing { + private static final String SETTINGS_COLLECTION = "settings"; + + static final String NAME_KEY = "name"; + static final String POSTFACH_NAME = "Postfach"; + + @Execution + public void doMigration(MongoTemplate template) { + // todo: check if settings collection contains a "postfach" object + // add a postfach object if it is missing + } + + @RollbackExecution + public void rollback() { + // kein rollback implementiert + } +} diff --git a/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java b/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java new file mode 100644 index 0000000000000000000000000000000000000000..84e860cb2cbdee0312df576f903dd285e89e1bd9 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.admin.migration; + +import io.mongock.runner.spring.base.events.SpringMigrationFailureEvent; +import lombok.extern.log4j.Log4j2; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Log4j2 +@Component +public class MongockFailedEventListener implements ApplicationListener<SpringMigrationFailureEvent> { + + @Override + public void onApplicationEvent(SpringMigrationFailureEvent event) { + log.error("Mongock migration failed", event.getMigrationResult()); + } +} \ No newline at end of file diff --git a/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java b/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java new file mode 100644 index 0000000000000000000000000000000000000000..ad1558351ae353658dbe653bfe2630e627373489 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.admin.migration; + +import io.mongock.runner.spring.base.events.SpringMigrationStartedEvent; +import lombok.extern.log4j.Log4j2; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Log4j2 +@Component +public class MongockStartEventListener implements ApplicationListener<SpringMigrationStartedEvent> { + + @Override + public void onApplicationEvent(SpringMigrationStartedEvent event) { + log.info("Mongock start migration..."); + } +} \ No newline at end of file diff --git a/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java b/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java new file mode 100644 index 0000000000000000000000000000000000000000..95a7f76ee988dc8f1e72b8db6341da77514e5b54 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.admin.migration; + +import io.mongock.runner.spring.base.events.SpringMigrationSuccessEvent; +import lombok.extern.log4j.Log4j2; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Log4j2 +@Component +public class MongockSuccessEventListener implements ApplicationListener<SpringMigrationSuccessEvent> { + + @Override + public void onApplicationEvent(SpringMigrationSuccessEvent event) { + log.info("Mongock migration successfull", event.getMigrationResult()); + } +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/admin/AdministrationApplicationTest.java b/src/test/java/de/ozgcloud/admin/AdministrationApplicationTest.java index c322c8fe7563f4f76ad2f6eb2793e4057543e4e0..7b7fb5056c8fd67bc11be9a1cc016610e1181146 100644 --- a/src/test/java/de/ozgcloud/admin/AdministrationApplicationTest.java +++ b/src/test/java/de/ozgcloud/admin/AdministrationApplicationTest.java @@ -23,7 +23,6 @@ package de.ozgcloud.admin; import de.ozgcloud.common.test.ITCase; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; @ITCase class AdministrationApplicationTest { diff --git a/src/test/java/de/ozgcloud/admin/migration/M001_CreateEmptyPostfachIfMissingITCase.java b/src/test/java/de/ozgcloud/admin/migration/M001_CreateEmptyPostfachIfMissingITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..69277ba8d18e7185770a3df920f2cb8f2196de9f --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/migration/M001_CreateEmptyPostfachIfMissingITCase.java @@ -0,0 +1,132 @@ +package de.ozgcloud.admin.migration; + +import de.ozgcloud.common.test.DataITCase; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; + +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +@DataITCase +public class M001_CreateEmptyPostfachIfMissingITCase { + private final M001_CreateEmptyPostfachIfMissing changeUnit = new M001_CreateEmptyPostfachIfMissing(); + + private static final Document POSTFACH = MigrationTestFactory.createPostfach(); + + @Autowired + private MongoTemplate template; + + public static final String SETTINGS_COLLECTION = "settings"; + + @DisplayName("Do migration") + @Nested + class TestDoMigration { + @BeforeEach + public void init() { + template.dropCollection(SETTINGS_COLLECTION); + } + + @Test + void shouldAddPostfachIfMissing() { + changeUnit.doMigration(template); + + List<Document> settings = template.find(new Query(), Document.class, SETTINGS_COLLECTION); + assertThat(settings).hasSize(1) + .anyMatch(this::isEmptyPostfachSetting + ); + } + + @Test + void shouldAddPostfachIfMissingInCollection() { + var settingItem = MigrationTestFactory.createSettingsItem("SomeType", new Document()); + template.save(settingItem, SETTINGS_COLLECTION); + + changeUnit.doMigration(template); + + // assert leeres Postfach sollte angelegt sein + List<Document> settings = template.find(new Query(), Document.class, SETTINGS_COLLECTION); + assertThat(settings).hasSize(2) + .anyMatch(s -> + s.get(MigrationTestFactory.ITEM_TYPE_KEY).equals("SomeType") + ) + .anyMatch(this::isEmptyPostfachSetting + ); + } + + @Test + void shouldKeepExistingPostfach() { + // Postfach in settings Collection anlegen + template.save(POSTFACH, SETTINGS_COLLECTION); + + changeUnit.doMigration(template); + + // assert Postfach in settings Collection sollte unverändert sein + List<Document> settings = template.find(new Query(), Document.class, SETTINGS_COLLECTION); + assertThat(settings).hasSize(1) + .contains(POSTFACH); + } + + private boolean isEmptyPostfachSetting(Document document) { + Set<String> expectedKeySet = Set.of( + MigrationTestFactory.ITEM_TYPE_KEY, + MigrationTestFactory.ITEM_SETTINGS_KEY + ); + if(document.keySet().containsAll(expectedKeySet) && + document.get(MigrationTestFactory.ITEM_TYPE_KEY).equals(MigrationTestFactory.ITEM_TYPE_VALUE_POSTFACH)) { + var settingsValue = document.get(MigrationTestFactory.ITEM_SETTINGS_KEY); + if (settingsValue instanceof Document postfach) { + return isEmptyPostfach(postfach); + } + } + return false; + } + + private boolean isEmptyPostfach(Document document) { + Set<String> expectedKeySet = Set.of( + MigrationTestFactory.POSTFACH_ABSENDER_KEY, + MigrationTestFactory.POSTFACH_SIGNATUR_KEY + ); + if (document.keySet().containsAll(expectedKeySet) && + document.keySet().size() == expectedKeySet.size()) { + var absenderValue = document.get(MigrationTestFactory.POSTFACH_ABSENDER_KEY); + var signaturValue = document.get(MigrationTestFactory.POSTFACH_SIGNATUR_KEY); + if (absenderValue instanceof Document absender && + signaturValue instanceof Document signatur) { + return isEmptyAbsender(absender) && isEmptySignatur(signatur); + } + } + return false; + } + + private boolean isEmptyAbsender(Document document) { + Set<String> expectedKeySet = Set.of( + MigrationTestFactory.ABSENDER_ANSCHRIFT_KEY, + MigrationTestFactory.ABSENDER_NAME_KEY, + MigrationTestFactory.ABSENDER_DIENST_KEY, + MigrationTestFactory.ABSENDER_MANDANT_KEY, + MigrationTestFactory.ABSENDER_GEMEINDESCHLUESSEL_KEY + ); + return document.keySet().containsAll(expectedKeySet) && + document.keySet().size() == expectedKeySet.size() && + document.entrySet().stream().allMatch(entry -> entry.getValue().equals("")); + } + + private boolean isEmptySignatur(Document document) { + Set<String> expectedKeySet = Set.of( + MigrationTestFactory.SIGNATUR_TEXT_KEY + ); + return document.keySet().containsAll(expectedKeySet) && + document.keySet().size() == expectedKeySet.size() && + document.entrySet().stream().allMatch(entry -> entry.getValue().equals("")); + } + + } +} diff --git a/src/test/java/de/ozgcloud/admin/migration/MigrationTestFactory.java b/src/test/java/de/ozgcloud/admin/migration/MigrationTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..35fa0e187870364cfa79c5ca8aea18a00bebf4f1 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/migration/MigrationTestFactory.java @@ -0,0 +1,62 @@ +package de.ozgcloud.admin.migration; + +import com.thedeanda.lorem.Lorem; +import com.thedeanda.lorem.LoremIpsum; +import org.bson.Document; + +import java.util.Random; + +public class MigrationTestFactory { + + private static final Lorem lorem = LoremIpsum.getInstance(); + + public static final String ITEM_TYPE_KEY = "name"; + public static final String ITEM_SETTINGS_KEY = "settings"; + + public static Document createSettingsItem(String itemType, Document itemValue) { + var settingsItem = new Document(); + settingsItem.put(ITEM_TYPE_KEY, itemType); + settingsItem.put(ITEM_SETTINGS_KEY, itemValue); + return settingsItem; + } + + + public static final String ITEM_TYPE_VALUE_POSTFACH = "Postfach"; + public static final String POSTFACH_ABSENDER_KEY = "absender"; + public static final String POSTFACH_SIGNATUR_KEY = "signatur"; + public static final String ABSENDER_NAME_KEY = "name"; + public static final String ABSENDER_NAME_VALUE = lorem.getName(); + public static final String ABSENDER_ANSCHRIFT_KEY = "anschrift"; + public static final String ABSENDER_ANSCHRIFT_VALUE = lorem.getWords(1) + ", " + lorem.getZipCode() + " " + lorem.getCity(); + public static final String ABSENDER_DIENST_KEY = "dienst"; + public static final String ABSENDER_DIENST_VALUE = lorem.getWords(1, 2); + public static final String ABSENDER_MANDANT_KEY = "mandant"; + public static final String ABSENDER_MANDANT_VALUE = lorem.getWords(2, 3); + public static final String ABSENDER_GEMEINDESCHLUESSEL_KEY = "gemeindeschluessel"; + public static final String ABSENDER_GEMEINDESCHLUESSEL_VALUE = String.valueOf(new Random().nextInt(1000000)); + public static final String SIGNATUR_TEXT_KEY = "text"; + public static final String SIGNATUR_TEXT_VALUE = lorem.getParagraphs(1, 3); + + public static Document createPostfach() { + var postfach = new Document(); + postfach.put(POSTFACH_ABSENDER_KEY, createAbsender()); + postfach.put(POSTFACH_SIGNATUR_KEY, createSignatur()); + return createSettingsItem(ITEM_TYPE_VALUE_POSTFACH, postfach); + } + + private static Document createAbsender() { + var absender = new Document(); + absender.put(ABSENDER_NAME_KEY, ABSENDER_NAME_VALUE); + absender.put(ABSENDER_ANSCHRIFT_KEY, ABSENDER_ANSCHRIFT_VALUE); + absender.put(ABSENDER_DIENST_KEY, ABSENDER_DIENST_VALUE); + absender.put(ABSENDER_MANDANT_KEY, ABSENDER_MANDANT_VALUE); + absender.put(ABSENDER_GEMEINDESCHLUESSEL_KEY, ABSENDER_GEMEINDESCHLUESSEL_VALUE); + return absender; + } + + private static Document createSignatur() { + var signatur = new Document(); + signatur.put(SIGNATUR_TEXT_KEY, SIGNATUR_TEXT_VALUE); + return signatur; + } +}