diff --git a/src/main/java/net/hostsharing/hsadminng/errors/MultiValidationException.java b/src/main/java/net/hostsharing/hsadminng/errors/MultiValidationException.java index 9a6d459d..a6ba69e8 100644 --- a/src/main/java/net/hostsharing/hsadminng/errors/MultiValidationException.java +++ b/src/main/java/net/hostsharing/hsadminng/errors/MultiValidationException.java @@ -8,7 +8,11 @@ import static java.lang.String.join; public class MultiValidationException extends ValidationException { private MultiValidationException(final List violations) { - super("[\n" + join(",\n", violations) + "\n]"); + super( + violations.size() > 1 + ? "[\n" + join(",\n", violations) + "\n]" + : "[" + join(",\n", violations) + "]" + ); } public static void throwInvalid(final List violations) { 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 76003671..d3578833 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 @@ -1,5 +1,6 @@ package net.hostsharing.hsadminng.hs.hosting.asset; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetsApi; import net.hostsharing.hsadminng.context.Context; @@ -34,6 +35,9 @@ public class HsHostingAssetController implements HsHostingAssetsApi { @Autowired private HsHostingAssetRepository assetRepo; + @Autowired + private HsBookingItemRepository bookingItemRepo; + @Override @Transactional(readOnly = true) public ResponseEntity> listAssets( @@ -124,6 +128,11 @@ public class HsHostingAssetController implements HsHostingAssetsApi { final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { entity.putConfig(KeyValueMap.from(resource.getConfig())); + if (resource.getBookingItemUuid() != null) { + entity.setBookingItem(bookingItemRepo.findByUuid(resource.getBookingItemUuid()) + .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] bookingItemUuid %s not found".formatted( + resource.getBookingItemUuid())))); + } if (resource.getParentAssetUuid() != null) { entity.setParentAsset(assetRepo.findByUuid(resource.getParentAssetUuid()) .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] parentAssetUuid %s not found".formatted( diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java index ed36c540..fa15537a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java @@ -27,6 +27,7 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import jakarta.persistence.Transient; import jakarta.persistence.Version; @@ -78,7 +79,7 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject { @Version private int version; - @ManyToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "bookingitemuuid") private HsBookingItemEntity bookingItem; 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 0da54b89..20122736 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 @@ -332,9 +332,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .body("", lenientlyEquals(""" { "statusPhrase": "Bad Request", - "message": "[ - <<<'D-1000111:D-1000111 default project:separate ManagedWebspace.resources.Multi=1 allows at maximum 25 unix users, but 26 found - <<<]" + "message": "['D-1000111:D-1000111 default project:separate ManagedWebspace.resources.Multi=1 allows at maximum 25 unix users, but 26 found]" } """.replaceAll(" +<<<", ""))); // @formatter:on } 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 856356cf..dc1b3f61 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 @@ -109,9 +109,9 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean assertThat(debitorRepo.count()).isEqualTo(count + 1); } + @Transactional @ParameterizedTest @ValueSource(strings = {"", "a", "ab", "a12", "123", "12a"}) - @Transactional public void canNotCreateNewDebitorWithInvalidDefaultPrefix(final String givenPrefix) { // given context("superuser-alex@hostsharing.net"); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java index 6c9ac849..c2de3959 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java @@ -14,6 +14,7 @@ import org.junit.jupiter.api.TestInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; +import org.springframework.transaction.PlatformTransactionManager; import jakarta.persistence.*; import java.util.*; @@ -28,9 +29,13 @@ import static org.assertj.core.api.Assertions.assertThat; public abstract class ContextBasedTestWithCleanup extends ContextBasedTest { private static final boolean DETAILED_BUT_SLOW_CHECK = true; + @PersistenceContext protected EntityManager em; + @Autowired + private PlatformTransactionManager tm; + @Autowired RbacGrantRepository rbacGrantRepo; @@ -166,12 +171,16 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest { @AfterEach void cleanupAndCheckCleanup(final TestInfo testInfo) { - out.println(ContextBasedTestWithCleanup.class.getSimpleName() + ".cleanupAndCheckCleanup"); - cleanupTemporaryTestData(); - deleteLeakedRbacObjects(); - long rbacObjectCount = assertNoNewRbacObjectsRolesAndGrantsLeaked(); + // If the whole test method has its own transaction, cleanup makes no sense. + // If that transaction even failed, cleaunup would cause an exception. + if (!tm.getTransaction(null).isRollbackOnly()) { + out.println(ContextBasedTestWithCleanup.class.getSimpleName() + ".cleanupAndCheckCleanup"); + cleanupTemporaryTestData(); + deleteLeakedRbacObjects(); - out.println("TOTAL OBJECT COUNT (after): " + rbacObjectCount); + long rbacObjectCount = assertNoNewRbacObjectsRolesAndGrantsLeaked(); + out.println("TOTAL OBJECT COUNT (after): " + rbacObjectCount); + } } private void cleanupTemporaryTestData() {