From 9c8d7616e380dbe75d97c0a2551be69970c15da9 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 15 Jan 2025 13:43:20 +0100 Subject: [PATCH] Upgrade to SpringBoot 3.4.1 and dependencies (#147) Co-authored-by: Michael Hoennig Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/147 Reviewed-by: Marc Sandlus --- .aliases | 4 +- .tc-environment | 2 +- .unset-environment | 2 +- README.md | 5 + bin/howto | 86 +++++++++ build.gradle | 26 +-- etc/allowed-licenses.json | 22 ++- .../RestResponseEntityExceptionHandler.java | 3 +- .../debitor/HsBookingDebitorEntity.java | 3 +- .../project/HsBookingProjectController.java | 4 +- .../hs/hosting/asset/HsHostingAsset.java | 2 +- .../asset/HsHostingAssetController.java | 4 +- .../DomainSetupHostingAssetFactory.java | 6 +- .../asset/factories/HostingAssetFactory.java | 4 +- .../HsBookingItemCreatedListener.java | 14 +- .../ManagedWebspaceHostingAssetFactory.java | 8 +- .../HsOfficeBankAccountController.java | 4 +- .../hs/office/contact/HsOfficeContact.java | 3 +- .../contact/HsOfficeContactController.java | 4 +- .../HsOfficeCoopAssetsTransactionEntity.java | 29 +-- ...OfficeCoopSharesTransactionController.java | 56 ++++-- .../HsOfficeCoopSharesTransactionEntity.java | 15 +- .../debitor/HsOfficeDebitorController.java | 90 ++++++---- .../office/debitor/HsOfficeDebitorEntity.java | 19 +- .../debitor/HsOfficeDebitorRepository.java | 4 +- .../HsOfficeMembershipController.java | 22 ++- .../membership/HsOfficeMembershipEntity.java | 7 +- .../HsOfficeMembershipEntityPatcher.java | 6 +- .../hs/office/partner/HsOfficePartner.java | 103 +++++++++++ .../partner/HsOfficePartnerController.java | 31 ++-- .../office/partner/HsOfficePartnerEntity.java | 128 ------------- .../partner/HsOfficePartnerEntityPatcher.java | 4 +- .../partner/HsOfficePartnerRbacEntity.java | 59 ++++++ .../HsOfficePartnerRbacRepository.java | 47 +++++ .../partner/HsOfficePartnerRealEntity.java | 21 +++ .../HsOfficePartnerRealRepository.java | 41 +++++ .../partner/HsOfficePartnerRepository.java | 45 ----- .../person/HsOfficePersonController.java | 4 +- .../person/HsOfficePersonRealEntity.java | 2 - .../relation/HsOfficeRelationController.java | 4 +- .../HsOfficeSepaMandateController.java | 26 ++- .../hsadminng/hs/validation/UuidResolver.java | 17 ++ .../hsadminng/mapper/StandardMapper.java | 17 -- .../hsadminng/persistence/BaseEntity.java | 7 + .../persistence/EntityExistsValidator.java | 38 ---- .../rbac/grant/RbacGrantController.java | 4 +- .../rbac/grant/RbacGrantsDiagramService.java | 76 +++++--- .../rbac/role/RbacRoleController.java | 4 +- .../rbac/subject/RbacSubjectController.java | 4 +- .../test/cust/TestCustomerController.java | 4 +- .../rbac/test/pac/TestPackageController.java | 4 +- .../hs-office/hs-office-debitor-schemas.yaml | 1 + .../5118-hs-office-coopshares-test-data.sql | 5 +- .../5128-hs-office-coopassets-test-data.sql | 5 +- ...esponseEntityExceptionHandlerUnitTest.java | 5 +- ...HsBookingItemControllerAcceptanceTest.java | 1 - .../item/HsBookingItemControllerRestTest.java | 12 +- ...sBookingItemRepositoryIntegrationTest.java | 4 +- ...ookingProjectControllerAcceptanceTest.java | 1 - ...okingProjectRepositoryIntegrationTest.java | 4 +- ...sHostingAssetControllerAcceptanceTest.java | 4 - .../HsHostingAssetControllerRestTest.java | 20 +-- ...HostingAssetRepositoryIntegrationTest.java | 4 +- ...omainSetupHostingAssetFactoryUnitTest.java | 4 +- .../HsBookingItemCreatedListenerUnitTest.java | 4 +- ...edWebspaceHostingAssetFactoryUnitTest.java | 4 +- .../hs/migration/BaseOfficeDataImport.java | 6 +- .../hsadminng/hs/migration/CsvDataImport.java | 4 +- ...HsOfficeBankAccountControllerRestTest.java | 12 +- ...eBankAccountRepositoryIntegrationTest.java | 4 +- ...OfficeContactControllerAcceptanceTest.java | 1 - ...eContactRbacRepositoryIntegrationTest.java | 4 +- ...opAssetsTransactionControllerRestTest.java | 16 +- ...sTransactionRepositoryIntegrationTest.java | 4 +- ...esTransactionControllerAcceptanceTest.java | 140 +++++++++------ ...opSharesTransactionControllerRestTest.java | 16 +- ...sTransactionRepositoryIntegrationTest.java | 4 +- ...OfficeDebitorControllerAcceptanceTest.java | 21 +-- .../HsOfficeDebitorEntityUnitTest.java | 12 +- ...fficeDebitorRepositoryIntegrationTest.java | 8 +- .../office/debitor/TestHsOfficeDebitor.java | 2 +- ...iceMembershipControllerAcceptanceTest.java | 5 +- .../HsOfficeMembershipControllerRestTest.java | 27 +-- ...OfficeMembershipEntityPatcherUnitTest.java | 6 +- .../HsOfficeMembershipEntityUnitTest.java | 6 +- ...ceMembershipRepositoryIntegrationTest.java | 8 +- .../office/membership/TestHsMembership.java | 2 +- ...OfficePartnerControllerAcceptanceTest.java | 8 +- .../HsOfficePartnerControllerRestTest.java | 22 +-- .../HsOfficePartnerEntityPatcherUnitTest.java | 10 +- .../HsOfficePartnerEntityUnitTest.java | 4 +- ...PartnerRbacRepositoryIntegrationTest.java} | 169 +++++++++--------- ...tner.java => HsOfficeTestRealPartner.java} | 8 +- ...sOfficePersonControllerAcceptanceTest.java | 1 - ...cePersonRbacRepositoryIntegrationTest.java | 4 +- ...cePersonRealRepositoryIntegrationTest.java | 4 +- ...RealRelationRepositoryIntegrationTest.java | 4 +- ...ficeRelationRepositoryIntegrationTest.java | 4 +- ...ceSepaMandateControllerAcceptanceTest.java | 10 +- ...eSepaMandateRepositoryIntegrationTest.java | 4 +- .../rbac/context/ContextIntegrationTests.java | 8 +- .../RbacGrantRepositoryIntegrationTest.java | 4 +- ...acGrantsDiagramServiceIntegrationTest.java | 4 +- .../rbac/role/RbacRoleControllerRestTest.java | 14 +- .../RbacRoleRepositoryIntegrationTest.java | 4 +- .../RbacSubjectControllerRestTest.java | 12 +- .../RbacSubjectRepositoryIntegrationTest.java | 4 +- .../hsadminng/rbac/test/MapperUnitTest.java | 4 +- ...TestCustomerRepositoryIntegrationTest.java | 11 +- .../TestPackageRepositoryIntegrationTest.java | 4 +- src/test/resources/application.yml | 2 +- 111 files changed, 1095 insertions(+), 758 deletions(-) create mode 100755 bin/howto create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartner.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacEntity.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepository.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealEntity.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealRepository.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/UuidResolver.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/mapper/StandardMapper.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/persistence/EntityExistsValidator.java rename src/test/java/net/hostsharing/hsadminng/hs/office/partner/{HsOfficePartnerRepositoryIntegrationTest.java => HsOfficePartnerRbacRepositoryIntegrationTest.java} (80%) rename src/test/java/net/hostsharing/hsadminng/hs/office/partner/{TestHsOfficePartner.java => HsOfficeTestRealPartner.java} (82%) diff --git a/.aliases b/.aliases index cfd7c284..eb60c71d 100644 --- a/.aliases +++ b/.aliases @@ -93,7 +93,8 @@ alias gw-spotless='./gradlew spotlessApply -x pitest -x test -x :processResource alias gw-test='. .aliases; ./gradlew test' alias gw-check='. .aliases; gw test check -x pitest' -alias cas-curl='bin/cas-curl' +alias howto=bin/howto +alias cas-curl=bin/cas-curl # etc/docker-compose.yml limits CPUs+MEM and includes a PostgreSQL config for analysing slow queries alias gw-importOfficeData-in-docker-compose=' @@ -108,3 +109,4 @@ source .environment alias scenario-reports-upload='./gradlew scenarioTests convertMarkdownToHtml && ssh hsh03-hsngdev@h50.hostsharing.net "rm -f doms/hsngdev.hs-example.de/htdocs-ssl/scenarios/office/*.html" && scp build/doc/scenarios/*.html hsh03-hsngdev@h50.hostsharing.net:doms/hsngdev.hs-example.de/htdocs-ssl/scenarios/office' alias scenario-reports-open='open https://hsngdev.hs-example.de/scenarios/office' + diff --git a/.tc-environment b/.tc-environment index ecc6dc9a..595d0096 100644 --- a/.tc-environment +++ b/.tc-environment @@ -4,5 +4,5 @@ export HSADMINNG_POSTGRES_ADMIN_PASSWORD= export HSADMINNG_POSTGRES_RESTRICTED_USERNAME=restricted export HSADMINNG_SUPERUSER=superuser-alex@hostsharing.net export HSADMINNG_MIGRATION_DATA_PATH=migration -export LIQUIBASE_CONTEXT= +export LIQUIBASE_COMMAND_CONTEXT_FILTER= export LANG=en_US.UTF-8 diff --git a/.unset-environment b/.unset-environment index a9e4ee81..fbc180cc 100644 --- a/.unset-environment +++ b/.unset-environment @@ -4,5 +4,5 @@ unset HSADMINNG_POSTGRES_ADMIN_PASSWORD unset HSADMINNG_POSTGRES_RESTRICTED_USERNAME unset HSADMINNG_SUPERUSER unset HSADMINNG_MIGRATION_DATA_PATH -unset LIQUIBASE_CONTEXT +unset LIQUIBASE_COMMAND_CONTEXT_FILTER diff --git a/README.md b/README.md index a015f73c..e9f40f79 100644 --- a/README.md +++ b/README.md @@ -617,6 +617,11 @@ Besides the following *How Tos* you can also find several *How Tos* in the sourc grep -r HOWTO src ``` +also try this (assumed you've sourced .aliases): +```sh +howto +``` + ### How to Configure .pgpass for the Default PostgreSQL Database? To access the default database schema as used during development, add this line to your `.pgpass` file in your users home directory: diff --git a/bin/howto b/bin/howto new file mode 100755 index 00000000..0a3b6404 --- /dev/null +++ b/bin/howto @@ -0,0 +1,86 @@ +#!/usr/bin/python3 +import os +import sys +from urllib.parse import urljoin, quote + +def path_to_file_uri(path): + """ + Converts a file path to a file URI. + Handles absolute and relative paths. + """ + abs_path = os.path.abspath(path) + return urljoin("file://", quote(abs_path)) + +def is_binary_file(filepath, chunk_size=1024): + """ + Prüft, ob eine Datei binär ist, indem sie den Inhalt der Datei auf nicht-druckbare Zeichen untersucht. + """ + try: + with open(filepath, "rb") as file: + chunk = file.read(chunk_size) + if b"\0" in chunk: # Nullbyte ist ein typisches Zeichen für Binärdateien + return True + return False + except Exception as e: + print(f"Fehler beim Prüfen, ob Datei binär ist: {filepath}: {e}") + return True + +def search_keywords_in_files(keywords): + if not keywords: + print("Bitte geben Sie mindestens ein Stichwort an.") + sys.exit(1) + + # Allowed comment symbols + comment_symbols = {"//", "#", ";"} + + for root, dirs, files in os.walk("."): + # Ausschließen bestimmter Verzeichnisse + dirs[:] = [d for d in dirs if d not in {".git", "build"}] + + for file in files: + filepath = os.path.join(root, file) + + # Überspringen von Binärdateien + if is_binary_file(filepath): + continue + + try: + with open(filepath, "r", encoding="utf-8") as f: + lines = f.readlines() + + for line_number, line in enumerate(lines, start=1): + stripped_line = line.lstrip() # Entfernt führende Leerzeichen + for symbol in comment_symbols: + if stripped_line.startswith(symbol): + # Entfernt das Kommentarzeichen und nachfolgende Leerzeichen + howtoMatch = stripped_line[len(symbol):].lstrip() + if howtoMatch.startswith(("HOWTO ", "HOWTO: ", "How to ")): + if all(keyword in howtoMatch.lower() for keyword in keywords): + + # Titelzeile ohne Kommentarzeichen + print(howtoMatch.rstrip()) + + # Ausgabe nachfolgender Zeilen mit dem gleichen Kommentar-Präfix + for subsequent_line in lines[line_number:]: + subsequent_line = subsequent_line.lstrip() + if subsequent_line.startswith(symbol): + # Entfernt Kommentarzeichen aus Folgezeilen + print("\t" + subsequent_line[len(symbol):].strip()) + else: + break + + # Link mit Zeilennummer + print(f"--> {path_to_file_uri(filepath)}:{line_number}") + + # Abstand zwischen Matches + print() + break + except Exception as e: + print(f"Fehler beim Lesen der Datei {filepath}: {e}") + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Verwendung: bin/howto ...") + sys.exit(1) + + search_keywords_in_files([arg.lower() for arg in sys.argv[1:]]) diff --git a/build.gradle b/build.gradle index 7646a33b..6ba3c5e1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,17 +1,20 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.3.7' + id 'org.springframework.boot' version '3.4.1' id 'io.spring.dependency-management' version '1.1.7' id 'io.openapiprocessor.openapi-processor' version '2023.2' id 'com.github.jk1.dependency-license-report' version '2.9' - id "org.owasp.dependencycheck" version "11.1.1" - id "com.diffplug.spotless" version "7.0.0" + id "org.owasp.dependencycheck" version "12.0.0" + id "com.diffplug.spotless" version "7.0.2" id 'jacoco' id 'info.solidsoft.pitest' version '1.15.0' id 'se.patrikerdes.use-latest-versions' version '0.2.18' id 'com.github.ben-manes.versions' version '0.51.0' } +// HOWTO: find out which dependency versions are managed by Spring Boot: +// https://docs.spring.io/spring-boot/appendix/dependency-versions/coordinates.html + group = 'net.hostsharing' version = '0.0.1-SNAPSHOT' @@ -20,6 +23,9 @@ wrapper { gradleVersion = '8.5' } +// TODO.impl: self-attaching is deprecated, see: +// https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.3 + configurations { compileOnly { extendsFrom annotationProcessor @@ -61,23 +67,23 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.10.0' - implementation 'org.springdoc:springdoc-openapi:2.6.0' - implementation 'org.postgresql:postgresql:42.7.4' - implementation 'org.liquibase:liquibase-core:4.30.0' + implementation 'org.springdoc:springdoc-openapi:2.8.3' + implementation 'org.postgresql:postgresql' + implementation 'org.liquibase:liquibase-core' implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.9.0' - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' implementation 'org.openapitools:jackson-databind-nullable:0.2.6' implementation 'org.apache.commons:commons-text:1.13.0' implementation 'net.java.dev.jna:jna:5.16.0' implementation 'org.modelmapper:modelmapper:3.2.2' implementation 'org.iban4j:iban4j:3.2.10-RELEASE' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.3' implementation 'org.reflections:reflections:0.10.2' compileOnly 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok' - // FIXME: developmentOnly 'org.springframework.boot:spring-boot-devtools' + developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' @@ -89,7 +95,7 @@ dependencies { testImplementation 'org.testcontainers:postgresql' testImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0' testImplementation 'io.rest-assured:spring-mock-mvc' - testImplementation 'org.hamcrest:hamcrest-core:3.0' + testImplementation 'org.hamcrest:hamcrest-core' testImplementation 'org.pitest:pitest-junit5-plugin:1.2.1' testImplementation 'org.junit.jupiter:junit-jupiter-api' testImplementation 'org.wiremock:wiremock-standalone:3.10.0' diff --git a/etc/allowed-licenses.json b/etc/allowed-licenses.json index ff50a78f..447f5c62 100644 --- a/etc/allowed-licenses.json +++ b/etc/allowed-licenses.json @@ -5,9 +5,23 @@ { "moduleLicense": "Apache-2.0" }, { "moduleLicense": "Apache License 2.0" }, { "moduleLicense": "Apache License v2.0" }, + { "moduleLicense": "Apache License Version 2.0" }, { "moduleLicense": "Apache License, Version 2.0" }, + { "moduleLicense": "The Apache License, Version 2.0" }, { "moduleLicense": "The Apache Software License, Version 2.0" }, + { + "moduleLicense": null, + "#moduleLicense": "Apache License 2.0, see https://github.com/springdoc/springdoc-openapi/blob/main/LICENSE", + "moduleVersion": "2.4.0", + "moduleName": "org.springdoc:springdoc-openapi" + }, + { + "moduleLicense": null, + "moduleVersion": "1.0.0", + "moduleName": "org.jspecify:jspecify" + }, + { "moduleLicense": "BSD License" }, { "moduleLicense": "BSD-2-Clause" }, { "moduleLicense": "BSD-3-Clause" }, @@ -46,14 +60,8 @@ { "moduleLicense": "Public Domain, per Creative Commons CC0", "moduleVersion": "2.0.3" - }, - - { - "moduleLicense": null, - "#moduleLicense": "Apache License 2.0, see https://github.com/springdoc/springdoc-openapi/blob/main/LICENSE", - "moduleVersion": "2.4.0", - "moduleName": "org.springdoc:springdoc-openapi" } + ] } diff --git a/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java b/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java index c366d7bc..31ab3647 100644 --- a/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java +++ b/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java @@ -97,6 +97,7 @@ public class RestResponseEntityExceptionHandler return errorResponse(request, HttpStatus.valueOf(statusCode.value()), Optional.ofNullable(response.getBody()).map(Object::toString).orElse(firstMessageLine(exc))); } + @Override @SuppressWarnings("unchecked,rawtypes") protected ResponseEntity handleHttpMessageNotReadable( @@ -131,7 +132,7 @@ public class RestResponseEntityExceptionHandler final HttpStatusCode status, final WebRequest request) { final var errorList = exc - .getAllValidationResults() + .getParameterValidationResults() .stream() .map(ParameterValidationResult::getResolvableErrors) .flatMap(Collection::stream) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/debitor/HsBookingDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/debitor/HsBookingDebitorEntity.java index a09a33bc..f982a443 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/debitor/HsBookingDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/debitor/HsBookingDebitorEntity.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import net.hostsharing.hsadminng.errors.DisplayAs; +import net.hostsharing.hsadminng.rbac.role.WithRoleId; import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringifyable; @@ -24,7 +25,7 @@ import static net.hostsharing.hsadminng.repr.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayAs("BookingDebitor") -public class HsBookingDebitorEntity implements Stringifyable { +public class HsBookingDebitorEntity implements Stringifyable, WithRoleId { public static final String DEBITOR_NUMBER_TAG = "D-"; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectController.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectController.java index ac21083a..98b856b9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectController.java @@ -7,7 +7,7 @@ import net.hostsharing.hsadminng.hs.booking.generated.api.v1.api.HsBookingProjec import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectInsertResource; import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectPatchResource; import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectResource; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; @@ -26,7 +26,7 @@ public class HsBookingProjectController implements HsBookingProjectsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsBookingProjectRbacRepository bookingProjectRepo; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAsset.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAsset.java index d327f354..f8a1d0c3 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAsset.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAsset.java @@ -89,7 +89,7 @@ public abstract class HsHostingAsset implements Stringifyable, BaseEntity subHostingAssets; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java index a8d4f7cf..f9a45f70 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java @@ -12,7 +12,7 @@ import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAsse import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetResource; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource; import net.hostsharing.hsadminng.mapper.KeyValueMap; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; @@ -36,7 +36,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsHostingAssetRbacRepository rbacAssetRepo; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactory.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactory.java index 00a8c4d4..812c81a9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactory.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactory.java @@ -9,7 +9,7 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity; import net.hostsharing.hsadminng.lambda.Reducer; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.mapper.ToStringConverter; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; @@ -31,8 +31,8 @@ public class DomainSetupHostingAssetFactory extends HostingAssetFactory { final EntityManagerWrapper emw, final HsBookingItemRealEntity newBookingItemRealEntity, final HsHostingAssetAutoInsertResource asset, - final StandardMapper standardMapper) { - super(emw, newBookingItemRealEntity, asset, standardMapper); + final StrictMapper StrictMapper) { + super(emw, newBookingItemRealEntity, asset, StrictMapper); } @Override diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HostingAssetFactory.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HostingAssetFactory.java index 392fe1e6..290f40ec 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HostingAssetFactory.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HostingAssetFactory.java @@ -6,7 +6,7 @@ import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAsse import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAsset; import net.hostsharing.hsadminng.hs.hosting.asset.validators.HostingAssetEntitySaveProcessor; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; @@ -16,7 +16,7 @@ abstract class HostingAssetFactory { final EntityManagerWrapper emw; final HsBookingItemRealEntity fromBookingItem; final HsHostingAssetAutoInsertResource asset; - final StandardMapper standardMapper; + final StrictMapper StrictMapper; protected abstract HsHostingAsset create(); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListener.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListener.java index 8818cef8..73291368 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListener.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListener.java @@ -9,7 +9,7 @@ import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAsse import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedAppEvent; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAsset; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; @@ -25,7 +25,7 @@ public class HsBookingItemCreatedListener implements ApplicationListener - forNowNoAutomaticHostingAssetCreationPossible(emw, newBookingItemRealEntity, asset, standardMapper); - case MANAGED_WEBSPACE -> new ManagedWebspaceHostingAssetFactory(emw, newBookingItemRealEntity, asset, standardMapper); - case DOMAIN_SETUP -> new DomainSetupHostingAssetFactory(emw, newBookingItemRealEntity, asset, standardMapper); + forNowNoAutomaticHostingAssetCreationPossible(emw, newBookingItemRealEntity, asset, StrictMapper); + case MANAGED_WEBSPACE -> new ManagedWebspaceHostingAssetFactory(emw, newBookingItemRealEntity, asset, StrictMapper); + case DOMAIN_SETUP -> new DomainSetupHostingAssetFactory(emw, newBookingItemRealEntity, asset, StrictMapper); }; if (factory != null) { final var statusMessage = factory.createAndPersist(); @@ -62,9 +62,9 @@ public class HsBookingItemCreatedListener implements ApplicationListener { +public class HsOfficeContact implements Stringifyable, BaseEntity, WithRoleId { private static Stringify toString = stringify(HsOfficeContact.class, "contact") .withProp(Fields.caption, HsOfficeContact::getCaption) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java index 572a0ce8..9b676af6 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.contact; import io.micrometer.core.annotation.Timed; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeContactsApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactInsertResource; @@ -28,7 +28,7 @@ public class HsOfficeContactController implements HsOfficeContactsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsOfficeContactRbacRepository contactRepo; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java index c0c908df..6dd244aa 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java @@ -1,4 +1,3 @@ - package net.hostsharing.hsadminng.hs.office.coopassets; import lombok.AllArgsConstructor; @@ -10,11 +9,22 @@ import net.hostsharing.hsadminng.errors.DisplayAs; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.persistence.BaseEntity; import net.hostsharing.hsadminng.rbac.generator.RbacSpec; +import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL; import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringifyable; -import org.hibernate.annotations.GenericGenerator; -import jakarta.persistence.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Version; import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; @@ -57,8 +67,7 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, BaseE .quotedValues(false); @Id - @GeneratedValue(generator = "UUID") - @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator") + @GeneratedValue private UUID uuid; @Version @@ -122,15 +131,15 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, BaseE return this; } - public String getTaggedMemberNumber() { - return ofNullable(membership).map(HsOfficeMembershipEntity::toShortString).orElse("M-???????"); - } - @Override public String toString() { return stringify.apply(this); } + public String getTaggedMemberNumber() { + return ofNullable(membership).map(HsOfficeMembershipEntity::toShortString).orElse("M-???????"); + } + @Override public String toShortString() { return "%s:%.3s:%+1.2f".formatted( @@ -141,7 +150,7 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, BaseE public static RbacSpec rbac() { return rbacViewFor("coopAssetsTransaction", HsOfficeCoopAssetsTransactionEntity.class) - .withIdentityView(RbacSpec.SQL.projection("reference")) + .withIdentityView(SQL.projection("reference")) .withUpdatableColumns("comment") .importEntityAlias("membership", HsOfficeMembershipEntity.class, usingDefaultCase(), dependsOnColumn("membershipUuid"), diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java index b903dd85..5583d44e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java @@ -1,14 +1,13 @@ package net.hostsharing.hsadminng.hs.office.coopshares; -import jakarta.persistence.EntityNotFoundException; - import io.micrometer.core.annotation.Timed; import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.errors.MultiValidationException; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopSharesApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionInsertResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionResource; -import net.hostsharing.hsadminng.errors.MultiValidationException; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository; +import net.hostsharing.hsadminng.mapper.StrictMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat.ISO; @@ -25,6 +24,7 @@ import java.util.function.BiConsumer; import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionTypeResource.CANCELLATION; import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionTypeResource.SUBSCRIPTION; +import static net.hostsharing.hsadminng.hs.validation.UuidResolver.resolve; @RestController public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopSharesApi { @@ -33,14 +33,16 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo; + @Autowired + private HsOfficeMembershipRepository membershipRepo; + @Override @Transactional(readOnly = true) - @Timed("app.office.coopShares.api.getListOfCoopShares") public ResponseEntity> getListOfCoopShares( final String currentSubject, @@ -55,7 +57,10 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar fromValueDate, toValueDate); - final var resources = mapper.mapList(entities, HsOfficeCoopSharesTransactionResource.class); + final var resources = mapper.mapList( + entities, + HsOfficeCoopSharesTransactionResource.class, + ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.ok(resources); } @@ -70,7 +75,10 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar context.define(currentSubject, assumedRoles); validate(requestBody); - final var entityToSave = mapper.map(requestBody, HsOfficeCoopSharesTransactionEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); + final var entityToSave = mapper.map( + requestBody, + HsOfficeCoopSharesTransactionEntity.class, + RESOURCE_TO_ENTITY_POSTMAPPER); final var saved = coopSharesTransactionRepo.save(entityToSave); @@ -79,7 +87,7 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar .path("/api/hs/office/coopsharestransactions/{id}") .buildAndExpand(saved.getUuid()) .toUri(); - final var mapped = mapper.map(saved, HsOfficeCoopSharesTransactionResource.class); + final var mapped = mapper.map(saved, HsOfficeCoopSharesTransactionResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.created(uri).body(mapped); } @@ -87,15 +95,18 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar @Transactional(readOnly = true) @Timed("app.office.coopShares.repo.getSingleCoopShareTransactionByUuid") public ResponseEntity getSingleCoopShareTransactionByUuid( - final String currentSubject, final String assumedRoles, final UUID shareTransactionUuid) { + final String currentSubject, final String assumedRoles, final UUID shareTransactionUuid) { - context.define(currentSubject, assumedRoles); + context.define(currentSubject, assumedRoles); - final var result = coopSharesTransactionRepo.findByUuid(shareTransactionUuid); - if (result.isEmpty()) { - return ResponseEntity.notFound().build(); - } - return ResponseEntity.ok(mapper.map(result.get(), HsOfficeCoopSharesTransactionResource.class)); + final var result = coopSharesTransactionRepo.findByUuid(shareTransactionUuid); + if (result.isEmpty()) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(mapper.map( + result.get(), + HsOfficeCoopSharesTransactionResource.class, + ENTITY_TO_RESOURCE_POSTMAPPER)); } @@ -137,9 +148,16 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar } final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { - if ( resource.getRevertedShareTxUuid() != null ) { - entity.setRevertedShareTx(coopSharesTransactionRepo.findByUuid(resource.getRevertedShareTxUuid()) - .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] revertedShareTxUuid %s not found".formatted(resource.getRevertedShareTxUuid())))); + entity.setMembership(resolve("membership.uuid", resource.getMembershipUuid(), membershipRepo::findByUuid)); + if (resource.getRevertedShareTxUuid() != null) { + entity.setRevertedShareTx(resolve( + "revertedShareTx.uuid", + resource.getRevertedShareTxUuid(), + coopSharesTransactionRepo::findByUuid)); } }; + + final BiConsumer ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> { + resource.setMembershipUuid(entity.getMembership().getUuid()); + }; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java index 2deb57b5..fcc900f1 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java @@ -7,13 +7,23 @@ import lombok.NoArgsConstructor; import lombok.Setter; import net.hostsharing.hsadminng.errors.DisplayAs; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; -import net.hostsharing.hsadminng.rbac.generator.RbacSpec; import net.hostsharing.hsadminng.persistence.BaseEntity; +import net.hostsharing.hsadminng.rbac.generator.RbacSpec; import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL; import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringifyable; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Version; import java.io.IOException; import java.time.LocalDate; import java.util.UUID; @@ -132,6 +142,7 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, BaseE directlyFetchedByDependsOnColumn(), NOT_NULL) + // the membership:ADMIN is not to be confused with the member itself, it's an account manager of the coop .toRole("membership", ADMIN).grantPermission(INSERT) .toRole("membership", ADMIN).grantPermission(UPDATE) .toRole("membership", AGENT).grantPermission(SELECT); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorController.java index 1e82b848..2e0ff210 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorController.java @@ -2,14 +2,16 @@ package net.hostsharing.hsadminng.hs.office.debitor; import io.micrometer.core.annotation.Timed; import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository; +import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealRepository; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeDebitorsApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorInsertResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorResource; +import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository; -import net.hostsharing.hsadminng.mapper.StandardMapper; -import net.hostsharing.hsadminng.persistence.EntityExistsValidator; +import net.hostsharing.hsadminng.mapper.StrictMapper; import org.apache.commons.lang3.Validate; import org.hibernate.Hibernate; import org.springframework.beans.factory.annotation.Autowired; @@ -26,6 +28,7 @@ import java.util.UUID; import java.util.function.BiConsumer; import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR; +import static net.hostsharing.hsadminng.hs.validation.UuidResolver.resolve; import static net.hostsharing.hsadminng.repr.TaggedNumber.cropTag; @RestController @@ -36,16 +39,22 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsOfficeDebitorRepository debitorRepo; @Autowired - private HsOfficeRelationRealRepository relrealRepo; + private HsOfficeRelationRealRepository realRelRepo; @Autowired - private EntityExistsValidator entityValidator; + private HsOfficePersonRealRepository realPersonRepo; + + @Autowired + private HsOfficeContactRealRepository realContactRepo; + + @Autowired + private HsOfficeBankAccountRepository bankAccountRepo; @PersistenceContext private EntityManager em; @@ -63,9 +72,9 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi { final var entities = partnerNumber != null ? debitorRepo.findDebitorsByPartnerNumber(cropTag("P-", partnerNumber)) - : partnerUuid != null - ? debitorRepo.findDebitorsByPartnerUuid(partnerUuid) - : debitorRepo.findDebitorsByOptionalNameLike(name); + : partnerUuid != null + ? debitorRepo.findDebitorsByPartnerUuid(partnerUuid) + : debitorRepo.findDebitorsByOptionalNameLike(name); final var resources = mapper.mapList(entities, HsOfficeDebitorResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.ok(resources); @@ -81,34 +90,19 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi { context.define(currentSubject, assumedRoles); - Validate.isTrue(body.getDebitorRel() == null || body.getDebitorRelUuid() == null, + Validate.isTrue( + body.getDebitorRel() == null || body.getDebitorRelUuid() == null, "ERROR: [400] exactly one of debitorRel and debitorRelUuid must be supplied, but found both"); - Validate.isTrue(body.getDebitorRel() != null || body.getDebitorRelUuid() != null, + Validate.isTrue( + body.getDebitorRel() != null || body.getDebitorRelUuid() != null, "ERROR: [400] exactly one of debitorRel and debitorRelUuid must be supplied, but found none"); - Validate.isTrue(body.getDebitorRel() == null || body.getDebitorRel().getMark() == null, + Validate.isTrue( + body.getDebitorRel() == null || body.getDebitorRel().getMark() == null, "ERROR: [400] debitorRel.mark must be null"); - final var entityToSave = mapper.map(body, HsOfficeDebitorEntity.class); - if (body.getDebitorRel() != null) { - final var debitorRel = mapper.map("debitorRel.", body.getDebitorRel(), HsOfficeRelationRealEntity.class); - debitorRel.setType(DEBITOR); - entityValidator.validateEntityExists("debitorRel.anchorUuid", debitorRel.getAnchor()); - entityValidator.validateEntityExists("debitorRel.holderUuid", debitorRel.getHolder()); - entityValidator.validateEntityExists("debitorRel.contactUuid", debitorRel.getContact()); - entityToSave.setDebitorRel(relrealRepo.save(debitorRel)); - } else { - final var debitorRelOptional = relrealRepo.findByUuid(body.getDebitorRelUuid()); - debitorRelOptional.ifPresentOrElse( - debitorRel -> {entityToSave.setDebitorRel(relrealRepo.save(debitorRel));}, - () -> { - throw new ValidationException( - "Unable to find RealRelation by debitorRelUuid: " + body.getDebitorRelUuid()); - }); - } + final var entityToSave = mapper.map(body, HsOfficeDebitorEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); - final var savedEntity = debitorRepo.save(entityToSave); - em.flush(); - em.refresh(savedEntity); + final var savedEntity = debitorRepo.save(entityToSave).reload(em); final var uri = MvcUriComponentsBuilder.fromController(getClass()) @@ -181,7 +175,7 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi { context.define(currentSubject, assumedRoles); - final var current = debitorRepo.findByUuid(debitorUuid).orElseThrow(); + final var current = debitorRepo.findByUuid(debitorUuid).orElseThrow().reload(em); new HsOfficeDebitorEntityPatcher(em, current).apply(body); @@ -191,7 +185,39 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi { return ResponseEntity.ok(mapped); } + final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { + if (resource.getDebitorRel() != null) { + final var debitorRel = realRelRepo.save(HsOfficeRelationRealEntity.builder() + .type(DEBITOR) + .anchor(resolve( + "debitorRel.anchor.uuid", resource.getDebitorRel().getAnchorUuid(), realPersonRepo::findByUuid)) + .holder(resolve( + "debitorRel.holder.uuid", resource.getDebitorRel().getHolderUuid(), realPersonRepo::findByUuid)) + .contact(resolve( + "debitorRel.contact.uuid", resource.getDebitorRel().getContactUuid(), realContactRepo::findByUuid)) + .build()); + entity.setDebitorRel(debitorRel); + } else { + final var debitorRelOptional = realRelRepo.findByUuid(resource.getDebitorRelUuid()); + debitorRelOptional.ifPresentOrElse( + debitorRel -> { + entity.setDebitorRel(realRelRepo.save(debitorRel)); + }, + () -> { + throw new ValidationException( + "Unable to find debitorRel.uuid: " + resource.getDebitorRelUuid()); + }); + } + + if (resource.getRefundBankAccountUuid() != null) { + entity.setRefundBankAccount(resolve( + "refundBankAccount.uuid", resource.getRefundBankAccountUuid(), bankAccountRepo::findByUuid)); + } + + }; + final BiConsumer ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> { resource.setDebitorNumber(entity.getTaggedDebitorNumber()); + resource.getPartner().setPartnerNumber(entity.getPartner().getTaggedPartnerNumber()); }; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index 6181c6f4..4e20fbf8 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -7,7 +7,8 @@ import lombok.NoArgsConstructor; import lombok.Setter; import net.hostsharing.hsadminng.errors.DisplayAs; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartner; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity; @@ -16,7 +17,6 @@ import net.hostsharing.hsadminng.rbac.generator.RbacSpec; import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL; import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringifyable; -import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.JoinFormula; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; @@ -75,7 +75,6 @@ public class HsOfficeDebitorEntity implements BaseEntity, @Id @GeneratedValue - @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator") private UUID uuid; @Version @@ -87,16 +86,16 @@ public class HsOfficeDebitorEntity implements BaseEntity, value = """ ( SELECT DISTINCT partner.uuid - FROM hs_office.partner_rv partner + FROM hs_office.partner partner JOIN hs_office.relation dRel - ON dRel.uuid = debitorreluuid AND dRel.type = 'DEBITOR' + ON dRel.uuid = debitorRelUuid AND dRel.type = 'DEBITOR' JOIN hs_office.relation pRel ON pRel.uuid = partner.partnerRelUuid AND pRel.type = 'PARTNER' WHERE pRel.holderUuid = dRel.anchorUuid ) """) - @NotFound(action = NotFoundAction.IGNORE) // TODO.impl: map a simplified raw-PartnerEntity, just for the partner-number - private HsOfficePartnerEntity partner; + @NotFound(action = NotFoundAction.EXCEPTION) // TODO.impl: map a simplified raw-PartnerEntity, just for the partner-number + private HsOfficePartnerRealEntity partner; @Column(name = "debitornumbersuffix", length = 2) @Pattern(regexp = TWO_DECIMAL_DIGITS) @@ -132,9 +131,7 @@ public class HsOfficeDebitorEntity implements BaseEntity, @Override public HsOfficeDebitorEntity load() { BaseEntity.super.load(); - if (partner != null) { - partner.load(); - } + partner.load(); debitorRel.load(); if (refundBankAccount != null) { refundBankAccount.load(); @@ -145,7 +142,7 @@ public class HsOfficeDebitorEntity implements BaseEntity, public String getTaggedDebitorNumber() { return ofNullable(partner) .filter(partner -> debitorNumberSuffix != null) - .map(HsOfficePartnerEntity::getPartnerNumber) + .map(HsOfficePartner::getPartnerNumber) .map(partnerNumber -> DEBITOR_NUMBER_TAG + partnerNumber + debitorNumberSuffix) .orElse(null); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepository.java index fa02053b..588f7a00 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepository.java @@ -19,7 +19,7 @@ public interface HsOfficeDebitorRepository extends Repository SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { + entity.setPartner(partnerRepo.findByUuid(resource.getPartnerUuid()) + .orElseThrow(() -> new EntityNotFoundException( + "ERROR: [400] partnerUuid %s not found".formatted(resource.getPartnerUuid())))); }; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java index 3b0f58de..2d9c8248 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java @@ -8,11 +8,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import net.hostsharing.hsadminng.errors.DisplayAs; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity; import net.hostsharing.hsadminng.persistence.BaseEntity; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.rbac.generator.RbacSpec; import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL; +import net.hostsharing.hsadminng.rbac.role.WithRoleId; import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringifyable; import org.hibernate.annotations.Type; @@ -63,7 +64,7 @@ import static net.hostsharing.hsadminng.repr.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayAs("Membership") -public class HsOfficeMembershipEntity implements BaseEntity, Stringifyable { +public class HsOfficeMembershipEntity implements BaseEntity, Stringifyable, WithRoleId { public static final String MEMBER_NUMBER_TAG = "M-"; public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; @@ -84,7 +85,7 @@ public class HsOfficeMembershipEntity implements BaseEntity { - private final StandardMapper mapper; + private final StrictMapper mapper; private final HsOfficeMembershipEntity entity; public HsOfficeMembershipEntityPatcher( - final StandardMapper mapper, + final StrictMapper mapper, final HsOfficeMembershipEntity entity) { this.mapper = mapper; this.entity = entity; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartner.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartner.java new file mode 100644 index 00000000..78acfd0e --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartner.java @@ -0,0 +1,103 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import net.hostsharing.hsadminng.errors.DisplayAs; +import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContact; +import net.hostsharing.hsadminng.hs.office.person.HsOfficePerson; +import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation; +import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; +import net.hostsharing.hsadminng.persistence.BaseEntity; +import net.hostsharing.hsadminng.repr.Stringify; +import net.hostsharing.hsadminng.repr.Stringifyable; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; + +import jakarta.persistence.Column; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Version; +import java.util.UUID; + +import static jakarta.persistence.CascadeType.DETACH; +import static jakarta.persistence.CascadeType.MERGE; +import static jakarta.persistence.CascadeType.PERSIST; +import static jakarta.persistence.CascadeType.REFRESH; +import static java.util.Optional.ofNullable; +import static net.hostsharing.hsadminng.repr.Stringify.stringify; + +@MappedSuperclass +@Getter +@Setter +@SuperBuilder(toBuilder = true) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@DisplayAs("Partner") +public class HsOfficePartner> implements Stringifyable, BaseEntity { + + public static final String PARTNER_NUMBER_TAG = "P-"; + + protected static Stringify stringify = stringify(HsOfficePartner.class, "partner") + .withIdProp(HsOfficePartner::toShortString) + .withProp(p -> ofNullable(p.getPartnerRel()) + .map(HsOfficeRelation::getHolder) + .map(HsOfficePerson::toShortString) + .orElse(null)) + .withProp(p -> ofNullable(p.getPartnerRel()) + .map(HsOfficeRelation::getContact) + .map(HsOfficeContact::toShortString) + .orElse(null)) + .quotedValues(false); + + @Id + @GeneratedValue + private UUID uuid; + + @Version + private int version; + + @Column(name = "partnernumber", columnDefinition = "numeric(5) not null") + private Integer partnerNumber; + + @ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "partnerreluuid", nullable = false) + private HsOfficeRelationRealEntity partnerRel; + + @ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = true, fetch = FetchType.LAZY) + @JoinColumn(name = "detailsuuid") + @NotFound(action = NotFoundAction.IGNORE) + private HsOfficePartnerDetailsEntity details; + + @Override + public T load() { + BaseEntity.super.load(); + partnerRel.load(); + if (details != null) { + details.load(); + } + //noinspection unchecked + return (T) this; + } + + public String getTaggedPartnerNumber() { + return PARTNER_NUMBER_TAG + partnerNumber; + } + + @Override + public String toString() { + return stringify.apply(this); + } + + @Override + public String toShortString() { + return getTaggedPartnerNumber(); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java index f3c25bd5..aa8b572e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java @@ -13,7 +13,7 @@ import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.BaseEntity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -26,6 +26,7 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import java.util.List; import java.util.UUID; +import java.util.function.BiConsumer; import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.EX_PARTNER; import static net.hostsharing.hsadminng.repr.TaggedNumber.cropTag; @@ -38,10 +39,10 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired - private HsOfficePartnerRepository partnerRepo; + private HsOfficePartnerRbacRepository partnerRepo; @Autowired private HsOfficeRelationRealRepository relationRepo; @@ -60,7 +61,7 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { final var entities = partnerRepo.findPartnerByOptionalNameLike(name); - final var resources = mapper.mapList(entities, HsOfficePartnerResource.class); + final var resources = mapper.mapList(entities, HsOfficePartnerResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.ok(resources); } @@ -83,7 +84,7 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { .path("/api/hs/office/partners/{id}") .buildAndExpand(saved.getUuid()) .toUri(); - final var mapped = mapper.map(saved, HsOfficePartnerResource.class); + final var mapped = mapper.map(saved, HsOfficePartnerResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.created(uri).body(mapped); } @@ -101,7 +102,8 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { if (result.isEmpty()) { return ResponseEntity.notFound().build(); } - return ResponseEntity.ok(mapper.map(result.get(), HsOfficePartnerResource.class)); + final var mapped = mapper.map(result.get(), HsOfficePartnerResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); + return ResponseEntity.ok(mapped); } @Override @@ -118,7 +120,8 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { if (result.isEmpty()) { return ResponseEntity.notFound().build(); } - return ResponseEntity.ok(mapper.map(result.get(), HsOfficePartnerResource.class)); + final var mapped = mapper.map(result.get(), HsOfficePartnerResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); + return ResponseEntity.ok(mapped); } @Override @@ -161,20 +164,20 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { final var saved = partnerRepo.save(current); optionallyCreateExPartnerRelation(saved, previousPartnerRel); - final var mapped = mapper.map(saved, HsOfficePartnerResource.class); + final var mapped = mapper.map(saved, HsOfficePartnerResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.ok(mapped); } - private void optionallyCreateExPartnerRelation(final HsOfficePartnerEntity saved, final HsOfficeRelationRealEntity previousPartnerRel) { + private void optionallyCreateExPartnerRelation(final HsOfficePartnerRbacEntity saved, final HsOfficeRelationRealEntity previousPartnerRel) { if (!saved.getPartnerRel().getUuid().equals(previousPartnerRel.getUuid())) { // TODO.impl: we also need to use the new partner-person as the anchor relationRepo.save(previousPartnerRel.toBuilder().uuid(null).type(EX_PARTNER).build()); } } - private HsOfficePartnerEntity createPartnerEntity(final HsOfficePartnerInsertResource body) { - final var entityToSave = new HsOfficePartnerEntity(); - entityToSave.setPartnerNumber(cropTag(HsOfficePartnerEntity.PARTNER_NUMBER_TAG, body.getPartnerNumber())); + private HsOfficePartnerRbacEntity createPartnerEntity(final HsOfficePartnerInsertResource body) { + final var entityToSave = new HsOfficePartnerRbacEntity(); + entityToSave.setPartnerNumber(cropTag(HsOfficePartnerRbacEntity.PARTNER_NUMBER_TAG, body.getPartnerNumber())); entityToSave.setPartnerRel(persistPartnerRel(body.getPartnerRel())); entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class)); return entityToSave; @@ -197,4 +200,8 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { throw new ReferenceNotFoundException(entityClass, uuid, exc); } } + + final BiConsumer ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> { + resource.setPartnerNumber(entity.getTaggedPartnerNumber()); + }; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java deleted file mode 100644 index 69fb49c9..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java +++ /dev/null @@ -1,128 +0,0 @@ -package net.hostsharing.hsadminng.hs.office.partner; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import net.hostsharing.hsadminng.errors.DisplayAs; -import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContact; -import net.hostsharing.hsadminng.hs.office.person.HsOfficePerson; -import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; -import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity; -import net.hostsharing.hsadminng.persistence.BaseEntity; -import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation; -import net.hostsharing.hsadminng.rbac.generator.RbacSpec; -import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL; -import net.hostsharing.hsadminng.repr.Stringify; -import net.hostsharing.hsadminng.repr.Stringifyable; -import org.hibernate.annotations.NotFound; -import org.hibernate.annotations.NotFoundAction; - -import jakarta.persistence.*; -import java.io.IOException; -import java.util.UUID; - -import static jakarta.persistence.CascadeType.*; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn; -import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor; -import static java.util.Optional.ofNullable; -import static net.hostsharing.hsadminng.repr.Stringify.stringify; - -@Entity -@Table(schema = "hs_office", name = "partner_rv") -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -@DisplayAs("Partner") -public class HsOfficePartnerEntity implements Stringifyable, BaseEntity { - - public static final String PARTNER_NUMBER_TAG = "P-"; - - private static Stringify stringify = stringify(HsOfficePartnerEntity.class, "partner") - .withIdProp(HsOfficePartnerEntity::toShortString) - .withProp(p -> ofNullable(p.getPartnerRel()) - .map(HsOfficeRelation::getHolder) - .map(HsOfficePerson::toShortString) - .orElse(null)) - .withProp(p -> ofNullable(p.getPartnerRel()) - .map(HsOfficeRelation::getContact) - .map(HsOfficeContact::toShortString) - .orElse(null)) - .quotedValues(false); - - @Id - @GeneratedValue - private UUID uuid; - - @Version - private int version; - - @Column(name = "partnernumber", columnDefinition = "numeric(5) not null") - private Integer partnerNumber; - - @ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "partnerreluuid", nullable = false) - private HsOfficeRelationRealEntity partnerRel; - - @ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = true, fetch = FetchType.LAZY) - @JoinColumn(name = "detailsuuid") - @NotFound(action = NotFoundAction.IGNORE) - private HsOfficePartnerDetailsEntity details; - - @Override - public HsOfficePartnerEntity load() { - BaseEntity.super.load(); - partnerRel.load(); - details.load(); - return this; - } - - public String getTaggedPartnerNumber() { - return PARTNER_NUMBER_TAG + partnerNumber; - } - - @Override - public String toString() { - return stringify.apply(this); - } - - @Override - public String toShortString() { - return getTaggedPartnerNumber(); - } - - public static RbacSpec rbac() { - return rbacViewFor("partner", HsOfficePartnerEntity.class) - .withIdentityView(SQL.projection("'P-' || partnerNumber")) - .withUpdatableColumns("partnerRelUuid") - .toRole(GLOBAL, ADMIN).grantPermission(INSERT) - - .importRootEntityAliasProxy("partnerRel", HsOfficeRelationRbacEntity.class, - usingDefaultCase(), - directlyFetchedByDependsOnColumn(), - dependsOnColumn("partnerRelUuid")) - .createPermission(DELETE).grantedTo("partnerRel", OWNER) - .createPermission(UPDATE).grantedTo("partnerRel", ADMIN) - .createPermission(SELECT).grantedTo("partnerRel", TENANT) - - .importSubEntityAlias("partnerDetails", HsOfficePartnerDetailsEntity.class, - directlyFetchedByDependsOnColumn(), - dependsOnColumn("detailsUuid")) - .createPermission("partnerDetails", DELETE).grantedTo("partnerRel", OWNER) - .createPermission("partnerDetails", UPDATE).grantedTo("partnerRel", AGENT) - .createPermission("partnerDetails", SELECT).grantedTo("partnerRel", AGENT); // not TENANT! - } - - public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("5-hs-office/504-partner/5043-hs-office-partner-rbac"); - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java index b01ccc6b..ecf8adc9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcher.java @@ -9,10 +9,10 @@ import jakarta.persistence.EntityManager; class HsOfficePartnerEntityPatcher implements EntityPatcher { private final EntityManager em; - private final HsOfficePartnerEntity entity; + private final HsOfficePartnerRbacEntity entity; HsOfficePartnerEntityPatcher( final EntityManager em, - final HsOfficePartnerEntity entity) { + final HsOfficePartnerRbacEntity entity) { this.em = em; this.entity = entity; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacEntity.java new file mode 100644 index 00000000..eddab1c7 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacEntity.java @@ -0,0 +1,59 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import net.hostsharing.hsadminng.errors.DisplayAs; +import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity; +import net.hostsharing.hsadminng.rbac.generator.RbacSpec; +import net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL; + +import jakarta.persistence.*; +import java.io.IOException; + +import static jakarta.persistence.CascadeType.*; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Column.dependsOnColumn; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.ColumnValue.usingDefaultCase; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.GLOBAL; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.*; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Permission.SELECT; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.Role.*; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.SQL.directlyFetchedByDependsOnColumn; +import static net.hostsharing.hsadminng.rbac.generator.RbacSpec.rbacViewFor; + +@Entity +@Table(schema = "hs_office", name = "partner_rv") +@Getter +@Setter +@SuperBuilder(toBuilder = true) +@NoArgsConstructor +@DisplayAs("RbacPartner") +public class HsOfficePartnerRbacEntity extends HsOfficePartner { + + public static RbacSpec rbac() { + return rbacViewFor("partner", HsOfficePartnerRbacEntity.class) + .withIdentityView(SQL.projection("'P-' || partnerNumber")) + .withUpdatableColumns("partnerRelUuid") + .toRole(GLOBAL, ADMIN).grantPermission(INSERT) + + .importRootEntityAliasProxy("partnerRel", HsOfficeRelationRbacEntity.class, + usingDefaultCase(), + directlyFetchedByDependsOnColumn(), + dependsOnColumn("partnerRelUuid")) + .createPermission(DELETE).grantedTo("partnerRel", OWNER) + .createPermission(UPDATE).grantedTo("partnerRel", ADMIN) + .createPermission(SELECT).grantedTo("partnerRel", TENANT) + + .importSubEntityAlias("partnerDetails", HsOfficePartnerDetailsEntity.class, + directlyFetchedByDependsOnColumn(), + dependsOnColumn("detailsUuid")) + .createPermission("partnerDetails", DELETE).grantedTo("partnerRel", OWNER) + .createPermission("partnerDetails", UPDATE).grantedTo("partnerRel", AGENT) + .createPermission("partnerDetails", SELECT).grantedTo("partnerRel", AGENT); // not TENANT! + } + + public static void main(String[] args) throws IOException { + rbac().generateWithBaseFileName("5-hs-office/504-partner/5043-hs-office-partner-rbac"); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepository.java new file mode 100644 index 00000000..759fd133 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepository.java @@ -0,0 +1,47 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import io.micrometer.core.annotation.Timed; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface HsOfficePartnerRbacRepository extends Repository { + + @Timed("app.office.partners.repo.findByUuid.rbac") + Optional findByUuid(UUID id); + + @Timed("app.office.partners.repo.findAll.rbac") + List findAll(); // TODO.refa: move to a repo in test sources + + @Query(value = """ + select partner.uuid, partner.detailsuuid, partner.partnernumber, partner.partnerreluuid, partner.version + from hs_office.partner_rv partner + join hs_office.relation partnerRel on partnerRel.uuid = partner.partnerreluuid + join hs_office.contact contact on contact.uuid = partnerRel.contactuuid + join hs_office.person partnerPerson on partnerPerson.uuid = partnerRel.holderuuid + left join hs_office.partner_details_rv partnerDetails on partnerDetails.uuid = partner.detailsuuid + where :name is null + or (partnerDetails.uuid is not null and partnerDetails.birthname like (cast(:name as text) || '%') escape '') + or contact.caption like (cast(:name as text) || '%') escape '' + or partnerPerson.tradename like (cast(:name as text) || '%') escape '' + or partnerPerson.givenname like (cast(:name as text) || '%') escape '' + or partnerPerson.familyname like (cast(:name as text) || '%') escape '' + """, nativeQuery = true) + @Timed("app.office.partners.repo.findPartnerByOptionalNameLike.rbac") + List findPartnerByOptionalNameLike(String name); + + @Timed("app.office.partners.repo.findPartnerByPartnerNumber.rbac") + Optional findPartnerByPartnerNumber(Integer partnerNumber); + + @Timed("app.office.partners.repo.save.rbac") + HsOfficePartnerRbacEntity save(final HsOfficePartnerRbacEntity entity); + + @Timed("app.office.partners.repo.count.rbac") + long count(); + + @Timed("app.office.partners.repo.deleteByUuid.rbac") + int deleteByUuid(UUID uuid); +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealEntity.java new file mode 100644 index 00000000..ddaf346b --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealEntity.java @@ -0,0 +1,21 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import net.hostsharing.hsadminng.errors.DisplayAs; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + + +@Entity +@Table(schema = "hs_office", name = "partner") +@Getter +@Setter +@SuperBuilder(toBuilder = true) +@NoArgsConstructor +@DisplayAs("RealPartner") +public class HsOfficePartnerRealEntity extends HsOfficePartner { +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealRepository.java new file mode 100644 index 00000000..a971cbf2 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRealRepository.java @@ -0,0 +1,41 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import io.micrometer.core.annotation.Timed; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface HsOfficePartnerRealRepository extends Repository { + + @Timed("app.office.partners.repo.findByUuid.real") + Optional findByUuid(UUID id); + + @Timed("app.office.partners.repo.findAll.real") + List findAll(); // TODO.refa: move to a repo in test sources + + @Query(value = """ + select partner.uuid, partner.detailsuuid, partner.partnernumber, partner.partnerreluuid, partner.version + from hs_office.partner partner + join hs_office.relation partnerRel on partnerRel.uuid = partner.partnerreluuid + join hs_office.contact contact on contact.uuid = partnerRel.contactuuid + join hs_office.person partnerPerson on partnerPerson.uuid = partnerRel.holderuuid + left join hs_office.partner_details_rv partnerDetails on partnerDetails.uuid = partner.detailsuuid + where :name is null + or (partnerDetails.uuid is not null and partnerDetails.birthname like (cast(:name as text) || '%') escape '') + or contact.caption like (cast(:name as text) || '%') escape '' + or partnerPerson.tradename like (cast(:name as text) || '%') escape '' + or partnerPerson.givenname like (cast(:name as text) || '%') escape '' + or partnerPerson.familyname like (cast(:name as text) || '%') escape '' + """, nativeQuery = true) + @Timed("app.office.partners.repo.findPartnerByOptionalNameLike.real") + List findPartnerByOptionalNameLike(String name); + + @Timed("app.office.partners.repo.findPartnerByPartnerNumber.real") + Optional findPartnerByPartnerNumber(Integer partnerNumber); + + @Timed("app.office.partners.repo.save.real") + HsOfficePartnerRealEntity save(final HsOfficePartnerRealEntity entity); +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java deleted file mode 100644 index 3ae4a26a..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.hostsharing.hsadminng.hs.office.partner; - -import io.micrometer.core.annotation.Timed; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.Repository; - -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -public interface HsOfficePartnerRepository extends Repository { - - @Timed("app.office.partners.repo.findByUuid") - Optional findByUuid(UUID id); - - @Timed("app.office.partners.repo.findAll") - List findAll(); // TODO.refa: move to a repo in test sources - - @Query(""" - SELECT partner FROM HsOfficePartnerEntity partner - JOIN HsOfficeRelationRealEntity rel ON rel.uuid = partner.partnerRel.uuid - JOIN HsOfficeContactRealEntity contact ON contact.uuid = rel.contact.uuid - JOIN HsOfficePersonRealEntity person ON person.uuid = rel.holder.uuid - WHERE :name is null - OR partner.details.birthName like concat(cast(:name as text), '%') - OR contact.caption like concat(cast(:name as text), '%') - OR person.tradeName like concat(cast(:name as text), '%') - OR person.givenName like concat(cast(:name as text), '%') - OR person.familyName like concat(cast(:name as text), '%') - """) - @Timed("app.office.partners.repo.findPartnerByOptionalNameLike") - List findPartnerByOptionalNameLike(String name); - - @Timed("app.office.partners.repo.findPartnerByPartnerNumber") - Optional findPartnerByPartnerNumber(Integer partnerNumber); - - @Timed("app.office.partners.repo.save") - HsOfficePartnerEntity save(final HsOfficePartnerEntity entity); - - @Timed("app.office.partners.repo.count") - long count(); - - @Timed("app.office.partners.repo.deleteByUuid") - int deleteByUuid(UUID uuid); -} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java index 02012820..28a1b56f 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.person; import io.micrometer.core.annotation.Timed; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePersonsApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonInsertResource; @@ -24,7 +24,7 @@ public class HsOfficePersonController implements HsOfficePersonsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsOfficePersonRbacRepository personRepo; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealEntity.java index 766785a0..0d320d07 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealEntity.java @@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.office.person; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import lombok.experimental.FieldNameConstants; import lombok.experimental.SuperBuilder; import net.hostsharing.hsadminng.errors.DisplayAs; @@ -17,7 +16,6 @@ import jakarta.persistence.Table; @Setter @NoArgsConstructor @SuperBuilder(toBuilder = true) -@FieldNameConstants @DisplayAs("RealPerson") public class HsOfficePersonRealEntity extends HsOfficePerson { } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java index a4f17edf..83eda5a0 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java @@ -9,7 +9,7 @@ import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelation import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; @@ -32,7 +32,7 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private HsOfficeRelationRbacRepository rbacRelationRepo; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java index 02a3beb4..61399d1e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java @@ -2,11 +2,14 @@ package net.hostsharing.hsadminng.hs.office.sepamandate; import io.micrometer.core.annotation.Timed; import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository; +import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeSepaMandatesApi; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandateInsertResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandatePatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandateResource; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; @@ -15,6 +18,7 @@ import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBui import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import jakarta.validation.ValidationException; import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; @@ -29,7 +33,13 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; + + @Autowired + private HsOfficeDebitorRepository debitorRepo; + + @Autowired + private HsOfficeBankAccountRepository bankAccountRepo; @Autowired private HsOfficeSepaMandateRepository sepaMandateRepo; @@ -137,10 +147,22 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { if (entity.getValidity().hasUpperBound()) { resource.setValidTo(entity.getValidity().upper().minusDays(1)); } + resource.setDebitor(mapper.map(entity.getDebitor(), HsOfficeDebitorResource.class)); resource.getDebitor().setDebitorNumber(entity.getDebitor().getTaggedDebitorNumber()); + resource.getDebitor().getPartner().setPartnerNumber(entity.getDebitor().getPartner().getTaggedPartnerNumber()); }; final BiConsumer SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { entity.setValidity(toPostgresDateRange(resource.getValidFrom(), resource.getValidTo())); + entity.setDebitor(debitorRepo.findByUuid(resource.getDebitorUuid()).orElseThrow( () -> + new ValidationException( + "debitor.uuid='" + resource.getDebitorUuid() + "' not found or not accessible" + ) + )); + entity.setBankAccount(bankAccountRepo.findByUuid(resource.getBankAccountUuid()).orElseThrow( () -> + new ValidationException( + "bankAccount.uuid='" + resource.getBankAccountUuid() + "' not found or not accessible" + ) + )); }; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/UuidResolver.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/UuidResolver.java new file mode 100644 index 00000000..6ff98ca1 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/UuidResolver.java @@ -0,0 +1,17 @@ +package net.hostsharing.hsadminng.hs.validation; + +import lombok.experimental.UtilityClass; + +import jakarta.validation.ValidationException; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Function; + +@UtilityClass +public class UuidResolver { + + public static T resolve(final String jsonPath, final UUID uuid, final Function> findByUuid) { + return findByUuid.apply(uuid) + .orElseThrow(() -> new ValidationException("Unable to find " + jsonPath + ": " + uuid)); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/mapper/StandardMapper.java b/src/main/java/net/hostsharing/hsadminng/mapper/StandardMapper.java deleted file mode 100644 index 3f6a851b..00000000 --- a/src/main/java/net/hostsharing/hsadminng/mapper/StandardMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.hostsharing.hsadminng.mapper; - -import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * A nicer API for ModelMapper in standard mode. - */ -@Component -public class StandardMapper extends Mapper { - - public StandardMapper(@Autowired final EntityManagerWrapper em) { - super(em); - getConfiguration().setAmbiguityIgnored(true); - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/persistence/BaseEntity.java b/src/main/java/net/hostsharing/hsadminng/persistence/BaseEntity.java index b3e5a535..aede0d7d 100644 --- a/src/main/java/net/hostsharing/hsadminng/persistence/BaseEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/persistence/BaseEntity.java @@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.persistence; import org.hibernate.Hibernate; +import jakarta.persistence.EntityManager; import java.util.UUID; public interface BaseEntity> { @@ -15,4 +16,10 @@ public interface BaseEntity> { //noinspection unchecked return (T) this; }; + + default T reload(final EntityManager em) { + em.flush(); + em.refresh(this); + return load(); + } } diff --git a/src/main/java/net/hostsharing/hsadminng/persistence/EntityExistsValidator.java b/src/main/java/net/hostsharing/hsadminng/persistence/EntityExistsValidator.java deleted file mode 100644 index 1b29e007..00000000 --- a/src/main/java/net/hostsharing/hsadminng/persistence/EntityExistsValidator.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.hostsharing.hsadminng.persistence; - -import net.hostsharing.hsadminng.errors.DisplayAs.DisplayName; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import jakarta.persistence.Entity; -import jakarta.validation.ValidationException; - -@Service -public class EntityExistsValidator { - - @Autowired - private EntityManagerWrapper em; - - public > void validateEntityExists(final String property, final T entitySkeleton) { - final var foundEntity = em.find(entityClass(entitySkeleton), entitySkeleton.getUuid()); - if ( foundEntity == null) { - throw new ValidationException("Unable to find " + DisplayName.of(entitySkeleton) + " by " + property + ": " + entitySkeleton.getUuid()); - } - } - - private static > Class entityClass(final T entityOrProxy) { - final var entityClass = entityClass(entityOrProxy.getClass()); - if (entityClass == null) { - throw new IllegalArgumentException("@Entity not found in superclass hierarchy of " + entityOrProxy.getClass()); - } - return entityClass; - } - - private static Class entityClass(final Class entityOrProxyClass) { - return entityOrProxyClass.isAnnotationPresent(Entity.class) - ? entityOrProxyClass - : entityOrProxyClass.getSuperclass() == null - ? null - : entityClass(entityOrProxyClass.getSuperclass()); - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantController.java b/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantController.java index 500c0ff3..02dc6ae2 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantController.java @@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.rbac.grant; import io.micrometer.core.annotation.Timed; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacGrantsApi; import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacGrantResource; import org.springframework.beans.factory.annotation.Autowired; @@ -23,7 +23,7 @@ public class RbacGrantController implements RbacGrantsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private RbacGrantRepository rbacGrantRepository; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramService.java b/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramService.java index 64a2d33e..7e0c7d4c 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramService.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramService.java @@ -30,7 +30,7 @@ public class RbacGrantsDiagramService { try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { writer.write(""" ### all grants to %s - + ```mermaid %s ``` @@ -49,8 +49,18 @@ public class RbacGrantsDiagramService { NON_TEST_ENTITIES; public static final EnumSet ALL = EnumSet.allOf(Include.class); - public static final EnumSet ALL_TEST_ENTITY_RELATED = EnumSet.of(USERS, DETAILS, NOT_ASSUMED, TEST_ENTITIES, PERMISSIONS); - public static final EnumSet ALL_NON_TEST_ENTITY_RELATED = EnumSet.of(USERS, DETAILS, NOT_ASSUMED, NON_TEST_ENTITIES, PERMISSIONS); + public static final EnumSet ALL_TEST_ENTITY_RELATED = EnumSet.of( + USERS, + DETAILS, + NOT_ASSUMED, + TEST_ENTITIES, + PERMISSIONS); + public static final EnumSet ALL_NON_TEST_ENTITY_RELATED = EnumSet.of( + USERS, + DETAILS, + NOT_ASSUMED, + NON_TEST_ENTITIES, + PERMISSIONS); } @Autowired @@ -66,9 +76,9 @@ public class RbacGrantsDiagramService { public String allGrantsTocurrentSubject(final EnumSet includes) { final var graph = new LimitedHashSet(); - for ( UUID subjectUuid: context.fetchCurrentSubjectOrAssumedRolesUuids() ) { + for (UUID subjectUuid : context.fetchCurrentSubjectOrAssumedRolesUuids()) { traverseGrantsTo(graph, subjectUuid, includes); - } + } return toMermaidFlowchart(graph, includes); } @@ -78,7 +88,7 @@ public class RbacGrantsDiagramService { if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm:")) { return; } - if ( !g.getDescendantIdName().startsWith("role:rbac.global")) { + if (!g.getDescendantIdName().startsWith("role:rbac.global")) { if (!includes.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(":rbactest.")) { return; } @@ -94,12 +104,17 @@ public class RbacGrantsDiagramService { } public String allGrantsFrom(final UUID targetObject, final String op, final EnumSet includes) { - final var refUuid = (UUID) em.createNativeQuery("SELECT uuid FROM rbac.permission WHERE objectuuid=:targetObject AND op=:op") + final var graph = new LimitedHashSet(); + + @SuppressWarnings("unchecked") // List -> List> + final var refUuidLists = (List>) em.createNativeQuery( + "select uuid from rbac.permission where objectUuid=:targetObject and op=:op", + List.class) .setParameter("targetObject", targetObject) .setParameter("op", op) - .getSingleResult(); - final var graph = new LimitedHashSet(); - traverseGrantsFrom(graph, refUuid, includes); + .getResultList(); + refUuidLists.stream().flatMap(Collection::stream) + .forEach(refUuid -> traverseGrantsFrom(graph, refUuid, includes)); return toMermaidFlowchart(graph, includes); } @@ -125,20 +140,20 @@ public class RbacGrantsDiagramService { final var entities = includes.contains(DETAILS) ? graph.stream() - .flatMap(g -> Stream.of( - new Node(g.getAscendantIdName(), g.getAscendingUuid()), - new Node(g.getDescendantIdName(), g.getDescendantUuid())) - ) - .collect(groupingBy(RbacGrantsDiagramService::renderEntityIdName)) - .entrySet().stream() - .map(entity -> "subgraph " + cleanId(entity.getKey()) + renderSubgraph(entity.getKey()) + "\n\n " - + entity.getValue().stream() - .map(n -> renderNode(n.idName(), n.uuid()).replace("\n", "\n ")) - .sorted() - .distinct() - .collect(joining("\n\n "))) - .collect(joining("\n\nend\n\n")) - + "\n\nend\n\n" + .flatMap(g -> Stream.of( + new Node(g.getAscendantIdName(), g.getAscendingUuid()), + new Node(g.getDescendantIdName(), g.getDescendantUuid())) + ) + .collect(groupingBy(RbacGrantsDiagramService::renderEntityIdName)) + .entrySet().stream() + .map(entity -> "subgraph " + cleanId(entity.getKey()) + renderSubgraph(entity.getKey()) + "\n\n " + + entity.getValue().stream() + .map(n -> renderNode(n.idName(), n.uuid()).replace("\n", "\n ")) + .sorted() + .distinct() + .collect(joining("\n\n "))) + .collect(joining("\n\nend\n\n")) + + "\n\nend\n\n" : ""; final var grants = graph.stream() @@ -193,7 +208,7 @@ public class RbacGrantsDiagramService { final var refType = refType(idName); if (refType.equals("user")) { - final var displayName = idName.substring(refType.length()+1); + final var displayName = idName.substring(refType.length() + 1); return "(" + displayName + "\nref:" + uuid + ")"; } if (refType.equals("role")) { @@ -215,15 +230,20 @@ public class RbacGrantsDiagramService { @NotNull private static String cleanId(final String idName) { return idName.replaceAll("@.*", "") - .replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", "").replace(">", ":").replace("|", "_"); + .replace("[", "") + .replace("]", "") + .replace("(", "") + .replace(")", "") + .replace(",", "") + .replace(">", ":") + .replace("|", "_"); } - static class LimitedHashSet extends HashSet { @Override public boolean add(final T t) { - if (size() < GRANT_LIMIT ) { + if (size() < GRANT_LIMIT) { return super.add(t); } else { return false; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/role/RbacRoleController.java b/src/main/java/net/hostsharing/hsadminng/rbac/role/RbacRoleController.java index 121d4d44..de7446e8 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/role/RbacRoleController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/role/RbacRoleController.java @@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.rbac.role; import io.micrometer.core.annotation.Timed; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacRolesApi; import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacRoleResource; import org.springframework.beans.factory.annotation.Autowired; @@ -19,7 +19,7 @@ public class RbacRoleController implements RbacRolesApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private RbacRoleRepository rbacRoleRepository; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectController.java b/src/main/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectController.java index f2f7afab..c893fb98 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectController.java @@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.rbac.subject; import io.micrometer.core.annotation.Timed; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacSubjectsApi; import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacSubjectPermissionResource; import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacSubjectResource; @@ -22,7 +22,7 @@ public class RbacSubjectController implements RbacSubjectsApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private RbacSubjectRepository rbacSubjectRepository; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerController.java b/src/main/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerController.java index 26628545..82e3a57d 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerController.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.rbac.test.cust; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.test.generated.api.v1.api.TestCustomersApi; import net.hostsharing.hsadminng.test.generated.api.v1.model.TestCustomerResource; import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +21,7 @@ public class TestCustomerController implements TestCustomersApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private TestCustomerRepository testCustomerRepository; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageController.java b/src/main/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageController.java index d503bf58..43fd3b0b 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageController.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.rbac.test.pac; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.mapper.OptionalFromJson; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.test.generated.api.v1.api.TestPackagesApi; @@ -21,7 +21,7 @@ public class TestPackageController implements TestPackagesApi { private Context context; @Autowired - private StandardMapper mapper; + private StrictMapper mapper; @Autowired private TestPackageRepository testPackageRepository; diff --git a/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml index c868a459..9b115889 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml @@ -90,6 +90,7 @@ components: type: boolean vatReverseCharge: type: boolean + # TODO.feat: alternatively the complete refundBankAccount refundBankAccount.uuid: type: string format: uuid diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql index e7229595..5dd06009 100644 --- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql @@ -43,7 +43,10 @@ end; $$; do language plpgsql $$ begin - call base.defineContext('creating coopSharesTransaction test-data'); + call base.defineContext('creating coopSharesTransaction test-data', + null, + 'superuser-alex@hostsharing.net', + 'rbac.global#global:ADMIN'); SET CONSTRAINTS ALL DEFERRED; call hs_office.coopsharetx_create_test_data(10001, '01'); diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql index ce94ddfc..2ce3186b 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql @@ -49,7 +49,10 @@ end; $$; do language plpgsql $$ begin - call base.defineContext('creating coopAssetsTransaction test-data'); + call base.defineContext('creating coopAssetsTransaction test-data', + null, + 'superuser-alex@hostsharing.net', + 'rbac.global#global:ADMIN'); SET CONSTRAINTS ALL DEFERRED; call hs_office.coopassettx_create_test_data(10001, '01'); diff --git a/src/test/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandlerUnitTest.java b/src/test/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandlerUnitTest.java index e54eac1e..8675e6f6 100644 --- a/src/test/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandlerUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandlerUnitTest.java @@ -81,8 +81,7 @@ class RestResponseEntityExceptionHandlerUnitTest { void handleJpaObjectRetrievalFailureExceptionWithDisplayName() { // given final var givenException = new JpaObjectRetrievalFailureException( - new EntityNotFoundException( - "Unable to find net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity with id 12345-123454") + new EntityNotFoundException("Unable to find Entity with id 12345-123454") ); final var givenWebRequest = mock(WebRequest.class); @@ -91,7 +90,7 @@ class RestResponseEntityExceptionHandlerUnitTest { // then assertThat(errorResponse.getBody().getStatusCode()).isEqualTo(400); - assertThat(errorResponse.getBody().getMessage()).isEqualTo("ERROR: [400] Unable to find Partner with uuid 12345-123454"); + assertThat(errorResponse.getBody().getMessage()).isEqualTo("ERROR: [400] Unable to find Entity with id 12345-123454"); } @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java index 4715ad72..ab3b3d08 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java @@ -643,7 +643,6 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup final var givenProject = realProjectRepo.findByCaption(projectCaption).stream() .findAny().orElseThrow(); final var newBookingItem = HsBookingItemRealEntity.builder() - .uuid(UUID.randomUUID()) .project(givenProject) .type(hsBookingItemType) .caption("some test-booking") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerRestTest.java index 7c0c68b0..0d7b11f7 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerRestTest.java @@ -14,7 +14,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; @@ -48,23 +48,23 @@ class HsBookingItemControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; @Autowired @SuppressWarnings("unused") // not used in test, but in controller class StrictMapper mapper; - @MockBean + @MockitoBean EntityManagerWrapper em; - @MockBean + @MockitoBean EntityManagerFactory emf; - @MockBean + @MockitoBean HsBookingProjectRealRepository realProjectRepo; - @MockBean + @MockitoBean HsBookingItemRbacRepository rbacBookingItemRepo; @TestConfiguration diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java index b6c8d757..9a222b0c 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -61,7 +61,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup @PersistenceContext EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java index 05313c56..37b54e7e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java @@ -270,7 +270,6 @@ class HsBookingProjectControllerAcceptanceTest extends ContextBasedTestWithClean context.define("superuser-alex@hostsharing.net"); final var givenDebitor = debitorRepo.findByDebitorNumber(debitorNumber).stream().findAny().orElseThrow(); final var newBookingProject = HsBookingProjectRealEntity.builder() - .uuid(UUID.randomUUID()) .debitor(givenDebitor) .caption(caption) .build(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java index 411d4360..971b1ba8 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -56,7 +56,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea @PersistenceContext EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java index 9055148e..ea7c93b1 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java @@ -488,7 +488,6 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup final var givenAsset = givenSomeTemporaryHostingAsset(() -> HsHostingAssetRealEntity.builder() - .uuid(UUID.randomUUID()) .bookingItem(givenSomeNewBookingItem( "D-1000111 default project", HsBookingItemType.MANAGED_SERVER, @@ -571,7 +570,6 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup final var givenAsset = givenSomeTemporaryHostingAsset(() -> HsHostingAssetRealEntity.builder() - .uuid(UUID.randomUUID()) .type(UNIX_USER) .parentAsset(givenRealHostingAsset(MANAGED_WEBSPACE, "fir01")) .identifier("fir01-temp") @@ -648,7 +646,6 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup context.define("superuser-alex@hostsharing.net"); final var givenAsset = givenSomeTemporaryHostingAsset(() -> HsHostingAssetRealEntity.builder() - .uuid(UUID.randomUUID()) .bookingItem(givenSomeNewBookingItem( "D-1000111 default project", HsBookingItemType.MANAGED_SERVER, @@ -681,7 +678,6 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup context.define("superuser-alex@hostsharing.net"); final var givenAsset = givenSomeTemporaryHostingAsset(() -> HsHostingAssetRealEntity.builder() - .uuid(UUID.randomUUID()) .bookingItem(givenSomeNewBookingItem( "D-1000111 default project", HsBookingItemType.MANAGED_SERVER, diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java index be1eaef9..3b10e26e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java @@ -9,7 +9,7 @@ import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealRepository; import net.hostsharing.hsadminng.mapper.Array; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.api.BeforeEach; @@ -24,7 +24,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -54,7 +54,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(HsHostingAssetController.class) -@Import({ StandardMapper.class, JsonObjectMapperConfiguration.class, DisableSecurityConfig.class }) +@Import({ StrictMapper.class, JsonObjectMapperConfiguration.class, DisableSecurityConfig.class }) @RunWith(SpringRunner.class) @ActiveProfiles("test") public class HsHostingAssetControllerRestTest { @@ -62,27 +62,27 @@ public class HsHostingAssetControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; @Autowired @SuppressWarnings("unused") // not used in test, but in controller class - StandardMapper mapper; + StrictMapper mapper; - @MockBean + @MockitoBean EntityManagerWrapper em; - @MockBean + @MockitoBean EntityManagerFactory emf; - @MockBean + @MockitoBean @SuppressWarnings("unused") // bean needs to be present for HsHostingAssetController private HsBookingItemRealRepository realBookingItemRepo; - @MockBean + @MockitoBean private HsHostingAssetRealRepository realAssetRepo; - @MockBean + @MockitoBean private HsHostingAssetRbacRepository rbacAssetRepo; @TestConfiguration diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java index 90ac5bf6..4024d16f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -70,7 +70,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu @PersistenceContext EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactoryUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactoryUnitTest.java index cf2fc350..fb2e622e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactoryUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/DomainSetupHostingAssetFactoryUnitTest.java @@ -12,7 +12,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.fasterxml.jackson.databind.ObjectMapper; import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -59,7 +59,7 @@ class DomainSetupHostingAssetFactoryUnitTest { private ObjectMapper jsonMapper = new JsonObjectMapperConfiguration().customObjectMapper().build(); @Spy - private StandardMapper standardMapper = new StandardMapper(emw); + private StrictMapper StrictMapper = new StrictMapper(emw); @InjectMocks private HsBookingItemCreatedListener listener; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListenerUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListenerUnitTest.java index 07442a71..63af1b78 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListenerUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/HsBookingItemCreatedListenerUnitTest.java @@ -8,7 +8,7 @@ import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedEventEntity; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.lambda.Reducer; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapperFake; import org.junit.jupiter.api.extension.ExtendWith; @@ -42,7 +42,7 @@ class HsBookingItemCreatedListenerUnitTest { private ObjectMapper jsonMapper = new JsonObjectMapperConfiguration().customObjectMapper().build(); @Spy - private StandardMapper standardMapper = new StandardMapper(emw); + private StrictMapper StrictMapper = new StrictMapper(emw); @InjectMocks private HsBookingItemCreatedListener listener; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/ManagedWebspaceHostingAssetFactoryUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/ManagedWebspaceHostingAssetFactoryUnitTest.java index 511e408c..758dc5e2 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/ManagedWebspaceHostingAssetFactoryUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/factories/ManagedWebspaceHostingAssetFactoryUnitTest.java @@ -13,7 +13,7 @@ import net.hostsharing.hsadminng.hs.hosting.asset.validators.Dns; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContact; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity; import net.hostsharing.hsadminng.lambda.Reducer; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapperFake; import org.junit.jupiter.api.BeforeEach; @@ -55,7 +55,7 @@ class ManagedWebspaceHostingAssetFactoryUnitTest { private ObjectMapper jsonMapper = new JsonObjectMapperConfiguration().customObjectMapper().build(); @Spy - private StandardMapper standardMapper = new StandardMapper(emw); + private StrictMapper StrictMapper = new StrictMapper(emw); @InjectMocks private HsBookingItemCreatedListener listener; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java index da89e268..f4095e5b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java @@ -10,7 +10,7 @@ import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipStatus; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation; @@ -84,7 +84,7 @@ public abstract class BaseOfficeDataImport extends CsvDataImport { static Map contacts = new WriteOnceMap<>(); static Map persons = new WriteOnceMap<>(); - static Map partners = new WriteOnceMap<>(); + static Map partners = new WriteOnceMap<>(); static Map debitors = new WriteOnceMap<>(); static Map memberships = new WriteOnceMap<>(); @@ -743,7 +743,7 @@ public abstract class BaseOfficeDataImport extends CsvDataImport { null // is set during contacts import depending on assigned roles ); - final var partner = HsOfficePartnerEntity.builder() + final var partner = HsOfficePartnerRealEntity.builder() .partnerNumber(rec.getInteger("member_id")) .details(HsOfficePartnerDetailsEntity.builder().build()) .partnerRel(partnerRel) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java index 049681e4..811f3752 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java @@ -14,7 +14,7 @@ import org.junit.jupiter.api.extension.TestWatcher; import org.opentest4j.AssertionFailedError; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.core.io.Resource; import org.springframework.transaction.support.TransactionTemplate; @@ -76,7 +76,7 @@ public class CsvDataImport extends ContextBasedTest { @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; static final LinkedHashSet errors = new LinkedHashSet<>(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerRestTest.java index a83558d6..597421a3 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerRestTest.java @@ -1,13 +1,13 @@ package net.hostsharing.hsadminng.hs.office.bankaccount; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; @@ -26,14 +26,14 @@ class HsOfficeBankAccountControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; - @MockBean + @MockitoBean @SuppressWarnings("unused") // not used in test, but in controller class - StandardMapper mapper; + StrictMapper mapper; - @MockBean + @MockitoBean HsOfficeBankAccountRepository bankAccountRepo; enum InvalidIbanTestCase { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java index f0f197d9..7a95b503 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java @@ -11,7 +11,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -46,7 +46,7 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactControllerAcceptanceTest.java index a4b19eef..48d12f44 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactControllerAcceptanceTest.java @@ -374,7 +374,6 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu return jpaAttempt.transacted(() -> { context.define(creatingUser); final var newContact = HsOfficeContactRbacEntity.builder() - .uuid(UUID.randomUUID()) .caption("Temp from " + Context.getCallerMethodNameFromStackFrame(1) ) .postalAddress(Map.ofEntries( entry("name", RandomStringUtils.randomAlphabetic(6) + " " + RandomStringUtils.randomAlphabetic(10)), diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java index 5b59f3b6..7e652325 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java @@ -11,7 +11,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -46,7 +46,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java index b9cb7aff..45b2e30d 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java @@ -4,7 +4,7 @@ import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.rbac.test.JsonBuilder; @@ -17,10 +17,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -67,7 +67,7 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { private static final String ORIGIN_MEMBER_NUMBER = "M-1111100"; public final HsOfficeMembershipEntity ORIGIN_TARGET_MEMBER_ENTITY = HsOfficeMembershipEntity.builder() .uuid(ORIGIN_MEMBERSHIP_UUID) - .partner(HsOfficePartnerEntity.builder() + .partner(HsOfficePartnerRealEntity.builder() .partnerNumber(partnerNumberOf(ORIGIN_MEMBER_NUMBER)) .build()) .memberNumberSuffix(suffixOf(ORIGIN_MEMBER_NUMBER)) @@ -77,7 +77,7 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { private static final String AVAILABLE_TARGET_MEMBER_NUMBER = "M-1234500"; public final HsOfficeMembershipEntity AVAILABLE_MEMBER_ENTITY = HsOfficeMembershipEntity.builder() .uuid(AVAILABLE_TARGET_MEMBERSHIP_UUID) - .partner(HsOfficePartnerEntity.builder() + .partner(HsOfficePartnerRealEntity.builder() .partnerNumber(partnerNumberOf(AVAILABLE_TARGET_MEMBER_NUMBER)) .build()) .memberNumberSuffix(suffixOf(AVAILABLE_TARGET_MEMBER_NUMBER)) @@ -499,20 +499,20 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; @Autowired @SuppressWarnings("unused") // not used in test, but in controller class StrictMapper mapper; - @MockBean + @MockitoBean EntityManagerWrapper emw; // even if not used in test anymore, it's needed by base-class of StrictMapper - @MockBean + @MockitoBean HsOfficeCoopAssetsTransactionRepository coopAssetsTransactionRepo; - @MockBean + @MockitoBean HsOfficeMembershipRepository membershipRepo; static final String INSERT_REQUEST_BODY_TEMPLATE = """ diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java index 01248496..706c8034 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -51,7 +51,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java index 5568fa2f..810f0a60 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerAcceptanceTest.java @@ -170,7 +170,9 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased final var givenMembership = membershipRepo.findMembershipByMemberNumber(1000101).orElseThrow(); final var location = RestAssured // @formatter:off - .given().header("current-subject", "superuser-alex@hostsharing.net").contentType(ContentType.JSON).body(""" + .given() + .header("current-subject", "superuser-alex@hostsharing.net") + .contentType(ContentType.JSON).body(""" { "membership.uuid": "%s", "transactionType": "SUBSCRIPTION", @@ -179,15 +181,29 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased "reference": "temp ref A", "comment": "just some test coop shares transaction" } - """.formatted(givenMembership.getUuid())).port(port).when().post("http://localhost/api/hs/office/coopsharestransactions").then().log().all().assertThat().statusCode(201).contentType(ContentType.JSON).body("uuid", isUuidValid()).body("", lenientlyEquals(""" + """.formatted(givenMembership.getUuid())) + .port(port) + .when() + .post("http://localhost/api/hs/office/coopsharestransactions") + .then() + .log().all() + .assertThat() + .statusCode(201) + .contentType(ContentType.JSON) + .body("uuid", isUuidValid()) + .body("", lenientlyEquals(""" { + "membership.uuid": "%s", "transactionType": "SUBSCRIPTION", "shareCount": 8, "valueDate": "2022-10-13", "reference": "temp ref A", "comment": "just some test coop shares transaction" } - """)).header("Location", startsWith("http://localhost")).extract().header("Location"); // @formatter:on + """.formatted(givenMembership.getUuid()))) + .header("Location", startsWith("http://localhost")) + .extract() + .header("Location"); // @formatter:on // finally, the new coopSharesTransaction can be accessed under the generated UUID final var newShareTxUuid = UUID.fromString(location.substring(location.lastIndexOf('/') + 1)); @@ -197,7 +213,7 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased @Test void globalAdmin_canAddCoopSharesReversalTransaction() { - context.define("superuser-alex@hostsharing.net"); + context.define("superuser-alex@hostsharing.net", "rbac.global#global:ADMIN"); final var givenMembership = membershipRepo.findMembershipByMemberNumber(1000101).orElseThrow(); final var givenTransaction = jpaAttempt.transacted(() -> { // TODO.impl: introduce something like transactedAsSuperuser / transactedAs("...", ...) @@ -214,46 +230,46 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased final var location = RestAssured // @formatter:off .given() - .header("current-subject", "superuser-alex@hostsharing.net") - .contentType(ContentType.JSON) - .body(""" - { - "membership.uuid": "%s", - "transactionType": "REVERSAL", - "shareCount": %s, - "valueDate": "2022-10-30", - "reference": "test reversal ref", - "comment": "some coop shares reversal transaction", - "revertedShareTx.uuid": "%s" - } - """.formatted( - givenMembership.getUuid(), - -givenTransaction.getShareCount(), - givenTransaction.getUuid())) - .port(port) + .header("current-subject", "superuser-alex@hostsharing.net") + .contentType(ContentType.JSON) + .body(""" + { + "membership.uuid": "%s", + "transactionType": "REVERSAL", + "shareCount": %s, + "valueDate": "2022-10-30", + "reference": "test reversal ref", + "comment": "some coop shares reversal transaction", + "revertedShareTx.uuid": "%s" + } + """.formatted( + givenMembership.getUuid(), + -givenTransaction.getShareCount(), + givenTransaction.getUuid())) + .port(port) .when() - .post("http://localhost/api/hs/office/coopsharestransactions") + .post("http://localhost/api/hs/office/coopsharestransactions") .then().log().all().assertThat() - .statusCode(201) - .contentType(ContentType.JSON) - .body("uuid", isUuidValid()) - .body("", lenientlyEquals(""" - { - "transactionType": "REVERSAL", - "shareCount": -13, - "valueDate": "2022-10-30", - "reference": "test reversal ref", - "comment": "some coop shares reversal transaction", - "revertedShareTx": { - "transactionType": "SUBSCRIPTION", - "shareCount": 13, - "valueDate": "2022-10-20", - "reference": "test ref" - } + .statusCode(201) + .contentType(ContentType.JSON) + .body("uuid", isUuidValid()) + .body("", lenientlyEquals(""" + { + "transactionType": "REVERSAL", + "shareCount": -13, + "valueDate": "2022-10-30", + "reference": "test reversal ref", + "comment": "some coop shares reversal transaction", + "revertedShareTx": { + "transactionType": "SUBSCRIPTION", + "shareCount": 13, + "valueDate": "2022-10-20", + "reference": "test ref" } - """)) - .header("Location", startsWith("http://localhost")) - .extract().header("Location"); // @formatter:on + } + """)) + .header("Location", startsWith("http://localhost")) + .extract().header("Location"); // @formatter:on // finally, the new coopAssetsTransaction can be accessed under the generated UUID final var newShareTxUuid = UUID.fromString( @@ -269,22 +285,34 @@ class HsOfficeCoopSharesTransactionControllerAcceptanceTest extends ContextBased final var givenMembership = membershipRepo.findMembershipByMemberNumber(1000101).orElseThrow(); RestAssured // @formatter:off - .given().header("current-subject", "superuser-alex@hostsharing.net").contentType(ContentType.JSON).body(""" - { - "membership.uuid": "%s", - "transactionType": "CANCELLATION", - "shareCount": -80, - "valueDate": "2022-10-13", - "reference": "temp ref X", - "comment": "just some test coop shares transaction" - } - """.formatted(givenMembership.getUuid())).port(port).when().post("http://localhost/api/hs/office/coopsharestransactions").then().log().all().assertThat().statusCode(400).contentType(ContentType.JSON).body("", lenientlyEquals(""" + .given() + .header("current-subject", "superuser-alex@hostsharing.net") + .contentType(ContentType.JSON) + .body(""" { - "statusCode": 400, - "statusPhrase": "Bad Request", - "message": "ERROR: [400] coop shares transaction would result in a negative number of shares" - } - """)); // @formatter:on + "membership.uuid": "%s", + "transactionType": "CANCELLATION", + "shareCount": -80, + "valueDate": "2022-10-13", + "reference": "temp ref X", + "comment": "just some test coop shares transaction" + } + """.formatted(givenMembership.getUuid())) + .port(port) + .when() + .post("http://localhost/api/hs/office/coopsharestransactions") + .then() + .log().all() + .assertThat() + .statusCode(400) + .contentType(ContentType.JSON) + .body("", lenientlyEquals(""" + { + "statusCode": 400, + "statusPhrase": "Bad Request", + "message": "ERROR: [400] coop shares transaction would result in a negative number of shares" + } + """)); // @formatter:on } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java index 5bc432de..60221df4 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java @@ -1,14 +1,15 @@ package net.hostsharing.hsadminng.hs.office.coopshares; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.rbac.test.JsonBuilder; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; @@ -31,16 +32,19 @@ class HsOfficeCoopSharesTransactionControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; - @MockBean + @MockitoBean @SuppressWarnings("unused") // not used in test, but in controller class - StandardMapper mapper; + StrictMapper mapper; - @MockBean + @MockitoBean HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo; + @MockitoBean + HsOfficeMembershipRepository membershipRepo; + static final String VALID_INSERT_REQUEST_BODY = """ { "membership.uuid": "%s", diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java index d428a9d7..afeae8c3 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -50,7 +50,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java index 7d72d56b..98be1755 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java @@ -6,7 +6,7 @@ import net.hostsharing.hsadminng.HsadminNgApplication; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealRepository; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRbacRepository; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository; @@ -28,6 +28,7 @@ import jakarta.persistence.PersistenceContext; import java.util.UUID; import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR; +import static net.hostsharing.hsadminng.rbac.role.RbacRoleType.ADMIN; import static net.hostsharing.hsadminng.rbac.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.hsadminng.test.JsonMatcher.lenientlyEquals; import static org.assertj.core.api.Assertions.assertThat; @@ -57,7 +58,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu HsOfficeDebitorRepository debitorRepo; @Autowired - HsOfficePartnerRepository partnerRepo; + HsOfficePartnerRbacRepository partnerRepo; @Autowired HsOfficeContactRealRepository contactRealRepo; @@ -467,7 +468,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu .post("http://localhost/api/hs/office/debitors") .then().log().all().assertThat() .statusCode(400) - .body("message", is("ERROR: [400] Unable to find RealContact by debitorRel.contactUuid: 00000000-0000-0000-0000-000000000000")); + .body("message", is("ERROR: [400] Unable to find debitorRel.contact.uuid: 00000000-0000-0000-0000-000000000000")); // @formatter:on } @@ -495,7 +496,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu .post("http://localhost/api/hs/office/debitors") .then().log().all().assertThat() .statusCode(400) - .body("message", is("ERROR: [400] Unable to find RealRelation by debitorRelUuid: 00000000-0000-0000-0000-000000000000")); + .body("message", is("ERROR: [400] Unable to find debitorRel.uuid: 00000000-0000-0000-0000-000000000000")); // @formatter:on } } @@ -695,16 +696,16 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu } @Test - void theContactOwner_canNotPatchARelatedDebitor() { + void theContactAdmin_canNotPatchARelatedDebitor() { context.define("superuser-alex@hostsharing.net"); final var givenDebitor = givenSomeTemporaryDebitor(); // @formatter:on RestAssured // @formatter:off - .given() + .given() .header("current-subject", "superuser-alex@hostsharing.net") - .header("assumed-roles", "hs_office.contact#tenthcontact:ADMIN") + .header("assumed-roles", givenDebitor.getDebitorRel().getContact().roleId(ADMIN) ) .contentType(ContentType.JSON) .body(""" { @@ -712,9 +713,9 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu } """) .port(port) - .when() + .when() .patch("http://localhost/api/hs/office/debitors/" + givenDebitor.getUuid()) - .then().log().all().assertThat() + .then().log().all().assertThat() .statusCode(403) .body("message", containsString("ERROR: [403] Subject")) .body("message", containsString("is not allowed to update hs_office.debitor uuid ")); @@ -802,7 +803,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu .vatReverseCharge(false) .build(); - return debitorRepo.save(newDebitor).load(); + return debitorRepo.save(newDebitor).reload(em); }).assertSuccessful().returnedValue(); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java index 57351efe..468e7006 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.debitor; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; @@ -30,7 +30,7 @@ class HsOfficeDebitorEntityUnitTest { .debitorNumberSuffix("67") .debitorRel(givenDebitorRel) .defaultPrefix("som") - .partner(HsOfficePartnerEntity.builder() + .partner(HsOfficePartnerRealEntity.builder() .partnerNumber(12345) .build()) .build(); @@ -45,7 +45,7 @@ class HsOfficeDebitorEntityUnitTest { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) .debitorNumberSuffix("67") - .partner(HsOfficePartnerEntity.builder() + .partner(HsOfficePartnerRealEntity.builder() .partnerNumber(12345) .build()) .build(); @@ -60,7 +60,7 @@ class HsOfficeDebitorEntityUnitTest { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) .debitorNumberSuffix("67") - .partner(HsOfficePartnerEntity.builder() + .partner(HsOfficePartnerRealEntity.builder() .partnerNumber(12345) .build()) .build(); @@ -88,7 +88,7 @@ class HsOfficeDebitorEntityUnitTest { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) .debitorNumberSuffix("67") - .partner(HsOfficePartnerEntity.builder().build()) + .partner(HsOfficePartnerRealEntity.builder().build()) .build(); final var result = given.getTaggedDebitorNumber(); @@ -101,7 +101,7 @@ class HsOfficeDebitorEntityUnitTest { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) .debitorNumberSuffix(null) - .partner(HsOfficePartnerEntity.builder() + .partner(HsOfficePartnerRealEntity.builder() .partnerNumber(12345) .build()) .build(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index 948ec958..7989cf74 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.debitor; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealRepository; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealRepository; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelation; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; @@ -22,7 +22,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; import org.springframework.transaction.annotation.Transactional; @@ -48,7 +48,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean HsOfficeDebitorRepository debitorRepo; @Autowired - HsOfficePartnerRepository partnerRepo; + HsOfficePartnerRealRepository partnerRepo; @Autowired HsOfficeContactRealRepository contactRealRepo; @@ -74,7 +74,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean @Autowired RbacGrantsDiagramService mermaidService; - @MockBean + @MockitoBean HttpServletRequest request; @Nested class CreateDebitor { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java index cd6233dc..a0dcb83d 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java @@ -5,7 +5,7 @@ import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import static net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealTestEntity.TEST_REAL_CONTACT; -import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER; +import static net.hostsharing.hsadminng.hs.office.partner.HsOfficeTestRealPartner.TEST_PARTNER; @UtilityClass public class TestHsOfficeDebitor { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java index 88f29868..a2306ba8 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java @@ -5,7 +5,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; import net.hostsharing.hsadminng.HsadminNgApplication; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealRepository; import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import net.hostsharing.hsadminng.config.DisableSecurityConfig; @@ -54,7 +54,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle HsOfficeMembershipRepository membershipRepo; @Autowired - HsOfficePartnerRepository partnerRepo; + HsOfficePartnerRealRepository partnerRepo; @Autowired JpaAttempt jpaAttempt; @@ -430,7 +430,6 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle context.define("superuser-alex@hostsharing.net"); final var givenPartner = partnerRepo.findPartnerByOptionalNameLike(partnerName).get(0); final var newMembership = HsOfficeMembershipEntity.builder() - .uuid(UUID.randomUUID()) .partner(givenPartner) .memberNumberSuffix(TEMP_MEMBER_NUMBER_SUFFIX) .validity(Range.closedInfinite(LocalDate.parse("2022-11-01"))) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java index 58271f57..cd5ac099 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java @@ -2,8 +2,10 @@ package net.hostsharing.hsadminng.hs.office.membership; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionRepository; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRbacEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealRepository; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.api.Nested; @@ -12,7 +14,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; @@ -34,11 +36,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(HsOfficeMembershipController.class) -@Import({StandardMapper.class, DisableSecurityConfig.class}) +@Import({StrictMapper.class, DisableSecurityConfig.class}) @ActiveProfiles("test") public class HsOfficeMembershipControllerRestTest { - private static final HsOfficePartnerEntity PARTNER_12345 = HsOfficePartnerEntity.builder() + private static final HsOfficePartnerRealEntity PARTNER_12345 = HsOfficePartnerRealEntity.builder() .partnerNumber(12345) .build(); public static final HsOfficeMembershipEntity MEMBERSHIP_1234501 = HsOfficeMembershipEntity.builder() @@ -69,16 +71,19 @@ public class HsOfficeMembershipControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; - @MockBean + @MockitoBean HsOfficeCoopAssetsTransactionRepository coopAssetsTransactionRepo; - @MockBean + @MockitoBean + HsOfficePartnerRealRepository partnerRepo; + + @MockitoBean HsOfficeMembershipRepository membershipRepo; - @MockBean + @MockitoBean EntityManagerWrapper em; @Nested @@ -252,7 +257,7 @@ public class HsOfficeMembershipControllerRestTest { // given final var givenPartnerUuid = UUID.randomUUID(); - when(em.find(HsOfficePartnerEntity.class, givenPartnerUuid)).thenReturn(null); + when(em.find(HsOfficePartnerRbacEntity.class, givenPartnerUuid)).thenReturn(null); // when mockMvc.perform(MockMvcRequestBuilders @@ -275,7 +280,7 @@ public class HsOfficeMembershipControllerRestTest { .andExpect(jsonPath("statusPhrase", is("Bad Request"))) .andExpect(jsonPath( "message", - is("ERROR: [400] Unable to find Partner by partner.uuid: " + givenPartnerUuid))); + is("ERROR: [400] partnerUuid " + givenPartnerUuid + " not found"))); } @ParameterizedTest diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java index f6ab56fa..f631e24a 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java @@ -4,7 +4,7 @@ import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipStatusResource; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase; import org.junit.jupiter.api.BeforeEach; @@ -17,7 +17,7 @@ import java.time.LocalDate; import java.util.UUID; import java.util.stream.Stream; -import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER; +import static net.hostsharing.hsadminng.hs.office.partner.HsOfficeTestRealPartner.TEST_PARTNER; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -40,7 +40,7 @@ class HsOfficeMembershipEntityPatcherUnitTest extends PatchUnitTestBase< @Mock private EntityManagerWrapper em; - private StandardMapper mapper = new StandardMapper(em); + private StrictMapper mapper = new StrictMapper(em); @BeforeEach void initMocks() { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java index 6d2b13be..975ca8d0 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.membership; import io.hypersistence.utils.hibernate.type.range.Range; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealEntity; import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator; import org.junit.jupiter.api.Test; @@ -10,7 +10,7 @@ import java.lang.reflect.InvocationTargetException; import java.time.LocalDate; import java.util.Arrays; -import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER; +import static net.hostsharing.hsadminng.hs.office.partner.HsOfficeTestRealPartner.TEST_PARTNER; import static org.assertj.core.api.Assertions.assertThat; class HsOfficeMembershipEntityUnitTest { @@ -57,7 +57,7 @@ class HsOfficeMembershipEntityUnitTest { @Test void getMemberNumberWithoutPartnerNumberButWithSuffix() { - givenMembership.setPartner(HsOfficePartnerEntity.builder().build()); + givenMembership.setPartner(HsOfficePartnerRealEntity.builder().build()); final var result = givenMembership.getMemberNumber(); assertThat(result).isEqualTo(null); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java index fc3599d2..44713c61 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java @@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.membership; import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository; -import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository; +import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRealRepository; import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.grant.RawRbacGrantRepository; import net.hostsharing.hsadminng.rbac.role.RawRbacRoleRepository; @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -37,7 +37,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl HsOfficeMembershipRepository membershipRepo; @Autowired - HsOfficePartnerRepository partnerRepo; + HsOfficePartnerRealRepository partnerRepo; @Autowired HsOfficeDebitorRepository debitorRepo; @@ -54,7 +54,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java index 857e9369..416a29ff 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java @@ -4,7 +4,7 @@ import io.hypersistence.utils.hibernate.type.range.Range; import java.time.LocalDate; -import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER; +import static net.hostsharing.hsadminng.hs.office.partner.HsOfficeTestRealPartner.TEST_PARTNER; public class TestHsMembership { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java index 54a4baf2..8bfc7009 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java @@ -42,7 +42,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu private Integer port; @Autowired - HsOfficePartnerRepository partnerRepo; + HsOfficePartnerRbacRepository partnerRepo; @Autowired HsOfficeRelationRealRepository relationRepo; @@ -541,12 +541,12 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu return partnerRel; }).assertSuccessful().returnedValue(); } - private HsOfficePartnerEntity givenSomeTemporaryPartnerBessler(final Integer partnerNumber) { + private HsOfficePartnerRbacEntity givenSomeTemporaryPartnerBessler(final Integer partnerNumber) { return jpaAttempt.transacted(() -> { context.define("superuser-alex@hostsharing.net"); final var partnerRel = em.merge(givenSomeTemporaryPartnerRel("Erben Bessler", "fourth contact")); - final var newPartner = HsOfficePartnerEntity.builder() + final var newPartner = HsOfficePartnerRbacEntity.builder() .partnerRel(partnerRel) .partnerNumber(partnerNumber) .details(HsOfficePartnerDetailsEntity.builder() @@ -561,7 +561,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu @AfterEach void cleanup() { - cleanupAllNew(HsOfficePartnerEntity.class); + cleanupAllNew(HsOfficePartnerRbacEntity.class); // TODO: should not be necessary anymore, once it's deleted via after delete trigger cleanupAllNew(HsOfficeRelationRealEntity.class); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java index 100d3852..1ed5389b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java @@ -5,7 +5,7 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRbacEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.api.BeforeEach; @@ -14,7 +14,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; @@ -38,7 +38,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(HsOfficePartnerController.class) -@Import({StandardMapper.class, DisableSecurityConfig.class}) +@Import({StrictMapper.class, DisableSecurityConfig.class}) @ActiveProfiles("test") class HsOfficePartnerControllerRestTest { @@ -50,19 +50,19 @@ class HsOfficePartnerControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; - @MockBean - HsOfficePartnerRepository partnerRepo; + @MockitoBean + HsOfficePartnerRbacRepository partnerRepo; - @MockBean + @MockitoBean HsOfficeRelationRealRepository relationRepo; - @MockBean + @MockitoBean EntityManagerWrapper em; - @MockBean + @MockitoBean EntityManagerFactory emf; @Mock @@ -75,7 +75,7 @@ class HsOfficePartnerControllerRestTest { HsOfficeContactRbacEntity contactMock; @Mock - HsOfficePartnerEntity partnerMock; + HsOfficePartnerRbacEntity partnerMock; @BeforeEach void init() { @@ -174,7 +174,7 @@ class HsOfficePartnerControllerRestTest { @Test void respondWithPartner_ifPartnerNumberIsAvailable() throws Exception { // given - when(partnerRepo.findPartnerByPartnerNumber(12345)).thenReturn(Optional.of(HsOfficePartnerEntity.builder() + when(partnerRepo.findPartnerByPartnerNumber(12345)).thenReturn(Optional.of(HsOfficePartnerRbacEntity.builder() .partnerNumber(12345) .build())); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcherUnitTest.java index 102b54e5..b38c41ae 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcherUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatcherUnitTest.java @@ -24,7 +24,7 @@ import static org.mockito.Mockito.lenient; @ExtendWith(MockitoExtension.class) class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase< HsOfficePartnerPatchResource, - HsOfficePartnerEntity + HsOfficePartnerRbacEntity > { private static final UUID INITIAL_PARTNER_UUID = UUID.randomUUID(); @@ -53,8 +53,8 @@ class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase< } @Override - protected HsOfficePartnerEntity newInitialEntity() { - final var entity = HsOfficePartnerEntity.builder() + protected HsOfficePartnerRbacEntity newInitialEntity() { + final var entity = HsOfficePartnerRbacEntity.builder() .uuid(INITIAL_PARTNER_UUID) .partnerNumber(12345) .partnerRel(HsOfficeRelationRealEntity.builder() @@ -72,7 +72,7 @@ class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase< } @Override - protected HsOfficePartnerEntityPatcher createPatcher(final HsOfficePartnerEntity partner) { + protected HsOfficePartnerEntityPatcher createPatcher(final HsOfficePartnerRbacEntity partner) { return new HsOfficePartnerEntityPatcher(em, partner); } @@ -83,7 +83,7 @@ class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase< "partnerRel", HsOfficePartnerPatchResource::setPartnerRelUuid, PATCHED_PARTNER_ROLE_UUID, - HsOfficePartnerEntity::setPartnerRel, + HsOfficePartnerRbacEntity::setPartnerRel, newPartnerRel(PATCHED_PARTNER_ROLE_UUID)) .notNullable() ); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityUnitTest.java index 93ca0315..79c24ec7 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityUnitTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; class HsOfficePartnerEntityUnitTest { - private final HsOfficePartnerEntity givenPartner = HsOfficePartnerEntity.builder() + private final HsOfficePartnerRbacEntity givenPartner = HsOfficePartnerRbacEntity.builder() .partnerNumber(12345) .partnerRel(HsOfficeRelationRealEntity.builder() .anchor(HsOfficePersonRealEntity.builder() @@ -42,7 +42,7 @@ class HsOfficePartnerEntityUnitTest { @Test void definesRbac() { - final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficePartnerEntity.rbac()).toString(); + final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficePartnerRbacEntity.rbac()).toString(); assertThat(rbacFlowchart).isEqualTo(""" %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepositoryIntegrationTest.java similarity index 80% rename from src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepositoryIntegrationTest.java index c8a709a1..2b5dfe1b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRbacRepositoryIntegrationTest.java @@ -6,19 +6,19 @@ import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType; -import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.grant.RawRbacGrantRepository; import net.hostsharing.hsadminng.rbac.role.RawRbacObjectRepository; import net.hostsharing.hsadminng.rbac.role.RawRbacRoleRepository; +import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; @@ -27,20 +27,21 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import static net.hostsharing.hsadminng.mapper.Array.from; import static net.hostsharing.hsadminng.rbac.grant.RawRbacGrantEntity.distinctGrantDisplaysOf; import static net.hostsharing.hsadminng.rbac.role.RawRbacObjectEntity.objectDisplaysOf; import static net.hostsharing.hsadminng.rbac.role.RawRbacRoleEntity.distinctRoleNamesOf; -import static net.hostsharing.hsadminng.mapper.Array.from; import static net.hostsharing.hsadminng.rbac.role.RbacRoleType.ADMIN; +import static net.hostsharing.hsadminng.rbac.role.RbacRoleType.AGENT; import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt; import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest -@Import( { Context.class, JpaAttempt.class }) -class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithCleanup { +@Import({ Context.class, JpaAttempt.class }) +class HsOfficePartnerRbacRepositoryIntegrationTest extends ContextBasedTestWithCleanup { @Autowired - HsOfficePartnerRepository partnerRepo; + HsOfficePartnerRbacRepository partnerRepo; @Autowired HsOfficeRelationRealRepository relationRepo; @@ -66,7 +67,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested @@ -80,18 +81,19 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean final var partnerRel = givenSomeTemporaryHostsharingPartnerRel("Winkler", "first contact"); // when - final var result = attempt(em, () -> { - final var newPartner = HsOfficePartnerEntity.builder() - .partnerNumber(20031) - .partnerRel(partnerRel) - .details(HsOfficePartnerDetailsEntity.builder().build()) - .build(); - return partnerRepo.save(newPartner); - }); + final var result = attempt( + em, () -> { + final var newPartner = HsOfficePartnerRbacEntity.builder() + .partnerNumber(20031) + .partnerRel(partnerRel) + .details(HsOfficePartnerDetailsEntity.builder().build()) + .build(); + return partnerRepo.save(newPartner); + }); // then result.assertSuccessful(); - assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePartnerEntity::getUuid).isNotNull(); + assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePartnerRbacEntity::getUuid).isNotNull(); assertThatPartnerIsPersisted(result.returnedValue()); assertThat(partnerRepo.count()).isEqualTo(count + 1); } @@ -108,26 +110,27 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean .toList(); // when - attempt(em, () -> { - final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0); - final var givenContact = contactrealRepo.findContactByOptionalCaptionLike("fourth contact").get(0); - final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0); + attempt( + em, () -> { + final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0); + final var givenContact = contactrealRepo.findContactByOptionalCaptionLike("fourth contact").get(0); + final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0); - final var newRelation = HsOfficeRelationRealEntity.builder() - .holder(givenPartnerPerson) - .type(HsOfficeRelationType.PARTNER) - .anchor(givenMandantPerson) - .contact(givenContact) - .build(); - relationRepo.save(newRelation); + final var newRelation = HsOfficeRelationRealEntity.builder() + .holder(givenPartnerPerson) + .type(HsOfficeRelationType.PARTNER) + .anchor(givenMandantPerson) + .contact(givenContact) + .build(); + relationRepo.save(newRelation); - final var newPartner = HsOfficePartnerEntity.builder() - .partnerNumber(20032) - .partnerRel(newRelation) - .details(HsOfficePartnerDetailsEntity.builder().build()) - .build(); - return partnerRepo.save(newPartner); - }).assertSuccessful(); + final var newPartner = HsOfficePartnerRbacEntity.builder() + .partnerNumber(20032) + .partnerRel(newRelation) + .details(HsOfficePartnerDetailsEntity.builder().build()) + .build(); + return partnerRepo.save(newPartner); + }).assertSuccessful(); // then assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(from( @@ -179,7 +182,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean null))); } - private void assertThatPartnerIsPersisted(final HsOfficePartnerEntity saved) { + private void assertThatPartnerIsPersisted(final HsOfficePartnerRbacEntity saved) { final var found = partnerRepo.findByUuid(saved.getUuid()); assertThat(found).isNotEmpty().get().extracting(Object::toString).isEqualTo(saved.toString()); } @@ -207,15 +210,32 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean } @Test - public void normalUser_canViewOnlyRelatedPartners() { + public void partnerAgent_canViewOnlyRelatedPartnersWithDetails() { // given: - context("person-FirstGmbH@example.com"); + context( + "person-FirstGmbH@example.com", + "hs_office.relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT"); // when: final var result = partnerRepo.findPartnerByOptionalNameLike(null); // then: - exactlyThesePartnersAreReturned(result, "partner(P-10001: LP First GmbH, first contact)"); + exactlyThesePartnersAreReturned(result, + "partner(P-10001: LP First GmbH, first contact)+(partnerDetails(Hamburg, RegNo123456789))"); + } + + @Test + public void partnerTenant_canViewRelatedPartnersButWithoutDetails() { + // given: + context( + "person-FirstGmbH@example.com", + "hs_office.relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT"); + + // when: + final var result = partnerRepo.findPartnerByOptionalNameLike(null); + + // then: + exactlyThesePartnersAreReturned(result, "partner(P-10001: LP First GmbH, first contact)+null"); } } @@ -223,7 +243,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean class FindByNameLike { @Test - public void globalAdmin_withoutAssumedRole_canViewAllPartners() { + public void globalAdmin_withoutAssumedRole_canViewAllPartnersWithDetails() { // given context("superuser-alex@hostsharing.net"); @@ -231,7 +251,8 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean final var result = partnerRepo.findPartnerByOptionalNameLike("third contact"); // then - exactlyThesePartnersAreReturned(result, "partner(P-10003: IF Third OHG, third contact)"); + exactlyThesePartnersAreReturned(result, + "partner(P-10003: IF Third OHG, third contact)+(partnerDetails(Hamburg, RegNo123456789))"); } } @@ -289,19 +310,20 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean } @Test - public void partnerRelationAgent_canUpdateRelatedPartner() { + public void partnerRelationAgent_canUpdateRelatedPartnerDetails() { // given context("superuser-alex@hostsharing.net"); final var givenPartner = givenSomeTemporaryHostsharingPartner(20037, "Erben Bessler", "ninth"); assertThatPartnerIsVisibleForUserWithRole( givenPartner, - "hs_office.person#ErbenBesslerMelBessler:ADMIN"); + givenPartner.getPartnerRel().roleId(AGENT)); assertThatPartnerActuallyInDatabase(givenPartner); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", - "hs_office.person#ErbenBesslerMelBessler:ADMIN"); + context( + "superuser-alex@hostsharing.net", + givenPartner.getPartnerRel().roleId(AGENT)); givenPartner.getDetails().setBirthName("new birthname"); return partnerRepo.save(givenPartner); }); @@ -310,37 +332,17 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean result.assertSuccessful(); } - @Test - public void partnerRelationTenant_canNotUpdateRelatedPartner() { - // given - context("superuser-alex@hostsharing.net"); - final var givenPartner = givenSomeTemporaryHostsharingPartner(20037, "Erben Bessler", "ninth"); - assertThatPartnerIsVisibleForUserWithRole( - givenPartner, - "hs_office.person#ErbenBesslerMelBessler:ADMIN"); - assertThatPartnerActuallyInDatabase(givenPartner); - - // when - final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", - "hs_office.relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:TENANT"); - givenPartner.getDetails().setBirthName("new birthname"); - return partnerRepo.save(givenPartner); - }); - - // then - result.assertExceptionWithRootCauseMessage(JpaSystemException.class, - "ERROR: [403] insert into hs_office.partner_details ", - " not allowed for current subjects {hs_office.relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:TENANT}"); - } - - private void assertThatPartnerActuallyInDatabase(final HsOfficePartnerEntity saved) { + private void assertThatPartnerActuallyInDatabase(final HsOfficePartnerRbacEntity saved) { final var found = partnerRepo.findByUuid(saved.getUuid()); - assertThat(found).isNotEmpty().get().isNotSameAs(saved).extracting(HsOfficePartnerEntity::toString).isEqualTo(saved.toString()); + assertThat(found).isNotEmpty() + .get() + .isNotSameAs(saved) + .extracting(HsOfficePartnerRbacEntity::toString) + .isEqualTo(saved.toString()); } private void assertThatPartnerIsVisibleForUserWithRole( - final HsOfficePartnerEntity entity, + final HsOfficePartnerRbacEntity entity, final String assumedRoles) { jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", assumedRoles); @@ -349,7 +351,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean } private void assertThatPartnerIsNotVisibleForUserWithRole( - final HsOfficePartnerEntity entity, + final HsOfficePartnerRbacEntity entity, final String assumedRoles) { jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", assumedRoles); @@ -437,7 +439,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean select currentTask, targetTable, targetOp, targetdelta->>'partnernumber' from base.tx_journal_v where targettable = 'hs_office.partner'; - """); + """); // when @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); @@ -451,19 +453,22 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean "[creating partner test-data , hs_office.partner, INSERT, 10010]"); } - private HsOfficePartnerEntity givenSomeTemporaryHostsharingPartner( + private HsOfficePartnerRbacEntity givenSomeTemporaryHostsharingPartner( final Integer partnerNumber, final String person, final String contact) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); final var partnerRel = givenSomeTemporaryHostsharingPartnerRel(person, contact); - final var newPartner = HsOfficePartnerEntity.builder() + final var newPartner = HsOfficePartnerRbacEntity.builder() .partnerNumber(partnerNumber) .partnerRel(partnerRel) .details(HsOfficePartnerDetailsEntity.builder().build()) .build(); - return partnerRepo.save(newPartner); + final var savedPartner = partnerRepo.save(newPartner); + em.flush(); + final var partner = em.find(savedPartner.getClass(), savedPartner.getUuid()); + return savedPartner; }).assertSuccessful().returnedValue(); } @@ -482,21 +487,23 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean return partnerRel; } - void exactlyThesePartnersAreReturned(final List actualResult, final String... partnerNames) { + void exactlyThesePartnersAreReturned(final List actualResult, final String... partnerNames) { assertThat(actualResult) - .extracting(partnerEntity -> partnerEntity.toString()) + .extracting(partner -> + partner.toString() + "+" + + (partner.getDetails() != null ? ("(" + partner.getDetails() + ")") : "null")) .containsExactlyInAnyOrder(partnerNames); } - void allThesePartnersAreReturned(final List actualResult, final String... partnerNames) { + void allThesePartnersAreReturned(final List actualResult, final String... partnerNames) { assertThat(actualResult) - .extracting(partnerEntity -> partnerEntity.toString()) + .extracting(HsOfficePartnerRbacEntity::toString) .contains(partnerNames); } @AfterEach void cleanup() { - cleanupAllNew(HsOfficePartnerEntity.class); + cleanupAllNew(HsOfficePartnerRbacEntity.class); } private String[] distinct(final String[] strings) { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/TestHsOfficePartner.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficeTestRealPartner.java similarity index 82% rename from src/test/java/net/hostsharing/hsadminng/hs/office/partner/TestHsOfficePartner.java rename to src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficeTestRealPartner.java index 02358e28..630a1782 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/TestHsOfficePartner.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficeTestRealPartner.java @@ -7,12 +7,12 @@ import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType; import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL_PERSON; -public class TestHsOfficePartner { +public class HsOfficeTestRealPartner { - public static final HsOfficePartnerEntity TEST_PARTNER = hsOfficePartnerWithLegalPerson("Test Ltd."); + public static final HsOfficePartnerRealEntity TEST_PARTNER = hsOfficePartnerWithLegalPerson("Test Ltd."); - static public HsOfficePartnerEntity hsOfficePartnerWithLegalPerson(final String tradeName) { - return HsOfficePartnerEntity.builder() + static public HsOfficePartnerRealEntity hsOfficePartnerWithLegalPerson(final String tradeName) { + return HsOfficePartnerRealEntity.builder() .partnerNumber(10001) .partnerRel( HsOfficeRelationRealEntity.builder() diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonControllerAcceptanceTest.java index b0cae150..a2c21dac 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonControllerAcceptanceTest.java @@ -331,7 +331,6 @@ class HsOfficePersonControllerAcceptanceTest extends ContextBasedTestWithCleanup return jpaAttempt.transacted(() -> { context.define(creatingUser); final var newPerson = HsOfficePersonRealEntity.builder() - .uuid(UUID.randomUUID()) .personType(HsOfficePersonType.LEGAL_PERSON) .tradeName("Temp " + Context.getCallerMethodNameFromStackFrame(2)) .familyName(RandomStringUtils.randomAlphabetic(10) + "@example.org") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacRepositoryIntegrationTest.java index 481847c2..aff5561b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacRepositoryIntegrationTest.java @@ -11,7 +11,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -46,7 +46,7 @@ class HsOfficePersonRbacRepositoryIntegrationTest extends ContextBasedTestWithCl @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepositoryIntegrationTest.java index 2fc268a6..0d89050e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepositoryIntegrationTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -44,7 +44,7 @@ class HsOfficePersonRealRepositoryIntegrationTest extends ContextBasedTestWithCl @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Autowired private HsOfficePersonRealRepository hsOfficePersonRealRepository; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRealRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRealRelationRepositoryIntegrationTest.java index 05c2d971..4c8f7b75 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRealRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRealRelationRepositoryIntegrationTest.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; @@ -35,7 +35,7 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith @PersistenceContext EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index eb92aad9..df3bcf23 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -58,7 +58,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java index eabde5a7..b8876423 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java @@ -180,10 +180,9 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl void globalAdmin_canNotPostNewSepaMandateWhenDebitorUuidIsMissing() { context.define("superuser-alex@hostsharing.net"); - final var givenDebitor = debitorRepo.findDebitorsByOptionalNameLike("Third").get(0); final var givenBankAccount = bankAccountRepo.findByIbanOrderByIbanAsc("DE02200505501015871393").get(0); - final var location = RestAssured // @formatter:off + RestAssured // @formatter:off .given() .header("current-subject", "superuser-alex@hostsharing.net") .contentType(ContentType.JSON) @@ -227,12 +226,12 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl .post("http://localhost/api/hs/office/sepamandates") .then().log().all().assertThat() .statusCode(400) - .body("message", is("ERROR: [400] Unable to find BankAccount with uuid 00000000-0000-0000-0000-000000000000")); + .body("message", is("ERROR: [400] bankAccount.uuid='00000000-0000-0000-0000-000000000000' not found or not accessible")); // @formatter:on } @Test - void globalAdmin_canNotPostNewSepaMandate_ifPersonDoesNotExist() { + void globalAdmin_canNotPostNewSepaMandate_ifDebitorDoesNotExist() { context.define("superuser-alex@hostsharing.net"); final var givenDebitorUuid = UUID.fromString("00000000-0000-0000-0000-000000000000"); @@ -257,7 +256,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl .post("http://localhost/api/hs/office/sepamandates") .then().log().all().assertThat() .statusCode(400) - .body("message", is("ERROR: [400] Unable to find Debitor with uuid 00000000-0000-0000-0000-000000000000")); + .body("message", is("ERROR: [400] debitor.uuid='00000000-0000-0000-0000-000000000000' not found or not accessible")); // @formatter:on } } @@ -529,7 +528,6 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl .orElse(givenDebitor.getPartner().getPartnerRel().getHolder().getFamilyName()); final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0); final var newSepaMandate = HsOfficeSepaMandateEntity.builder() - .uuid(UUID.randomUUID()) .debitor(givenDebitor) .bankAccount(givenBankAccount) .reference("temp ref CAT Z") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java index 8e7512c3..3debf9f5 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -55,7 +55,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC @PersistenceContext EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextIntegrationTests.java b/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextIntegrationTests.java index 25d04156..7f59d4e3 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextIntegrationTests.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextIntegrationTests.java @@ -2,13 +2,13 @@ package net.hostsharing.hsadminng.rbac.context; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.mapper.Array; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.annotation.DirtiesContext; import org.springframework.transaction.annotation.Transactional; @@ -20,14 +20,14 @@ import jakarta.servlet.http.HttpServletRequest; import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest -@ComponentScan(basePackageClasses = { Context.class, JpaAttempt.class, EntityManagerWrapper.class, StandardMapper.class }) +@ComponentScan(basePackageClasses = { Context.class, JpaAttempt.class, EntityManagerWrapper.class, StrictMapper.class }) @DirtiesContext class ContextIntegrationTests { @Autowired private Context context; - @MockBean + @MockitoBean @SuppressWarnings("unused") // the bean must be present, even though it's not used directly private HttpServletRequest request; diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantRepositoryIntegrationTest.java index 14075fe8..41c2e6fc 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantRepositoryIntegrationTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; import org.springframework.transaction.annotation.Propagation; @@ -32,7 +32,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { @Autowired Context context; - @MockBean + @MockitoBean HttpServletRequest request; @Autowired diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramServiceIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramServiceIntegrationTest.java index b234e07b..085854f1 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramServiceIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/grant/RbacGrantsDiagramServiceIntegrationTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.servlet.http.HttpServletRequest; @@ -28,7 +28,7 @@ class RbacGrantsDiagramServiceIntegrationTest extends ContextBasedTestWithCleanu @Autowired RbacGrantsDiagramService grantsMermaidService; - @MockBean + @MockitoBean HttpServletRequest request; @Autowired diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleControllerRestTest.java index d79a5578..a10b1eee 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleControllerRestTest.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.rbac.role; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.api.BeforeEach; @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; @@ -31,7 +31,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(RbacRoleController.class) -@Import({StandardMapper.class, DisableSecurityConfig.class}) +@Import({StrictMapper.class, DisableSecurityConfig.class}) @ActiveProfiles("test") @RunWith(SpringRunner.class) class RbacRoleControllerRestTest { @@ -39,16 +39,16 @@ class RbacRoleControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; - @MockBean + @MockitoBean RbacRoleRepository rbacRoleRepository; - @MockBean + @MockitoBean EntityManagerWrapper em; - @MockBean + @MockitoBean EntityManagerFactory emf; @BeforeEach diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleRepositoryIntegrationTest.java index 98495e81..292305e5 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/role/RbacRoleRepositoryIntegrationTest.java @@ -7,7 +7,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; @@ -31,7 +31,7 @@ class RbacRoleRepositoryIntegrationTest { @Autowired EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectControllerRestTest.java index 917cd7ff..7d929042 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectControllerRestTest.java @@ -1,14 +1,14 @@ package net.hostsharing.hsadminng.rbac.subject; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import net.hostsharing.hsadminng.config.DisableSecurityConfig; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; @@ -26,7 +26,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(RbacSubjectController.class) -@Import({StandardMapper.class, DisableSecurityConfig.class}) +@Import({StrictMapper.class, DisableSecurityConfig.class}) @ActiveProfiles("test") @RunWith(SpringRunner.class) class RbacSubjectControllerRestTest { @@ -34,13 +34,13 @@ class RbacSubjectControllerRestTest { @Autowired MockMvc mockMvc; - @MockBean + @MockitoBean Context contextMock; - @MockBean + @MockitoBean RbacSubjectRepository rbacSubjectRepository; - @MockBean + @MockitoBean EntityManagerWrapper em; diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectRepositoryIntegrationTest.java index ea72ce14..00654d6e 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/subject/RbacSubjectRepositoryIntegrationTest.java @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.jpa.JpaSystemException; import org.springframework.transaction.annotation.Propagation; @@ -37,7 +37,7 @@ class RbacSubjectRepositoryIntegrationTest extends ContextBasedTest { @PersistenceContext EntityManager em; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/test/MapperUnitTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/test/MapperUnitTest.java index 5d64903f..8c93b0fb 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/test/MapperUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/test/MapperUnitTest.java @@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.rbac.test; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayAs; -import net.hostsharing.hsadminng.mapper.StandardMapper; +import net.hostsharing.hsadminng.mapper.StrictMapper; import net.hostsharing.hsadminng.persistence.EntityManagerWrapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,7 +27,7 @@ class MapperUnitTest { EntityManagerWrapper em; @InjectMocks - StandardMapper mapper; + StrictMapper mapper; final UUID GIVEN_UUID = UUID.randomUUID(); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerRepositoryIntegrationTest.java index 245278da..c0a0dd06 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/test/cust/TestCustomerRepositoryIntegrationTest.java @@ -7,13 +7,12 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import jakarta.persistence.PersistenceException; import jakarta.servlet.http.HttpServletRequest; import java.util.List; -import java.util.UUID; import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt; import static org.assertj.core.api.Assertions.assertThat; @@ -25,7 +24,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { @Autowired TestCustomerRepository testCustomerRepository; - @MockBean + @MockitoBean HttpServletRequest request; @Nested @@ -40,7 +39,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { // when final var result = attempt(em, () -> { final var newCustomer = new TestCustomerEntity( - UUID.randomUUID(), 0, "www", 90001, "customer-admin@www.example.com"); + null, 0, "www", 90001, "customer-admin@www.example.com"); return testCustomerRepository.save(newCustomer); }); @@ -59,7 +58,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { // when final var result = attempt(em, () -> { final var newCustomer = new TestCustomerEntity( - UUID.randomUUID(), 0, "www", 90001, "customer-admin@www.example.com"); + null, 0, "www", 90001, "customer-admin@www.example.com"); return testCustomerRepository.save(newCustomer); }); @@ -78,7 +77,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { // when final var result = attempt(em, () -> { final var newCustomer = new TestCustomerEntity( - UUID.randomUUID(), 0, "www", 90001, "customer-admin@www.example.com"); + null, 0, "www", 90001, "customer-admin@www.example.com"); return testCustomerRepository.save(newCustomer); }); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageRepositoryIntegrationTest.java index 5b45f1b5..f4fa58dc 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/test/pac/TestPackageRepositoryIntegrationTest.java @@ -7,7 +7,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.orm.ObjectOptimisticLockingFailureException; @@ -31,7 +31,7 @@ class TestPackageRepositoryIntegrationTest extends ContextBasedTest { @Autowired JpaAttempt jpaAttempt; - @MockBean + @MockitoBean HttpServletRequest request; @Nested diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 954bdd63..344828e7 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -6,7 +6,7 @@ management: endpoints: web: exposure: - include: info, health, metrics, metric-links + include: info, health, metrics, metric-links, mappings, openapi, swaggerui spring: sql: