real rbac-entities in booking+hosting #89
@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import net.hostsharing.hsadminng.rbac.rbacobject.BaseEntity;
|
||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||
@ -24,6 +25,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
public class TestCustomerEntity implements BaseEntity<TestCustomerEntity> {
|
||||
|
||||
@Id
|
||||
|
@ -1,13 +1,13 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.EntityManagerMock;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -41,9 +41,6 @@ class HsMariaDbDatabaseHostingAssetValidatorUnitTest {
|
||||
)))
|
||||
.build();
|
||||
|
||||
@Mock
|
||||
private EntityManager em;
|
||||
|
||||
private static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder givenValidMariaDbDatabaseBuilder() {
|
||||
return HsHostingAssetRbacEntity.builder()
|
||||
.type(MARIADB_DATABASE)
|
||||
@ -74,12 +71,13 @@ class HsMariaDbDatabaseHostingAssetValidatorUnitTest {
|
||||
// given
|
||||
final var givenMariaDbUserHostingAsset = givenValidMariaDbDatabaseBuilder().build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(givenMariaDbUserHostingAsset.getType());
|
||||
final var em = EntityManagerMock.createEntityManagerMockWithAssetQueryFake(null);
|
||||
|
||||
// when
|
||||
final var result = Stream.concat(
|
||||
final var result = HsEntityValidator.doWithEntityManager(em, () -> Stream.concat(
|
||||
validator.validateEntity(givenMariaDbUserHostingAsset).stream(),
|
||||
validator.validateContext(givenMariaDbUserHostingAsset).stream()
|
||||
).toList();
|
||||
).toList());
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
|
@ -1,7 +1,9 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.EntityManagerMock;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
@ -79,12 +81,13 @@ class HsMariaDbUserHostingAssetValidatorUnitTest {
|
||||
// given
|
||||
final var givenMariaDbUserHostingAsset = givenValidMariaDbUserBuilder().build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(givenMariaDbUserHostingAsset.getType());
|
||||
final var em = EntityManagerMock.createEntityManagerMockWithAssetQueryFake(null);
|
||||
|
||||
// when
|
||||
final var result = Stream.concat(
|
||||
final var result = HsEntityValidator.doWithEntityManager(em, () -> Stream.concat(
|
||||
validator.validateEntity(givenMariaDbUserHostingAsset).stream(),
|
||||
validator.validateContext(givenMariaDbUserHostingAsset).stream()
|
||||
).toList();
|
||||
).toList());
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
|
@ -2,8 +2,10 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.EntityManagerMock;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@ -71,12 +73,13 @@ class HsPostgreSqlDatabaseHostingAssetValidatorUnitTest {
|
||||
// given
|
||||
final var givenPgSqlUserHostingAsset = givenValidPgSqlDatabaseBuilder().build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(givenPgSqlUserHostingAsset.getType());
|
||||
final var em = EntityManagerMock.createEntityManagerMockWithAssetQueryFake(null);
|
||||
|
||||
// when
|
||||
final var result = Stream.concat(
|
||||
final var result = HsEntityValidator.doWithEntityManager(em, () -> Stream.concat(
|
||||
validator.validateEntity(givenPgSqlUserHostingAsset).stream(),
|
||||
validator.validateContext(givenPgSqlUserHostingAsset).stream()
|
||||
).toList();
|
||||
).toList());
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
|
@ -1,8 +1,10 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
|
||||
|
||||
import net.hostsharing.hsadminng.hash.HashGenerator;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.EntityManagerMock;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
@ -77,12 +79,13 @@ class HsPostgreSqlUserHostingAssetValidatorUnitTest {
|
||||
// given
|
||||
final var givenMariaDbUserHostingAsset = givenValidMariaDbUserBuilder().build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(givenMariaDbUserHostingAsset.getType());
|
||||
final var em = EntityManagerMock.createEntityManagerMockWithAssetQueryFake(null);
|
||||
|
||||
// when
|
||||
final var result = Stream.concat(
|
||||
final var result = HsEntityValidator.doWithEntityManager(em, () -> Stream.concat(
|
||||
validator.validateEntity(givenMariaDbUserHostingAsset).stream(),
|
||||
validator.validateContext(givenMariaDbUserHostingAsset).stream()
|
||||
).toList();
|
||||
).toList());
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
|
@ -1,9 +1,11 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
|
||||
|
||||
import net.hostsharing.hsadminng.hash.HashGenerator;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.EntityManagerMock;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@ -96,12 +98,13 @@ class HsUnixUserHostingAssetValidatorUnitTest {
|
||||
// given
|
||||
final var unixUserHostingAsset = GIVEN_VALID_UNIX_USER_HOSTING_ASSET;
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
||||
final var em = EntityManagerMock.createEntityManagerMockWithAssetQueryFake(null);
|
||||
|
||||
// when
|
||||
final var result = Stream.concat(
|
||||
final var result = HsEntityValidator.doWithEntityManager(em, () -> Stream.concat(
|
||||
validator.validateEntity(unixUserHostingAsset).stream(),
|
||||
validator.validateContext(unixUserHostingAsset).stream()
|
||||
).toList();
|
||||
).toList());
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
|
@ -140,7 +140,8 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
||||
});
|
||||
|
||||
// then
|
||||
result.assertExceptionWithRootCauseMessage(org.hibernate.exception.ConstraintViolationException.class);
|
||||
result.assertExceptionWithRootCauseMessage(org.hibernate.exception.ConstraintViolationException.class,
|
||||
"ERROR: new row for relation \"hs_office_debitor\" violates check constraint \"check_default_prefix\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -161,7 +161,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
||||
.extract().header("Location"); // @formatter:on
|
||||
|
||||
// finally, the new relation can be accessed under the generated UUID
|
||||
final var newUserUuid = toCleanup(HsOfficeRelation.class, UUID.fromString(
|
||||
final var newUserUuid = toCleanup(HsOfficeRelationRealEntity.class, UUID.fromString(
|
||||
location.substring(location.lastIndexOf('/') + 1)));
|
||||
assertThat(newUserUuid).isNotNull();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository;
|
||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity;
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
|
||||
import org.apache.commons.collections4.SetUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -56,9 +57,10 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
private static Long latestIntialTestDataSerialId;
|
||||
private static boolean countersInitialized = false;
|
||||
private static boolean initialTestDataValidated = false;
|
||||
private static Long initialRbacObjectCount = null;
|
||||
private static Long initialRbacRoleCount = null;
|
||||
private static Long initialRbacGrantCount = null;
|
||||
static private Long previousRbacObjectCount;
|
||||
private Long initialRbacObjectCount = null;
|
||||
private Long initialRbacRoleCount = null;
|
||||
private Long initialRbacGrantCount = null;
|
||||
private Set<String> initialRbacObjects;
|
||||
private Set<String> initialRbacRoles;
|
||||
private Set<String> initialRbacGrants;
|
||||
@ -120,6 +122,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
@BeforeEach
|
||||
//@Transactional -- TODO: check why this does not work but jpaAttempt.transacted does work
|
||||
void retrieveInitialTestData(final TestInfo testInfo) {
|
||||
this.testInfo = testInfo;
|
||||
out.println(ContextBasedTestWithCleanup.class.getSimpleName() + ".retrieveInitialTestData");
|
||||
|
||||
if (latestIntialTestDataSerialId == null ) {
|
||||
@ -127,7 +130,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
}
|
||||
|
||||
if (initialRbacObjects != null){
|
||||
assertNoNewRbacObjectsRolesAndGrantsLeaked();
|
||||
assertNoNewRbacObjectsRolesAndGrantsLeaked("before");
|
||||
}
|
||||
|
||||
initialTestDataValidated = false;
|
||||
@ -157,7 +160,10 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
assertThat(countersInitialized).as("error while retrieving initial test data").isTrue();
|
||||
assertThat(initialTestDataValidated).as("check previous test for leaked test data").isTrue();
|
||||
|
||||
out.println("TOTAL OBJECT COUNT (before): " + initialRbacObjectCount);
|
||||
out.println(testInfo.getDisplayName() + ": TOTAL OBJECT COUNT (initial): " + previousRbacObjectCount + " -> " + initialRbacObjectCount);
|
||||
if (previousRbacObjectCount != null) {
|
||||
assertThat(initialRbacObjectCount).as("TOTAL OBJECT COUNT changed from " + previousRbacObjectCount + " to " + initialRbacObjectCount).isEqualTo(previousRbacObjectCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Long assumeSameInitialCount(final Long countBefore, final long currentCount, final String name) {
|
||||
@ -167,23 +173,15 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
return currentCount;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void keepTestInfo(final TestInfo testInfo) {
|
||||
this.testInfo = testInfo;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanupAndCheckCleanup(final TestInfo testInfo) {
|
||||
// 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();
|
||||
repeatUntilTrue(3, this::deleteLeakedRbacObjects);
|
||||
this.testInfo = testInfo;
|
||||
|
||||
long rbacObjectCount = assertNoNewRbacObjectsRolesAndGrantsLeaked();
|
||||
out.println("TOTAL OBJECT COUNT (after): " + rbacObjectCount);
|
||||
}
|
||||
out.println(ContextBasedTestWithCleanup.class.getSimpleName() + ".cleanupAndCheckCleanup");
|
||||
cleanupTemporaryTestData();
|
||||
repeatUntilTrue(3, this::deleteLeakedRbacObjects);
|
||||
|
||||
assertNoNewRbacObjectsRolesAndGrantsLeaked("after");
|
||||
}
|
||||
|
||||
private void cleanupTemporaryTestData() {
|
||||
@ -208,8 +206,8 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
}
|
||||
}
|
||||
|
||||
private long assertNoNewRbacObjectsRolesAndGrantsLeaked() {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
private void assertNoNewRbacObjectsRolesAndGrantsLeaked(final String event) {
|
||||
long rbacObjectCount = jpaAttempt.transacted(() -> {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
assertEqual(initialRbacObjects, allRbacObjects());
|
||||
if (DETAILED_BUT_SLOW_CHECK) {
|
||||
@ -219,21 +217,27 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
|
||||
// The detailed check works with sets, thus it cannot determine duplicates.
|
||||
// Therefore, we always compare the counts as well.
|
||||
long rbacObjectCount = 0;
|
||||
assertThat(rbacObjectCount = rbacObjectRepo.count()).as("not all business objects got cleaned up (by current test)")
|
||||
long count = rbacObjectRepo.count();
|
||||
out.println(testInfo.getDisplayName() + ": TOTAL OBJECT COUNT (" + event+ "): " + previousRbacObjectCount+ " -> " + count);
|
||||
assertThat(count).as("not all business objects got cleaned up (by current test)")
|
||||
.isEqualTo(initialRbacObjectCount);
|
||||
assertThat(rbacRoleRepo.count()).as("not all rbac roles got cleaned up (by current test)")
|
||||
.isEqualTo(initialRbacRoleCount);
|
||||
assertThat(rbacGrantRepo.count()).as("not all rbac grants got cleaned up (by current test)")
|
||||
.isEqualTo(initialRbacGrantCount);
|
||||
return rbacObjectCount;
|
||||
return count;
|
||||
}).assertSuccessful().returnedValue();
|
||||
|
||||
if (previousRbacObjectCount != null) {
|
||||
assertThat(rbacObjectCount).as("TOTAL OBJECT COUNT changed from " + previousRbacObjectCount + " to " + rbacObjectCount).isEqualTo(previousRbacObjectCount);
|
||||
}
|
||||
previousRbacObjectCount = rbacObjectCount;
|
||||
}
|
||||
|
||||
private boolean deleteLeakedRbacObjects() {
|
||||
final var deletionSuccessful = new AtomicBoolean(true);
|
||||
rbacObjectRepo.findAll().stream()
|
||||
.filter(o -> o.serialId > latestIntialTestDataSerialId)
|
||||
jpaAttempt.transacted(() -> rbacObjectRepo.findAll()).assertSuccessful().returnedValue().stream()
|
||||
.filter(o -> latestIntialTestDataSerialId != null && o.serialId > latestIntialTestDataSerialId)
|
||||
.sorted(comparing(o -> o.serialId))
|
||||
.forEach(o -> {
|
||||
final var exception = jpaAttempt.transacted(() -> {
|
||||
@ -257,7 +261,8 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
|
||||
private void assertEqual(final Set<String> before, final Set<String> after) {
|
||||
assertThat(before).isNotNull();
|
||||
assertThat(after).isNotNull();
|
||||
assertThat(difference(before, after)).as("missing entities (deleted initial test data)").isEmpty();
|
||||
final SetUtils.SetView<String> difference = difference(before, after);
|
||||
assertThat(difference).as("missing entities (deleted initial test data)").isEmpty();
|
||||
assertThat(difference(after, before)).as("spurious entities (test data not cleaned up by this test)").isEmpty();
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,8 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// then
|
||||
result.assertExceptionWithRootCauseMessage(
|
||||
PersistenceException.class,
|
||||
"ERROR: [403] insert into test_customer not allowed for current subjects {test_customer#xxx:ADMIN}");
|
||||
"ERROR: [403] insert into test_customer ",
|
||||
"not allowed for current subjects {test_customer#xxx:ADMIN}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -84,7 +85,8 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// then
|
||||
result.assertExceptionWithRootCauseMessage(
|
||||
PersistenceException.class,
|
||||
"ERROR: [403] insert into test_customer not allowed for current subjects {customer-admin@xxx.example.com}");
|
||||
"ERROR: [403] insert into test_customer ",
|
||||
" not allowed for current subjects {customer-admin@xxx.example.com}");
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user