improve Contact/Partner/Contact Repository integration tests with Raw...Repos

This commit is contained in:
Michael Hoennig 2022-09-12 16:27:17 +02:00
parent 3eec8a4138
commit ac5f19e399
16 changed files with 210 additions and 109 deletions

View File

@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.admin.partner;
import lombok.*; import lombok.*;
import net.hostsharing.hsadminng.hs.admin.contact.HsAdminContactEntity; import net.hostsharing.hsadminng.hs.admin.contact.HsAdminContactEntity;
import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonEntity; import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonEntity;
import org.hibernate.annotations.Cascade;
import javax.persistence.*; import javax.persistence.*;
import java.time.LocalDate; import java.time.LocalDate;
@ -33,4 +32,8 @@ public class HsAdminPartnerEntity {
private @Column(name = "birthname") String birthName; private @Column(name = "birthname") String birthName;
private @Column(name = "birthday") LocalDate birthday; private @Column(name = "birthday") LocalDate birthday;
private @Column(name = "dateofdeath") LocalDate dateOfDeath; private @Column(name = "dateofdeath") LocalDate dateOfDeath;
public String getDisplayName() {
return "partner(%s, %s)".formatted(person.getDisplayName(), contact.getLabel());
}
} }

View File

@ -27,5 +27,6 @@ public interface HsAdminPartnerRepository extends Repository<HsAdminPartnerEntit
HsAdminPartnerEntity save(final HsAdminPartnerEntity entity); HsAdminPartnerEntity save(final HsAdminPartnerEntity entity);
long count(); long count();
void deleteByUuid(UUID uuid);
int deleteByUuid(UUID uuid);
} }

View File

@ -22,7 +22,7 @@ public interface HsAdminPersonRepository extends Repository<HsAdminPersonEntity,
HsAdminPersonEntity save(final HsAdminPersonEntity entity); HsAdminPersonEntity save(final HsAdminPersonEntity entity);
void deleteByUuid(final UUID personUuid); int deleteByUuid(final UUID personUuid);
long count(); long count();
} }

View File

@ -205,6 +205,7 @@ $$;
create or replace procedure deleteRole(roleUUid uuid) create or replace procedure deleteRole(roleUUid uuid)
language plpgsql as $$ language plpgsql as $$
begin begin
--raise exception '% deleting role uuid %', currentsubjectsuuids(), roleUUid;
delete from RbacRole where uuid = roleUUid; delete from RbacRole where uuid = roleUUid;
end; end;
$$; $$;
@ -266,6 +267,38 @@ begin
end; end;
$$; $$;
-- ============================================================================
--changeset hs-admin-person-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
RbacRole BEFORE DELETE TRIGGER function which deletes all related roles.
*/
create or replace function deleteRbacGrantsForRbacRole()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
delete from RbacGrants g where old.uuid in (g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid);
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
return old;
end; $$;
/*
Installs the RbacRole BEFORE DELETE TRIGGER.
*/
create trigger deleteRbacGrantsForRbacRole_Trigger
before delete
on RbacRole
for each row
execute procedure deleteRbacGrantsForRbacRole();
--//
-- ============================================================================ -- ============================================================================
--changeset rbac-base-PERMISSION:1 endDelimiter:--// --changeset rbac-base-PERMISSION:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -363,9 +396,9 @@ $$;
create table RbacGrants create table RbacGrants
( (
uuid uuid primary key default uuid_generate_v4(), uuid uuid primary key default uuid_generate_v4(),
grantedByRoleUuid uuid references RbacRole (uuid) on delete cascade, grantedByRoleUuid uuid references RbacRole (uuid),
ascendantUuid uuid references RbacReference (uuid) on delete cascade not null, ascendantUuid uuid references RbacReference (uuid),
descendantUuid uuid references RbacReference (uuid) on delete cascade not null, descendantUuid uuid references RbacReference (uuid),
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false) assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
unique (ascendantUuid, descendantUuid) unique (ascendantUuid, descendantUuid)
); );

View File

@ -168,6 +168,8 @@ execute function insertRbacGrant();
/** /**
Instead of delete trigger function for RbacGrants_RV. Instead of delete trigger function for RbacGrants_RV.
Checks if the current subject (user / assumed role) has the permission to revoke the grant.
*/ */
create or replace function deleteRbacGrant() create or replace function deleteRbacGrant()
returns trigger returns trigger
@ -283,6 +285,8 @@ execute function insertRbacUser();
/** /**
Instead of delete trigger function for RbacUser_RV. Instead of delete trigger function for RbacUser_RV.
Checks if the current subject (user / assumed role) has the permission to delete the user.
*/ */
create or replace function deleteRbacUser() create or replace function deleteRbacUser()
returns trigger returns trigger

View File

@ -6,7 +6,7 @@
create table if not exists hs_admin_contact create table if not exists hs_admin_contact
( (
uuid uuid unique references RbacObject (uuid), uuid uuid unique references RbacObject (uuid) on delete cascade,
label varchar(96) not null, label varchar(96) not null,
postalAddress text, postalAddress text,
emailAddresses text, -- TODO.feat: change to json emailAddresses text, -- TODO.feat: change to json

View File

@ -224,6 +224,8 @@ execute function insertHsAdminContact();
/** /**
Instead of delete trigger function for hs_admin_contact_rv. Instead of delete trigger function for hs_admin_contact_rv.
Checks if the current subject (user / assumed role) has the permission to delete the row.
*/ */
create or replace function deleteHsAdminContact() create or replace function deleteHsAdminContact()
returns trigger returns trigger

View File

@ -10,7 +10,7 @@ CREATE CAST (character varying as HsAdminPersonType) WITH INOUT AS IMPLICIT;
create table if not exists hs_admin_person create table if not exists hs_admin_person
( (
uuid uuid unique references RbacObject (uuid), uuid uuid unique references RbacObject (uuid) on delete cascade,
personType HsAdminPersonType not null, personType HsAdminPersonType not null,
tradeName varchar(96), tradeName varchar(96),
givenName varchar(48), givenName varchar(48),

View File

@ -66,12 +66,12 @@ begin
-- the owner role with full access for the creator assigned to the current user -- the owner role with full access for the creator assigned to the current user
ownerRole := createRole( ownerRole := createRole(
hsAdminPersonOwner(NEW), hsAdminPersonOwner(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']), grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
beneathRole(globalAdmin()), beneathRole(globalAdmin()),
withoutSubRoles(), withoutSubRoles(),
withUser(currentUser()), -- TODO.spec: Who is owner of a new person? withUser(currentUser()), -- TODO.spec: Who is owner of a new person?
grantedByRole(globalAdmin()) grantedByRole(globalAdmin())
); );
-- the tenant role for those related users who can view the data -- 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 -- the tenant role for those related users who can view the data
perform createRole( perform createRole(
hsAdminPersonTenant(NEW), hsAdminPersonTenant(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']), grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
beneathRole(adminRole) beneathRole(adminRole)
); );
return NEW; return NEW;
@ -107,6 +107,8 @@ execute procedure createRbacRolesForHsAdminPerson();
--changeset hs-admin-person-rbac-ROLES-REMOVAL:1 endDelimiter:--// --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. 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 begin
if TG_OP = 'DELETE' then if TG_OP = 'DELETE' then
call deleteRole(findRoleId(hsAdminPersonOwner(OLD))); call deleteRole(findRoleId(hsAdminPersonOwner(OLD)));
call deleteRole(findRoleId(hsAdminPersonAdmin(OLD)));
call deleteRole(findRoleId(hsAdminPersonTenant(OLD))); call deleteRole(findRoleId(hsAdminPersonTenant(OLD)));
else else
raise exception 'invalid usage of TRIGGER BEFORE DELETE'; 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. 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() create or replace function deleteHsAdminPerson()
returns trigger returns trigger
@ -255,9 +260,9 @@ execute function deleteHsAdminPerson();
*/ */
do language plpgsql $$ do language plpgsql $$
declare declare
addCustomerPermissions uuid[]; addCustomerPermissions uuid[];
globalObjectUuid uuid; globalObjectUuid uuid;
globalAdminRoleUuid uuid ; globalAdminRoleUuid uuid ;
begin begin
call defineContext('granting global new-person permission to global admin role', null, null, null); call defineContext('granting global new-person permission to global admin role', null, null, null);

View File

@ -63,7 +63,7 @@ do language plpgsql $$
call createHsAdminPersonTestData('NATURAL', null, 'Peter', 'Smith'); call createHsAdminPersonTestData('NATURAL', null, 'Peter', 'Smith');
call createHsAdminPersonTestData('LEGAL', 'Rockshop e.K.', 'Sandra', 'Miller'); call createHsAdminPersonTestData('LEGAL', 'Rockshop e.K.', 'Sandra', 'Miller');
call createHsAdminPersonTestData('SOLE_REPRESENTATION', 'Ostfriesische Kuhhandel OHG'); call createHsAdminPersonTestData('SOLE_REPRESENTATION', 'Ostfriesische Kuhhandel OHG');
call createHsAdminPersonTestData('JOINT_REPRESENTATION', 'Erbengemeinschaft Bessler', 'Mel', 'Bessler'); call createHsAdminPersonTestData('JOINT_REPRESENTATION', 'Erben Bessler', 'Mel', 'Bessler');
end; end;
$$; $$;
--// --//

View File

@ -6,7 +6,7 @@
create table if not exists hs_admin_partner 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), personUuid uuid not null references hs_admin_person(uuid),
contactUuid uuid not null references hs_admin_contact(uuid), contactUuid uuid not null references hs_admin_contact(uuid),
registrationOffice varchar(96), registrationOffice varchar(96),

View File

@ -234,6 +234,8 @@ execute function insertHsAdminPartner();
/** /**
Instead of delete trigger function for hs_admin_partner_rv. 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() create or replace function deleteHsAdminPartner()
returns trigger returns trigger

View File

@ -4,6 +4,7 @@ import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.context.ContextBasedTest; import net.hostsharing.hsadminng.context.ContextBasedTest;
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
@ -97,7 +98,7 @@ class HsAdminContactRepositoryIntegrationTest extends ContextBasedTest {
// given // given
context("drew@hostsharing.org"); context("drew@hostsharing.org");
final var count = contactRepo.count(); final var count = contactRepo.count();
final var initialRoleCount = roleRepo.findAll().size(); final var initialRoleNames = roleNamesOf(roleRepo.findAll());
final var initialGrantCount = grantRepo.findAll().size(); final var initialGrantCount = grantRepo.findAll().size();
// when // when
@ -107,11 +108,12 @@ class HsAdminContactRepositoryIntegrationTest extends ContextBasedTest {
// then // then
final var roles = roleRepo.findAll(); final var roles = roleRepo.findAll();
assertThat(roleNamesOf(roles)).containsAll(List.of( assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder(
"hs_admin_contact#anothernewcontact.owner", Array.from(
"hs_admin_contact#anothernewcontact.tenant")); initialRoleNames,
assertThat(roles.size()).as("invalid number of roles created") "hs_admin_contact#anothernewcontact.owner",
.isEqualTo(initialRoleCount + 2); "hs_admin_contact#anothernewcontact.admin",
"hs_admin_contact#anothernewcontact.tenant"));
final var grants = grantRepo.findAll(); final var grants = grantRepo.findAll();
assertThat(grantDisplaysOf(grants)).containsAll(List.of( assertThat(grantDisplaysOf(grants)).containsAll(List.of(
"{ grant assumed role hs_admin_contact#anothernewcontact.owner to user drew@hostsharing.org by role global#global.admin }")); "{ 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); context("alex@hostsharing.net", null);
final var result = contactRepo.findContactByOptionalLabelLike("some temporary contact"); final var result = contactRepo.findContactByOptionalLabelLike("some temporary contact");
result.forEach(tempPerson -> { result.forEach(tempPerson -> {
System.out.println("DELETING contact: " + tempPerson.getLabel()); System.out.println("DELETING temporary contact: " + tempPerson.getLabel());
contactRepo.deleteByUuid(tempPerson.getUuid()); contactRepo.deleteByUuid(tempPerson.getUuid());
}); });
} }

View File

@ -5,9 +5,11 @@ import net.hostsharing.hsadminng.context.ContextBasedTest;
import net.hostsharing.hsadminng.hs.admin.contact.HsAdminContactRepository; import net.hostsharing.hsadminng.hs.admin.contact.HsAdminContactRepository;
import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonEntity; import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonEntity;
import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonRepository; import net.hostsharing.hsadminng.hs.admin.person.HsAdminPersonRepository;
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -19,11 +21,13 @@ import org.springframework.test.annotation.DirtiesContext;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantDisplayExtractor.grantDisplaysOf; import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantDisplayExtractor.grantDisplaysOf;
import static net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleNameExtractor.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleNameExtractor.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat; import static org.assertj.core.api.Assumptions.assumeThat;
@ -43,10 +47,10 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
HsAdminContactRepository contactRepo; HsAdminContactRepository contactRepo;
@Autowired @Autowired
RbacRoleRepository roleRepo; RawRbacRoleRepository rawRoleRepo;
@Autowired @Autowired
RbacGrantRepository grantRepo; RawRbacGrantRepository rawGrantRepo;
@Autowired @Autowired
EntityManager em; EntityManager em;
@ -57,6 +61,8 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
@MockBean @MockBean
HttpServletRequest request; HttpServletRequest request;
Set<HsAdminPartnerEntity> tempPartners = new HashSet<>();
@Nested @Nested
class CreatePartner { class CreatePartner {
@ -89,12 +95,13 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
public void createsAndGrantsRoles() { public void createsAndGrantsRoles() {
// given // given
context("alex@hostsharing.net"); context("alex@hostsharing.net");
final var initialRoleCount = roleRepo.findAll().size(); final var initialRoleCount = rawRoleRepo.findAll().size();
final var initialGrantCount = grantRepo.findAll().size(); final var initialGrantCount = rawGrantRepo.findAll().size();
final var initialGrantsDisplayNames = grantDisplaysOf(rawGrantRepo.findAll());
// when // when
attempt(em, () -> { 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 givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0);
final var newPartner = HsAdminPartnerEntity.builder() final var newPartner = HsAdminPartnerEntity.builder()
.uuid(UUID.randomUUID()) .uuid(UUID.randomUUID())
@ -105,21 +112,24 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
}); });
// then // then
final var roles = roleRepo.findAll(); assertThat(roleNamesOf(rawRoleRepo.findAll())).containsAll(List.of(
assertThat(roleNamesOf(roles)).containsAll(List.of( "hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin",
"hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.admin", "hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner",
"hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.owner", "hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant"))
"hs_admin_partner#ErbengemeinschaftBesslerMelBessler-forthcontact.tenant")); .as("invalid number of roles created")
assertThat(roles.size()).as("invalid number of roles created") .hasSize(initialRoleCount + 3);
.isEqualTo(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 }",
context("customer-admin@forthcontact.example.com"); "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant to role hs_admin_contact#forthcontact.admin by system and assume }",
assertThat(grantDisplaysOf(grantRepo.findAll())).containsAll(List.of( "{ grant perm edit on hs_admin_partner#ErbenBesslerMelBessler-forthcontact to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin by system and assume }",
"{ grant assumed role hs_admin_contact#forthcontact.owner to user customer-admin@forthcontact.example.com by role global#global.admin }")); "{ 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 }",
context("person-ErbengemeinschaftBesslerMelBessl@example.com"); "{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner by system and assume }",
assertThat(grantDisplaysOf(grantRepo.findAll())).containsAll(List.of( "{ grant perm view on hs_admin_partner#ErbenBesslerMelBessler-forthcontact to role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant by system and assume }",
"{ grant assumed role hs_admin_person#ErbengemeinschaftBesslerMelBessler.owner to user person-ErbengemeinschaftBesslerMelBessl@example.com by role global#global.admin }")); "{ 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) { private void assertThatPartnerIsPersisted(final HsAdminPartnerEntity saved) {
@ -199,19 +209,20 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
public void nonGlobalAdmin_canNotDeleteTheirRelatedPartner() { public void nonGlobalAdmin_canNotDeleteTheirRelatedPartner() {
// given // given
context("alex@hostsharing.net", null); context("alex@hostsharing.net", null);
final var givenPartner = givenSomeTemporaryPartnerBessler(); final var givenPartner = toCleanup(givenSomeTemporaryPartnerBessler());
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("person-ErbengemeinschaftBesslerMelBessl@example.com"); context("person-ErbenBesslerMelBessler@example.com");
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent(); assumeThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent();
partnerRepo.deleteByUuid(givenPartner.getUuid()); partnerRepo.deleteByUuid(givenPartner.getUuid());
}); });
// then // then
result.assertExceptionWithRootCauseMessage(JpaSystemException.class, result.assertExceptionWithRootCauseMessage(
"[403] User person-ErbengemeinschaftBesslerMelBessl@example.com not allowed to delete partner"); JpaSystemException.class,
"[403] User person-ErbenBesslerMelBessler@example.com not allowed to delete partner");
assertThat(jpaAttempt.transacted(() -> { assertThat(jpaAttempt.transacted(() -> {
context("alex@hostsharing.net"); context("alex@hostsharing.net");
return partnerRepo.findByUuid(givenPartner.getUuid()); return partnerRepo.findByUuid(givenPartner.getUuid());
@ -222,10 +233,13 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
public void deletingAPartnerAlsoDeletesRelatedRolesAndGrants() { public void deletingAPartnerAlsoDeletesRelatedRolesAndGrants() {
// given // given
context("alex@hostsharing.net"); 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(); final var givenPartner = givenSomeTemporaryPartnerBessler();
assumeThat(roleRepo.findAll().size()).as("unexpected number of roles created") assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
.isEqualTo(initialRoleCount + 3);; .isEqualTo(initialRoleNames.length + 3);
assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
.isEqualTo(initialGrantNames.length + 10);
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
@ -234,28 +248,23 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
}).assertSuccessful(); }).assertSuccessful();
// then // then
final var roles = roleRepo.findAll(); final var roles = rawRoleRepo.findAll();
assertThat(roleNamesOf(roles)).doesNotContainAnyElementsOf(List.of( assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder(initialRoleNames);
"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);
context("customer-admin@forthcontact.example.com"); 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 }"); "{ 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"); context("person-ErbenBesslerMelBessler@example.com");
assertThat(grantDisplaysOf(grantRepo.findAll())).doesNotContain( assertThat(grantDisplaysOf(rawGrantRepo.findAll())).doesNotContain(
"{ grant assumed role hs_admin_person#ErbengemeinschaftBesslerMelBessler.owner to user person-ErbengemeinschaftBesslerMelBessl@example.com by role global#global.admin }"); "{ grant assumed role hs_admin_person#ErbenBesslerMelBessler.owner to user person-ErbenBesslerMelBessl@example.com by role global#global.admin }");
} }
} }
private HsAdminPartnerEntity givenSomeTemporaryPartnerBessler() { private HsAdminPartnerEntity givenSomeTemporaryPartnerBessler() {
return jpaAttempt.transacted(() -> { return jpaAttempt.transacted(() -> {
context("alex@hostsharing.net"); 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 givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0);
final var newPartner = HsAdminPartnerEntity.builder() final var newPartner = HsAdminPartnerEntity.builder()
.uuid(UUID.randomUUID()) .uuid(UUID.randomUUID())
@ -267,6 +276,21 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
}).assertSuccessful().returnedValue(); }).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<HsAdminPartnerEntity> actualResult, final String... partnerTradeNames) { void exactlyThesePartnersAreReturned(final List<HsAdminPartnerEntity> actualResult, final String... partnerTradeNames) {
assertThat(actualResult) assertThat(actualResult)
.hasSize(partnerTradeNames.length) .hasSize(partnerTradeNames.length)

View File

@ -2,8 +2,9 @@ package net.hostsharing.hsadminng.hs.admin.person;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.context.ContextBasedTest; import net.hostsharing.hsadminng.context.ContextBasedTest;
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
@ -21,8 +22,8 @@ import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import static net.hostsharing.hsadminng.hs.admin.person.TestHsAdminPerson.hsAdminPerson; 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.rbacgrant.RawRbacGrantDisplayExtractor.grantDisplaysOf;
import static net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleNameExtractor.roleNamesOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleNameExtractor.roleNamesOf;
import static net.hostsharing.test.JpaAttempt.attempt; import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat; import static org.assertj.core.api.Assumptions.assumeThat;
@ -36,10 +37,10 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest {
HsAdminPersonRepository personRepo; HsAdminPersonRepository personRepo;
@Autowired @Autowired
RbacRoleRepository roleRepo; RawRbacRoleRepository rawRoleRepo;
@Autowired @Autowired
RbacGrantRepository grantRepo; RawRbacGrantRepository rawGrantRepo;
@Autowired @Autowired
EntityManager em; EntityManager em;
@ -93,8 +94,8 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest {
// given // given
context("drew@hostsharing.org"); context("drew@hostsharing.org");
final var count = personRepo.count(); final var count = personRepo.count();
final var initialRoleCount = roleRepo.findAll().size(); final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
final var initialGrantCount = grantRepo.findAll().size(); final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
// when // when
attempt(em, () -> personRepo.save( attempt(em, () -> personRepo.save(
@ -102,17 +103,24 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest {
).assumeSuccessful(); ).assumeSuccessful();
// then // then
final var roles = roleRepo.findAll(); assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(
assertThat(roleNamesOf(roles)).containsAll(List.of( Array.from(
"hs_admin_person#anothernewperson.owner", initialRoleNames,
"hs_admin_person#anothernewperson.tenant")); "hs_admin_person#anothernewperson.owner",
assertThat(roles.size()).as("invalid number of roles created") "hs_admin_person#anothernewperson.admin",
.isEqualTo(initialRoleCount + 2); "hs_admin_person#anothernewperson.tenant"
final var grants = grantRepo.findAll(); ));
assertThat(grantDisplaysOf(grants)).containsAll(List.of( assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(
"{ grant assumed role hs_admin_person#anothernewperson.owner to user drew@hostsharing.org by role global#global.admin }")); Array.from(
assertThat(grants.size()).as("invalid number of grants created") initialGrantNames,
.isEqualTo(initialGrantCount + 1); "{ 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) { private void assertThatPersonIsPersisted(final HsAdminPersonEntity saved) {
@ -137,8 +145,8 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest {
result, result,
"Peter, Smith", "Peter, Smith",
"Rockshop e.K.", "Rockshop e.K.",
"Ostfriesische Stahlhandel OHG", "Ostfriesische Kuhhandel OHG",
"Erbengemeinschaft Bessler"); "Erben Bessler");
} }
@Test @Test
@ -231,25 +239,25 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest {
public void deletingAPersonAlsoDeletesRelatedRolesAndGrants() { public void deletingAPersonAlsoDeletesRelatedRolesAndGrants() {
// given // given
context("drew@hostsharing.org", null); context("drew@hostsharing.org", null);
final var initialRoleCount = roleRepo.findAll().size(); final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
final var initialGrantCount = grantRepo.findAll().size(); final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
final var givenPerson = givenSomeTemporaryPerson("drew@hostsharing.org"); final var givenPerson = givenSomeTemporaryPerson("drew@hostsharing.org");
assumeThat(roleRepo.findAll().size()).as("unexpected number of roles created") assumeThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
.isEqualTo(initialRoleCount + 2); .isEqualTo(initialRoleNames.size() + 3);
assumeThat(grantRepo.findAll().size()).as("unexpected number of grants created") assumeThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
.isEqualTo(initialGrantCount + 1); .isEqualTo(initialGrantNames.size() + 7);
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("drew@hostsharing.org", null); context("drew@hostsharing.org", null);
personRepo.deleteByUuid(givenPerson.getUuid()); return personRepo.deleteByUuid(givenPerson.getUuid());
}).assumeSuccessful(); });
// then // then
assertThat(roleRepo.findAll().size()).as("invalid number of roles deleted") result.assertSuccessful();
.isEqualTo(initialRoleCount); assertThat(result.returnedValue()).isEqualTo(1);
assertThat(grantRepo.findAll().size()).as("invalid number of grants revoked") assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(initialRoleNames));
.isEqualTo(initialGrantCount); assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.from(initialGrantNames));
} }
} }
@ -258,7 +266,7 @@ class HsAdminPersonRepositoryIntegrationTest extends ContextBasedTest {
context("alex@hostsharing.net", null); context("alex@hostsharing.net", null);
final var result = personRepo.findPersonByOptionalNameLike("some temporary person"); final var result = personRepo.findPersonByOptionalNameLike("some temporary person");
result.forEach(tempPerson -> { result.forEach(tempPerson -> {
System.out.println("DELETING person: " + tempPerson.getDisplayName()); System.out.println("DELETING temporary person: " + tempPerson.getDisplayName());
personRepo.deleteByUuid(tempPerson.getUuid()); personRepo.deleteByUuid(tempPerson.getUuid());
}); });
} }

View File

@ -1,8 +1,12 @@
package net.hostsharing.test; 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, * Java has List.of(...), Set.of(...) and Map.of(...) all with varargs parameter,
* but no Array.of(...). Here it is. * but no Array.of(...). Here it is.
*/ */
public class Array { public class Array {
@ -10,4 +14,17 @@ public class Array {
public static <E> E[] of(E... elements) { public static <E> E[] of(E... elements) {
return elements; return elements;
} }
public static String[] from(final List<String> 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);
}
} }