diff --git a/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerEntity.java index 84a87517..3c43cf11 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerEntity.java @@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.admin.partner; import lombok.*; import net.hostsharing.hsadminng.hs.admin.contact.HsAdminContactEntity; import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonEntity; -import org.hibernate.annotations.Cascade; import javax.persistence.*; import java.time.LocalDate; @@ -33,4 +32,8 @@ public class HsAdminPartnerEntity { private @Column(name = "birthname") String birthName; private @Column(name = "birthday") LocalDate birthday; private @Column(name = "dateofdeath") LocalDate dateOfDeath; + + public String getDisplayName() { + return "partner(%s, %s)".formatted(person.getDisplayName(), contact.getLabel()); + } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepository.java index a7a27085..a7a731ad 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepository.java @@ -27,5 +27,6 @@ public interface HsAdminPartnerRepository extends Repository NEW.uuid, permitOps => array ['*']), - beneathRole(globalAdmin()), - withoutSubRoles(), - withUser(currentUser()), -- TODO.spec: Who is owner of a new person? - grantedByRole(globalAdmin()) + hsAdminPersonOwner(NEW), + grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']), + beneathRole(globalAdmin()), + withoutSubRoles(), + withUser(currentUser()), -- TODO.spec: Who is owner of a new person? + grantedByRole(globalAdmin()) ); -- the tenant role for those related users who can view the data @@ -83,9 +83,9 @@ begin -- the tenant role for those related users who can view the data perform createRole( - hsAdminPersonTenant(NEW), - grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']), - beneathRole(adminRole) + hsAdminPersonTenant(NEW), + grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']), + beneathRole(adminRole) ); return NEW; @@ -107,6 +107,8 @@ execute procedure createRbacRolesForHsAdminPerson(); --changeset hs-admin-person-rbac-ROLES-REMOVAL:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- TODO: can we replace all these delete triggers by a delete trigger on RbacObject? + /* Deletes the roles and their assignments of a deleted person for the BEFORE DELETE TRIGGER. */ @@ -117,6 +119,7 @@ create or replace function deleteRbacRulesForHsAdminPerson() begin if TG_OP = 'DELETE' then call deleteRole(findRoleId(hsAdminPersonOwner(OLD))); + call deleteRole(findRoleId(hsAdminPersonAdmin(OLD))); call deleteRole(findRoleId(hsAdminPersonTenant(OLD))); else raise exception 'invalid usage of TRIGGER BEFORE DELETE'; @@ -224,6 +227,8 @@ execute function insertHsAdminPerson(); /** Instead of delete trigger function for hs_admin_person_rv. + + Checks if the current subject (user / assumed role) has the permission to delete the row. */ create or replace function deleteHsAdminPerson() returns trigger @@ -255,9 +260,9 @@ execute function deleteHsAdminPerson(); */ do language plpgsql $$ declare - addCustomerPermissions uuid[]; - globalObjectUuid uuid; - globalAdminRoleUuid uuid ; + addCustomerPermissions uuid[]; + globalObjectUuid uuid; + globalAdminRoleUuid uuid ; begin call defineContext('granting global new-person permission to global admin role', null, null, null); diff --git a/src/main/resources/db/changelog/218-hs-admin-person-test-data.sql b/src/main/resources/db/changelog/218-hs-admin-person-test-data.sql index 102c05f2..25e7af6b 100644 --- a/src/main/resources/db/changelog/218-hs-admin-person-test-data.sql +++ b/src/main/resources/db/changelog/218-hs-admin-person-test-data.sql @@ -63,7 +63,7 @@ do language plpgsql $$ call createHsAdminPersonTestData('NATURAL', null, 'Peter', 'Smith'); call createHsAdminPersonTestData('LEGAL', 'Rockshop e.K.', 'Sandra', 'Miller'); call createHsAdminPersonTestData('SOLE_REPRESENTATION', 'Ostfriesische Kuhhandel OHG'); - call createHsAdminPersonTestData('JOINT_REPRESENTATION', 'Erbengemeinschaft Bessler', 'Mel', 'Bessler'); + call createHsAdminPersonTestData('JOINT_REPRESENTATION', 'Erben Bessler', 'Mel', 'Bessler'); end; $$; --// diff --git a/src/main/resources/db/changelog/220-hs-admin-partner.sql b/src/main/resources/db/changelog/220-hs-admin-partner.sql index 8dda0959..740c757f 100644 --- a/src/main/resources/db/changelog/220-hs-admin-partner.sql +++ b/src/main/resources/db/changelog/220-hs-admin-partner.sql @@ -6,7 +6,7 @@ create table if not exists hs_admin_partner ( - uuid uuid unique references RbacObject (uuid), + uuid uuid unique references RbacObject (uuid) on delete cascade, personUuid uuid not null references hs_admin_person(uuid), contactUuid uuid not null references hs_admin_contact(uuid), registrationOffice varchar(96), diff --git a/src/main/resources/db/changelog/223-hs-admin-partner-rbac.sql b/src/main/resources/db/changelog/223-hs-admin-partner-rbac.sql index c813815b..c858c6e9 100644 --- a/src/main/resources/db/changelog/223-hs-admin-partner-rbac.sql +++ b/src/main/resources/db/changelog/223-hs-admin-partner-rbac.sql @@ -234,6 +234,8 @@ execute function insertHsAdminPartner(); /** Instead of delete trigger function for hs_admin_partner_rv. + + Checks if the current subject (user / assumed role) has the permission to delete the row. */ create or replace function deleteHsAdminPartner() returns trigger diff --git a/src/test/java/net/hostsharing/hsadminng/hs/admin/contact/HsAdminContactRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/admin/contact/HsAdminContactRepositoryIntegrationTest.java index 3d4a5d72..06e48234 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/admin/contact/HsAdminContactRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/admin/contact/HsAdminContactRepositoryIntegrationTest.java @@ -4,6 +4,7 @@ import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.ContextBasedTest; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; +import net.hostsharing.test.Array; import net.hostsharing.test.JpaAttempt; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; @@ -97,7 +98,7 @@ class HsAdminContactRepositoryIntegrationTest extends ContextBasedTest { // given context("drew@hostsharing.org"); final var count = contactRepo.count(); - final var initialRoleCount = roleRepo.findAll().size(); + final var initialRoleNames = roleNamesOf(roleRepo.findAll()); final var initialGrantCount = grantRepo.findAll().size(); // when @@ -107,11 +108,12 @@ class HsAdminContactRepositoryIntegrationTest extends ContextBasedTest { // then final var roles = roleRepo.findAll(); - assertThat(roleNamesOf(roles)).containsAll(List.of( - "hs_admin_contact#anothernewcontact.owner", - "hs_admin_contact#anothernewcontact.tenant")); - assertThat(roles.size()).as("invalid number of roles created") - .isEqualTo(initialRoleCount + 2); + assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder( + Array.from( + initialRoleNames, + "hs_admin_contact#anothernewcontact.owner", + "hs_admin_contact#anothernewcontact.admin", + "hs_admin_contact#anothernewcontact.tenant")); final var grants = grantRepo.findAll(); assertThat(grantDisplaysOf(grants)).containsAll(List.of( "{ grant assumed role hs_admin_contact#anothernewcontact.owner to user drew@hostsharing.org by role global#global.admin }")); @@ -265,7 +267,7 @@ class HsAdminContactRepositoryIntegrationTest extends ContextBasedTest { context("alex@hostsharing.net", null); final var result = contactRepo.findContactByOptionalLabelLike("some temporary contact"); result.forEach(tempPerson -> { - System.out.println("DELETING contact: " + tempPerson.getLabel()); + System.out.println("DELETING temporary contact: " + tempPerson.getLabel()); contactRepo.deleteByUuid(tempPerson.getUuid()); }); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepositoryIntegrationTest.java index 3c221bb3..04aa6481 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/admin/partner/HsAdminPartnerRepositoryIntegrationTest.java @@ -5,9 +5,11 @@ import net.hostsharing.hsadminng.context.ContextBasedTest; import net.hostsharing.hsadminng.hs.admin.contact.HsAdminContactRepository; import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonEntity; import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonRepository; -import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; -import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; +import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; +import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; +import net.hostsharing.test.Array; import net.hostsharing.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; @@ -19,11 +21,13 @@ import org.springframework.test.annotation.DirtiesContext; import javax.persistence.EntityManager; import javax.servlet.http.HttpServletRequest; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.UUID; -import static net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantDisplayExtractor.grantDisplaysOf; -import static net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleNameExtractor.roleNamesOf; +import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantDisplayExtractor.grantDisplaysOf; +import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleNameExtractor.roleNamesOf; import static net.hostsharing.test.JpaAttempt.attempt; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assumptions.assumeThat; @@ -43,10 +47,10 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { HsAdminContactRepository contactRepo; @Autowired - RbacRoleRepository roleRepo; + RawRbacRoleRepository rawRoleRepo; @Autowired - RbacGrantRepository grantRepo; + RawRbacGrantRepository rawGrantRepo; @Autowired EntityManager em; @@ -57,6 +61,8 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { @MockBean HttpServletRequest request; + Set tempPartners = new HashSet<>(); + @Nested class CreatePartner { @@ -89,12 +95,13 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { public void createsAndGrantsRoles() { // given context("alex@hostsharing.net"); - final var initialRoleCount = roleRepo.findAll().size(); - final var initialGrantCount = grantRepo.findAll().size(); + final var initialRoleCount = rawRoleRepo.findAll().size(); + final var initialGrantCount = rawGrantRepo.findAll().size(); + final var initialGrantsDisplayNames = grantDisplaysOf(rawGrantRepo.findAll()); // when attempt(em, () -> { - final var givenPerson = personRepo.findPersonByOptionalNameLike("Erbengemeinschaft Bessler").get(0); + final var givenPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0); final var newPartner = HsAdminPartnerEntity.builder() .uuid(UUID.randomUUID()) @@ -105,21 +112,24 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { }); // then - final var roles = roleRepo.findAll(); - assertThat(roleNamesOf(roles)).containsAll(List.of( - "hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.admin", - "hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.owner", - "hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.tenant")); - assertThat(roles.size()).as("invalid number of roles created") - .isEqualTo(initialRoleCount + 3); - - context("customer-admin@forthcontact.example.com"); - assertThat(grantDisplaysOf(grantRepo.findAll())).containsAll(List.of( - "{ grant assumed role hs_admin_contact#forthcontact.owner to user customer-admin@forthcontact.example.com by role global#global.admin }")); - - context("person-ErbengemeinschaftBesslerMelBessl@example.com"); - assertThat(grantDisplaysOf(grantRepo.findAll())).containsAll(List.of( - "{ grant assumed role hs_admin_person#ErbengemeinschaftBesslerMelBessler.owner to user person-ErbengemeinschaftBesslerMelBessl@example.com by role global#global.admin }")); + assertThat(roleNamesOf(rawRoleRepo.findAll())).containsAll(List.of( + "hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin", + "hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner", + "hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant")) + .as("invalid number of roles created") + .hasSize(initialRoleCount + 3); + assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsAll(List.of( + "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner to role global#global.admin by system and assume }", + "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant to role hs_admin_contact#forthcontact.admin by system and assume }", + "{ grant perm edit on hs_admin_partner#ErbenBesslerMelBessler-forthcontact to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin by system and assume }", + "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin by system and assume }", + "{ grant perm * on hs_admin_partner#ErbenBesslerMelBessler-forthcontact to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner by system and assume }", + "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner by system and assume }", + "{ grant perm view on hs_admin_partner#ErbenBesslerMelBessler-forthcontact to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant by system and assume }", + "{ grant role hs_admin_contact#forthcontact.tenant to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant by system and assume }", + "{ grant role hs_admin_person#ErbenBesslerMelBessler.tenant to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant by system and assume }", + "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant to role hs_admin_person#ErbenBesslerMelBessler.admin by system and assume }")) + .as("invalid number of grants created").hasSize(initialGrantCount + 10); } private void assertThatPartnerIsPersisted(final HsAdminPartnerEntity saved) { @@ -199,19 +209,20 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { public void nonGlobalAdmin_canNotDeleteTheirRelatedPartner() { // given context("alex@hostsharing.net", null); - final var givenPartner = givenSomeTemporaryPartnerBessler(); + final var givenPartner = toCleanup(givenSomeTemporaryPartnerBessler()); // when final var result = jpaAttempt.transacted(() -> { - context("person-ErbengemeinschaftBesslerMelBessl@example.com"); - assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent(); + context("person-ErbenBesslerMelBessler@example.com"); + assumeThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent(); partnerRepo.deleteByUuid(givenPartner.getUuid()); }); // then - result.assertExceptionWithRootCauseMessage(JpaSystemException.class, - "[403] User person-ErbengemeinschaftBesslerMelBessl@example.com not allowed to delete partner"); + result.assertExceptionWithRootCauseMessage( + JpaSystemException.class, + "[403] User person-ErbenBesslerMelBessler@example.com not allowed to delete partner"); assertThat(jpaAttempt.transacted(() -> { context("alex@hostsharing.net"); return partnerRepo.findByUuid(givenPartner.getUuid()); @@ -222,10 +233,13 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { public void deletingAPartnerAlsoDeletesRelatedRolesAndGrants() { // given context("alex@hostsharing.net"); - final var initialRoleCount = roleRepo.findAll().size(); + final var initialRoleNames = Array.from(roleNamesOf(rawRoleRepo.findAll())); + final var initialGrantNames = Array.from(grantDisplaysOf(rawGrantRepo.findAll())); final var givenPartner = givenSomeTemporaryPartnerBessler(); - assumeThat(roleRepo.findAll().size()).as("unexpected number of roles created") - .isEqualTo(initialRoleCount + 3);; + assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created") + .isEqualTo(initialRoleNames.length + 3); + assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created") + .isEqualTo(initialGrantNames.length + 10); // when final var result = jpaAttempt.transacted(() -> { @@ -234,28 +248,23 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { }).assertSuccessful(); // then - final var roles = roleRepo.findAll(); - assertThat(roleNamesOf(roles)).doesNotContainAnyElementsOf(List.of( - "hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.admin", - "hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.owner", - "hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.tenant")); - assertThat(roles.size()).as("invalid number of roles created") - .isEqualTo(initialRoleCount); + final var roles = rawRoleRepo.findAll(); + assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder(initialRoleNames); context("customer-admin@forthcontact.example.com"); - assertThat(grantDisplaysOf(grantRepo.findAll())).doesNotContain( + assertThat(grantDisplaysOf(rawGrantRepo.findAll())).doesNotContain( "{ grant assumed role hs_admin_contact#forthcontact.owner to user customer-admin@forthcontact.example.com by role global#global.admin }"); - context("person-ErbengemeinschaftBesslerMelBessl@example.com"); - assertThat(grantDisplaysOf(grantRepo.findAll())).doesNotContain( - "{ grant assumed role hs_admin_person#ErbengemeinschaftBesslerMelBessler.owner to user person-ErbengemeinschaftBesslerMelBessl@example.com by role global#global.admin }"); + context("person-ErbenBesslerMelBessler@example.com"); + assertThat(grantDisplaysOf(rawGrantRepo.findAll())).doesNotContain( + "{ grant assumed role hs_admin_person#ErbenBesslerMelBessler.owner to user person-ErbenBesslerMelBessl@example.com by role global#global.admin }"); } } private HsAdminPartnerEntity givenSomeTemporaryPartnerBessler() { return jpaAttempt.transacted(() -> { context("alex@hostsharing.net"); - final var givenPerson = personRepo.findPersonByOptionalNameLike("Erbengemeinschaft Bessler").get(0); + final var givenPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0); final var newPartner = HsAdminPartnerEntity.builder() .uuid(UUID.randomUUID()) @@ -267,6 +276,21 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest { }).assertSuccessful().returnedValue(); } + private HsAdminPartnerEntity toCleanup(final HsAdminPartnerEntity tempPartner) { + tempPartners.add(tempPartner); + return tempPartner; + } + + @AfterEach + void cleanup() { + context("alex@hostsharing.net", null); + tempPartners.forEach(tempPartner -> { + System.out.println("DELETING temporary partner: " + tempPartner.getDisplayName()); + final var count = partnerRepo.deleteByUuid(tempPartner.getUuid()); + assertThat(count).isGreaterThan(0); + }); + } + void exactlyThesePartnersAreReturned(final List actualResult, final String... partnerTradeNames) { assertThat(actualResult) .hasSize(partnerTradeNames.length) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/admin/person/HsAdminPersonRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/admin/person/HsAdminPersonRepositoryIntegrationTest.java index 7333d8d6..f720625f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/admin/person/HsAdminPersonRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/admin/person/HsAdminPersonRepositoryIntegrationTest.java @@ -2,8 +2,9 @@ package net.hostsharing.hsadminng.hs.admin.person; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.ContextBasedTest; -import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; -import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; +import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; +import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; +import net.hostsharing.test.Array; import net.hostsharing.test.JpaAttempt; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; @@ -21,8 +22,8 @@ import java.util.List; import java.util.function.Supplier; import static net.hostsharing.hsadminng.hs.admin.person.TestHsAdminPerson.hsAdminPerson; -import static net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantDisplayExtractor.grantDisplaysOf; -import static net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleNameExtractor.roleNamesOf; +import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantDisplayExtractor.grantDisplaysOf; +import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleNameExtractor.roleNamesOf; import static net.hostsharing.test.JpaAttempt.attempt; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assumptions.assumeThat; @@ -36,10 +37,10 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest { HsAdminPersonRepository personRepo; @Autowired - RbacRoleRepository roleRepo; + RawRbacRoleRepository rawRoleRepo; @Autowired - RbacGrantRepository grantRepo; + RawRbacGrantRepository rawGrantRepo; @Autowired EntityManager em; @@ -93,8 +94,8 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest { // given context("drew@hostsharing.org"); final var count = personRepo.count(); - final var initialRoleCount = roleRepo.findAll().size(); - final var initialGrantCount = grantRepo.findAll().size(); + final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll()); + final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()); // when attempt(em, () -> personRepo.save( @@ -102,17 +103,24 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest { ).assumeSuccessful(); // then - final var roles = roleRepo.findAll(); - assertThat(roleNamesOf(roles)).containsAll(List.of( - "hs_admin_person#anothernewperson.owner", - "hs_admin_person#anothernewperson.tenant")); - assertThat(roles.size()).as("invalid number of roles created") - .isEqualTo(initialRoleCount + 2); - final var grants = grantRepo.findAll(); - assertThat(grantDisplaysOf(grants)).containsAll(List.of( - "{ grant assumed role hs_admin_person#anothernewperson.owner to user drew@hostsharing.org by role global#global.admin }")); - assertThat(grants.size()).as("invalid number of grants created") - .isEqualTo(initialGrantCount + 1); + assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder( + Array.from( + initialRoleNames, + "hs_admin_person#anothernewperson.owner", + "hs_admin_person#anothernewperson.admin", + "hs_admin_person#anothernewperson.tenant" + )); + assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder( + Array.from( + initialGrantNames, + "{ grant role hs_admin_person#anothernewperson.owner to role global#global.admin by system and assume }", + "{ grant perm edit on hs_admin_person#anothernewperson to role hs_admin_person#anothernewperson.admin by system and assume }", + "{ grant role hs_admin_person#anothernewperson.tenant to role hs_admin_person#anothernewperson.admin by system and assume }", + "{ grant perm * on hs_admin_person#anothernewperson to role hs_admin_person#anothernewperson.owner by system and assume }", + "{ grant role hs_admin_person#anothernewperson.admin to role hs_admin_person#anothernewperson.owner by system and assume }", + "{ grant perm view on hs_admin_person#anothernewperson to role hs_admin_person#anothernewperson.tenant by system and assume }", + "{ grant role hs_admin_person#anothernewperson.owner to user drew@hostsharing.org by global#global.admin and assume }" + )); } private void assertThatPersonIsPersisted(final HsAdminPersonEntity saved) { @@ -137,8 +145,8 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest { result, "Peter, Smith", "Rockshop e.K.", - "Ostfriesische Stahlhandel OHG", - "Erbengemeinschaft Bessler"); + "Ostfriesische Kuhhandel OHG", + "Erben Bessler"); } @Test @@ -231,25 +239,25 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest { public void deletingAPersonAlsoDeletesRelatedRolesAndGrants() { // given context("drew@hostsharing.org", null); - final var initialRoleCount = roleRepo.findAll().size(); - final var initialGrantCount = grantRepo.findAll().size(); + final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll()); + final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()); final var givenPerson = givenSomeTemporaryPerson("drew@hostsharing.org"); - assumeThat(roleRepo.findAll().size()).as("unexpected number of roles created") - .isEqualTo(initialRoleCount + 2); - assumeThat(grantRepo.findAll().size()).as("unexpected number of grants created") - .isEqualTo(initialGrantCount + 1); + assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created") + .isEqualTo(initialRoleNames.size() + 3); + assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created") + .isEqualTo(initialGrantNames.size() + 7); // when final var result = jpaAttempt.transacted(() -> { context("drew@hostsharing.org", null); - personRepo.deleteByUuid(givenPerson.getUuid()); - }).assumeSuccessful(); + return personRepo.deleteByUuid(givenPerson.getUuid()); + }); // then - assertThat(roleRepo.findAll().size()).as("invalid number of roles deleted") - .isEqualTo(initialRoleCount); - assertThat(grantRepo.findAll().size()).as("invalid number of grants revoked") - .isEqualTo(initialGrantCount); + result.assertSuccessful(); + assertThat(result.returnedValue()).isEqualTo(1); + assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(initialRoleNames)); + assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.from(initialGrantNames)); } } @@ -258,7 +266,7 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest { context("alex@hostsharing.net", null); final var result = personRepo.findPersonByOptionalNameLike("some temporary person"); result.forEach(tempPerson -> { - System.out.println("DELETING person: " + tempPerson.getDisplayName()); + System.out.println("DELETING temporary person: " + tempPerson.getDisplayName()); personRepo.deleteByUuid(tempPerson.getUuid()); }); } diff --git a/src/test/java/net/hostsharing/test/Array.java b/src/test/java/net/hostsharing/test/Array.java index f5221ef9..1c98ce57 100644 --- a/src/test/java/net/hostsharing/test/Array.java +++ b/src/test/java/net/hostsharing/test/Array.java @@ -1,8 +1,12 @@ package net.hostsharing.test; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * Java has List.of(...), Set.of(...) and Map.of(...) all with varargs parameter, - * but no Array.of(...). Here it is. + * Java has List.of(...), Set.of(...) and Map.of(...) all with varargs parameter, + * but no Array.of(...). Here it is. */ public class Array { @@ -10,4 +14,17 @@ public class Array { public static E[] of(E... elements) { return elements; } + + public static String[] from(final List initialList, final String... additionalStrings) { + final var resultList = new ArrayList<>(initialList); + resultList.addAll(Arrays.asList(additionalStrings)); + return resultList.toArray(String[]::new); + } + + public static String[] from(final String[] initialStrings, final String... additionalStrings) { + final var resultList = Arrays.asList(initialStrings); + resultList.addAll(Arrays.asList(additionalStrings)); + return resultList.toArray(String[]::new); + } + }