diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepository.java index 5041b702..668661ad 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepository.java @@ -14,7 +14,7 @@ public interface HsOfficePersonRealRepository extends Repository findByUuid(UUID personUuid); @Query(""" - SELECT p FROM HsOfficePersonRbacEntity p + SELECT p FROM HsOfficePersonRealEntity p WHERE :name is null OR p.tradeName like concat(cast(:name as text), '%') OR p.givenName like concat(cast(:name as text), '%') @@ -26,9 +26,6 @@ public interface HsOfficePersonRealRepository extends Repository toCleanup(personRepo.save( - hsOfficePerson("a new person")))); + final var result = attempt(em, () -> toCleanup(personRbacRepo.save( + hsOfficePersonRbacEntity("a new person")))); // then result.assertSuccessful(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePersonRbacEntity::getUuid).isNotNull(); assertThatPersonIsPersisted(result.returnedValue()); - assertThat(personRepo.count()).isEqualTo(count + 1); + assertThat(personRbacRepo.count()).isEqualTo(count + 1); } @Test public void arbitraryUser_canCreateNewPerson() { // given context("selfregistered-user-drew@hostsharing.org"); - final var count = personRepo.count(); + final var count = personRbacRepo.count(); // when - final var result = attempt(em, () -> toCleanup(personRepo.save( - hsOfficePerson("another new person")))); + final var result = attempt(em, () -> toCleanup(personRbacRepo.save( + hsOfficePersonRbacEntity("another new person")))); // then result.assertSuccessful(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePersonRbacEntity::getUuid).isNotNull(); assertThatPersonIsPersisted(result.returnedValue()); - assertThat(personRepo.count()).isEqualTo(count + 1); + assertThat(personRbacRepo.count()).isEqualTo(count + 1); } @Test @@ -95,7 +95,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // when attempt(em, () -> toCleanup( - personRepo.save(hsOfficePerson("another new person")) + personRbacRepo.save(hsOfficePersonRbacEntity("another new person")) )).assumeSuccessful(); // then @@ -123,7 +123,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu } private void assertThatPersonIsPersisted(final HsOfficePersonRbacEntity saved) { - final var found = personRepo.findByUuid(saved.getUuid()); + final var found = personRbacRepo.findByUuid(saved.getUuid()); assertThat(found).isNotEmpty().get().extracting(Object::toString).isEqualTo(saved.toString()); } } @@ -137,7 +137,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu context("superuser-alex@hostsharing.net"); // when - final var result = personRepo.findPersonByOptionalNameLike(null); + final var result = personRbacRepo.findPersonByOptionalNameLike(null); // then allThesePersonsAreReturned( @@ -155,7 +155,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // when: context("pac-admin-zzz00@zzz.example.com"); - final var result = personRepo.findPersonByOptionalNameLike(null); + final var result = personRbacRepo.findPersonByOptionalNameLike(null); // then: exactlyThesePersonsAreReturned(result, givenPerson.getTradeName()); @@ -171,7 +171,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu context("superuser-alex@hostsharing.net", null); // when - final var result = personRepo.findPersonByOptionalNameLike("Second"); + final var result = personRbacRepo.findPersonByOptionalNameLike("Second"); // then exactlyThesePersonsAreReturned(result, "Second e.K."); @@ -184,7 +184,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // when: context("selfregistered-user-drew@hostsharing.org"); - final var result = personRepo.findPersonByOptionalNameLike(givenPerson.getTradeName()); + final var result = personRbacRepo.findPersonByOptionalNameLike(givenPerson.getTradeName()); // then: exactlyThesePersonsAreReturned(result, givenPerson.getTradeName()); @@ -202,14 +202,14 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // when final var result = jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", null); - personRepo.deleteByUuid(givenPerson.getUuid()); + personRbacRepo.deleteByUuid(givenPerson.getUuid()); }); // then result.assertSuccessful(); assertThat(jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", null); - return personRepo.findPersonByOptionalNameLike(givenPerson.getTradeName()); + return personRbacRepo.findPersonByOptionalNameLike(givenPerson.getTradeName()); }).assertSuccessful().returnedValue()).hasSize(0); } @@ -221,14 +221,14 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // when final var result = jpaAttempt.transacted(() -> { context("selfregistered-user-drew@hostsharing.org", null); - personRepo.deleteByUuid(givenPerson.getUuid()); + personRbacRepo.deleteByUuid(givenPerson.getUuid()); }); // then result.assertSuccessful(); assertThat(jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", null); - return personRepo.findPersonByOptionalNameLike(givenPerson.getTradeName()); + return personRbacRepo.findPersonByOptionalNameLike(givenPerson.getTradeName()); }).assertSuccessful().returnedValue()).hasSize(0); } @@ -245,7 +245,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // when final var result = jpaAttempt.transacted(() -> { context("selfregistered-user-drew@hostsharing.org", null); - return personRepo.deleteByUuid(givenPerson.getUuid()); + return personRbacRepo.deleteByUuid(givenPerson.getUuid()); }); // then @@ -281,13 +281,13 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu Supplier entitySupplier) { return jpaAttempt.transacted(() -> { context(createdByUser); - return toCleanup(personRepo.save(entitySupplier.get())); + return toCleanup(personRbacRepo.save(entitySupplier.get())); }).assumeSuccessful().returnedValue(); } private HsOfficePersonRbacEntity givenSomeTemporaryPerson(final String createdByUser) { return givenSomeTemporaryPerson(createdByUser, () -> - hsOfficePerson("some temporary person #" + RandomStringUtils.random(12))); + hsOfficePersonRbacEntity("some temporary person #" + RandomStringUtils.random(12))); } void exactlyThesePersonsAreReturned(final List actualResult, final String... personCaptions) { @@ -298,7 +298,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu void allThesePersonsAreReturned(final List actualResult, final String... personCaptions) { assertThat(actualResult) - .extracting(hsOfficePersonEntity -> hsOfficePersonEntity.toShortString()) + .extracting(HsOfficePerson::toShortString) .contains(personCaptions); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/TestHsOfficePerson.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacTestEntity.java similarity index 63% rename from src/test/java/net/hostsharing/hsadminng/hs/office/person/TestHsOfficePerson.java rename to src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacTestEntity.java index b0612ba0..7a6d6261 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/TestHsOfficePerson.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRbacTestEntity.java @@ -1,11 +1,11 @@ package net.hostsharing.hsadminng.hs.office.person; -public class TestHsOfficePerson { +public class HsOfficePersonRbacTestEntity { - public static final HsOfficePersonRbacEntity somePerson = hsOfficePerson("some person"); + public static final HsOfficePersonRbacEntity somePerson = hsOfficePersonRbacEntity("some person"); - static public HsOfficePersonRbacEntity hsOfficePerson(final String tradeName) { + public static HsOfficePersonRbacEntity hsOfficePersonRbacEntity(final String tradeName) { return HsOfficePersonRbacEntity.builder() .personType(HsOfficePersonType.NATURAL_PERSON) .tradeName(tradeName) 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 new file mode 100644 index 00000000..91897601 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealRepositoryIntegrationTest.java @@ -0,0 +1,182 @@ +package net.hostsharing.hsadminng.hs.office.person; + +import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.mapper.Array; +import net.hostsharing.hsadminng.rbac.grant.RawRbacGrantRepository; +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.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 jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; + +import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealTestEntity.hsOfficePersonRealEntity; +import static net.hostsharing.hsadminng.rbac.grant.RawRbacGrantEntity.distinctGrantDisplaysOf; +import static net.hostsharing.hsadminng.rbac.role.RawRbacRoleEntity.distinctRoleNamesOf; +import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt; +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Import( { Context.class, JpaAttempt.class }) +class HsOfficePersonRealRepositoryIntegrationTest extends ContextBasedTestWithCleanup { + + @Autowired + HsOfficePersonRealRepository personRealRepo; + + @Autowired + RawRbacRoleRepository rawRoleRepo; + + @Autowired + RawRbacGrantRepository rawGrantRepo; + + @PersistenceContext + EntityManager em; + + @Autowired + JpaAttempt jpaAttempt; + + @MockBean + HttpServletRequest request; + @Autowired + private HsOfficePersonRealRepository hsOfficePersonRealRepository; + + @Nested + class CreatePerson { + + @Test + public void arbitraryUser_canCreateNewPerson() { + // given + context("selfregistered-user-drew@hostsharing.org"); + final var count = personRealRepo.count(); + + // when + final var result = attempt(em, () -> toCleanup(personRealRepo.save( + hsOfficePersonRealEntity("another new person")))); + + // then + result.assertSuccessful(); + assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePersonRealEntity::getUuid).isNotNull(); + assertThatPersonIsPersisted(result.returnedValue()); + assertThat(personRealRepo.count()).isEqualTo(count + 1); + } + + @Test + public void createsAndGrantsRoles() { + // given + context("selfregistered-user-drew@hostsharing.org"); + final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); + final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()); + + // when + attempt(em, () -> toCleanup( + personRealRepo.save(hsOfficePersonRealEntity("another new person")) + )).assumeSuccessful(); + + // then + assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder( + Array.from( + initialRoleNames, + "hs_office.person#anothernewperson:OWNER", + "hs_office.person#anothernewperson:ADMIN", + "hs_office.person#anothernewperson:REFERRER" + )); + assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder( + Array.fromFormatted( + initialGrantNames, + "{ grant perm:hs_office.person#anothernewperson:INSERT>hs_office.relation to role:hs_office.person#anothernewperson:ADMIN by system and assume }", + + "{ grant role:hs_office.person#anothernewperson:OWNER to user:selfregistered-user-drew@hostsharing.org by hs_office.person#anothernewperson:OWNER and assume }", + "{ grant role:hs_office.person#anothernewperson:OWNER to role:rbac.global#global:ADMIN by system and assume }", + "{ grant perm:hs_office.person#anothernewperson:UPDATE to role:hs_office.person#anothernewperson:ADMIN by system and assume }", + "{ grant perm:hs_office.person#anothernewperson:DELETE to role:hs_office.person#anothernewperson:OWNER by system and assume }", + "{ grant role:hs_office.person#anothernewperson:ADMIN to role:hs_office.person#anothernewperson:OWNER by system and assume }", + + "{ grant perm:hs_office.person#anothernewperson:SELECT to role:hs_office.person#anothernewperson:REFERRER by system and assume }", + "{ grant role:hs_office.person#anothernewperson:REFERRER to role:hs_office.person#anothernewperson:ADMIN by system and assume }" + )); + } + + private void assertThatPersonIsPersisted(final HsOfficePersonRealEntity saved) { + final var found = personRealRepo.findByUuid(saved.getUuid()); + assertThat(found).isNotEmpty().get().extracting(Object::toString).isEqualTo(saved.toString()); + } + } + + @Nested + class FindAllPersons { + + @Test + public void arbitraryUser_canViewAllPersons() { + // given + context("selfregistered-user-drew@hostsharing.org"); + + // when + final var result = personRealRepo.findPersonByOptionalNameLike(null); + + // then + allThesePersonsAreReturned( + result, + "NP Smith, Peter", + "LP Second e.K.", + "IF Third OHG", + "UF Erben Bessler"); + } + } + + @Nested + class FindByCaptionLike { + + @Test + public void arbitraryUser_canViewAllPersons() { + // given + context("selfregistered-user-drew@hostsharing.org"); + + // when + final var result = personRealRepo.findPersonByOptionalNameLike("Second"); + + // then + exactlyThesePersonsAreReturned(result, "Second e.K."); + } + } + + @Test + public void auditJournalLogIsAvailable() { + // given + final var query = em.createNativeQuery(""" + select currentTask, targetTable, targetOp, targetdelta->>'tradename', targetdelta->>'lastname' + from base.tx_journal_v + where targettable = 'hs_office.person'; + """); + + // when + @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); + + // then + assertThat(customerLogEntries).map(Arrays::toString).contains( + "[creating person test-data, hs_office.person, INSERT, Hostsharing eG, null]", + "[creating person test-data, hs_office.person, INSERT, First GmbH, null]", + "[creating person test-data, hs_office.person, INSERT, Second e.K., null]", + "[creating person test-data, hs_office.person, INSERT, Third OHG, null]"); + } + + void exactlyThesePersonsAreReturned(final List actualResult, final String... personCaptions) { + assertThat(actualResult) + .extracting(HsOfficePersonRealEntity::getTradeName) + .containsExactlyInAnyOrder(personCaptions); + } + + void allThesePersonsAreReturned(final List actualResult, final String... personCaptions) { + assertThat(actualResult) + .extracting(HsOfficePerson::toShortString) + .contains(personCaptions); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealTestEntity.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealTestEntity.java new file mode 100644 index 00000000..3284d494 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRealTestEntity.java @@ -0,0 +1,14 @@ +package net.hostsharing.hsadminng.hs.office.person; + + +public class HsOfficePersonRealTestEntity { + + public static final HsOfficePersonRealEntity somePerson = hsOfficePersonRealEntity("some person"); + + public static HsOfficePersonRealEntity hsOfficePersonRealEntity(final String tradeName) { + return HsOfficePersonRealEntity.builder() + .personType(HsOfficePersonType.NATURAL_PERSON) + .tradeName(tradeName) + .build(); + } +}