1
0

RBAC generator with conditional grants used for REPRESENTATIVE-Relation (#33)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/33
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-04-08 11:16:06 +02:00
parent 896968e110
commit 44ff30c54a
29 changed files with 567 additions and 375 deletions

View File

@@ -186,13 +186,13 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
"{ grant perm:debitor#D-1000122:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to role:global#global:ADMIN by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to role:person#FirstGmbH:ADMIN by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to user:superuser-alex@hostsharing.net by relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER and assume }",
// admin
"{ grant perm:debitor#D-1000122:UPDATE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:UPDATE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:person#FirstGmbH:ADMIN by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }",
// agent
@@ -208,7 +208,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
"{ grant role:person#FirstGmbH:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }",
"{ grant role:person#FourtheG:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:contact#fourthcontact:ADMIN by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:person#FourtheG:ADMIN by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT by system and assume }",
null));

View File

@@ -134,6 +134,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
"{ grant perm:membership#M-1000117:SELECT to role:membership#M-1000117:AGENT by system and assume }",
"{ grant role:membership#M-1000117:AGENT to role:membership#M-1000117:ADMIN by system and assume }",
// referrer
"{ grant role:membership#M-1000117:AGENT to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:membership#M-1000117:AGENT by system and assume }",

View File

@@ -218,23 +218,6 @@ public class ImportOfficeData extends ContextBasedTest {
}
}
@Test
@Order(1021)
void buildDebitorRelations() {
debitors.forEach( (id, debitor) -> {
final var debitorRel = HsOfficeRelationEntity.builder()
.type(HsOfficeRelationType.DEBITOR)
.anchor(debitor.getPartner().getPartnerRel().getHolder())
.holder(debitor.getPartner().getPartnerRel().getHolder()) // just 1 debitor/partner in legacy hsadmin
// FIXME .contact()
.build();
if (debitorRel.getAnchor() != null && debitorRel.getHolder() != null &&
debitorRel.getContact() != null ) {
relations.put(relationId++, debitorRel);
}
});
}
@Test
@Order(1029)
void verifyContacts() {
@@ -292,29 +275,25 @@ public class ImportOfficeData extends ContextBasedTest {
{
2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000002=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000003=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000004=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
2000005=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000007=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000008=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000009=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
2000010=rel(anchor='null null, null', type='DEBITOR'),
2000011=rel(anchor='null null, null', type='DEBITOR'),
2000012=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000013=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000014=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
2000015=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000016=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000017=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000018=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000019=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000020=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000021=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
2000022=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000023=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000024=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000003=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
2000004=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000005=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
2000007=rel(anchor='null null, null', type='DEBITOR'),
2000008=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000009=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000010=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
2000011=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000012=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000013=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000014=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000015=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000016=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000017=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
2000018=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000019=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000020=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
}
""");
}
@@ -425,14 +404,33 @@ public class ImportOfficeData extends ContextBasedTest {
}
@Test
@Order(2009)
@Order(3001)
void removeSelfRepresentativeRelations() {
assumeThatWeAreImportingControlledTestData();
// this happens if a natural person is marked as 'contractual' for itself
final var idsToRemove = new HashSet<Integer>();
relations.forEach( (id, r) -> {
if (r.getHolder() == r.getAnchor() ) {
idsToRemove.add(id);
}
});
// remove self-representatives
idsToRemove.forEach(id -> {
System.out.println("removing self representative relation: " + relations.get(id).toString());
relations.remove(id);
});
}
@Test
@Order(3002)
void removeEmptyRelations() {
assumeThatWeAreImportingControlledTestData();
// avoid a error when persisting the deliberately invalid partner entry #99
final var idsToRemove = new HashSet<Integer>();
relations.forEach( (id, r) -> {
// such a record
if (r.getContact() == null || r.getContact().getLabel() == null ||
r.getHolder() == null || r.getHolder().getPersonType() == null ) {
idsToRemove.add(id);
@@ -447,7 +445,7 @@ public class ImportOfficeData extends ContextBasedTest {
}
@Test
@Order(2002)
@Order(3003)
void removeEmptyPartners() {
assumeThatWeAreImportingControlledTestData();
@@ -471,7 +469,7 @@ public class ImportOfficeData extends ContextBasedTest {
}
@Test
@Order(2003)
@Order(3004)
void removeEmptyDebitors() {
assumeThatWeAreImportingControlledTestData();
@@ -490,7 +488,7 @@ public class ImportOfficeData extends ContextBasedTest {
}
@Test
@Order(3000)
@Order(9000)
@Commit
void persistEntities() {
@@ -516,6 +514,7 @@ public class ImportOfficeData extends ContextBasedTest {
relations.forEach(this::persist);
}).assertSuccessful();
System.out.println("persisting " + partners.size() + " partners");
jpaAttempt.transacted(() -> {
context(rbacSuperuser);
partners.forEach((id, partner) -> {
@@ -533,7 +532,7 @@ public class ImportOfficeData extends ContextBasedTest {
context(rbacSuperuser);
debitors.forEach((id, debitor) -> {
debitor.setDebitorRel(em.merge(debitor.getDebitorRel()));
em.persist(debitor);
persist(id, debitor);
});
}).assertSuccessful();
@@ -721,7 +720,6 @@ public class ImportOfficeData extends ContextBasedTest {
null, // will be set in contacts import
null // will beset in contacts import
);
relations.put(relationId++, debitorRel);
final var debitor = HsOfficeDebitorEntity.builder()
.debitorNumberSuffix("00")

View File

@@ -10,7 +10,6 @@ import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectRepository;
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;
@@ -25,13 +24,13 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.distinctGrantDisplaysOf;
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectEntity.objectDisplaysOf;
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.distinctRoleNamesOf;
import static net.hostsharing.test.Array.fromFormatted;
import static net.hostsharing.test.Array.from;
import static net.hostsharing.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat;
@@ -130,7 +129,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
}).assertSuccessful();
// then
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(from(
initialRoleNames,
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:OWNER",
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:ADMIN",
@@ -140,44 +139,43 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
.map(s -> s.replace("ErbenBesslerMelBessler", "EBess"))
.map(s -> s.replace("fourthcontact", "4th"))
.map(s -> s.replace("hs_office_", ""))
.containsExactlyInAnyOrder(distinct(fromFormatted(
.containsExactlyInAnyOrder(distinct(from(
initialGrantNames,
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
// permissions on partner
"{ grant perm:partner#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant perm:partner#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
"{ grant perm:partner#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant perm:partner#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
"{ grant perm:partner#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant perm:partner#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
// permissions on partner-details
"{ grant perm:partner_details#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant perm:partner_details#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
"{ grant perm:partner_details#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
"{ grant perm:partner_details#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
"{ grant perm:partner_details#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
"{ grant perm:partner_details#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
// permissions on partner-relation
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
// relation owner
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:global#global:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:global#global:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }",
// relation admin
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:person#HostsharingeG:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:person#HostsharingeG:ADMIN by system and assume }",
// relation agent
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:person#EBess:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:person#EBess:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
// relation tenant
"{ grant role:contact#4th:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant role:person#EBess:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant role:person#HostsharingeG:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:contact#4th:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:person#EBess:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
"{ grant role:contact#4th:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant role:person#EBess:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant role:person#HostsharingeG:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:contact#4th:ADMIN by system and assume }",
"{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
null)));
}
@@ -411,9 +409,9 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
public void deletingAPartnerAlsoDeletesRelatedRolesAndGrants() {
// given
context("superuser-alex@hostsharing.net");
final var initialObjects = Array.from(objectDisplaysOf(rawObjectRepo.findAll()));
final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll()));
final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
final var initialObjects = from(objectDisplaysOf(rawObjectRepo.findAll()));
final var initialRoleNames = from(distinctRoleNamesOf(rawRoleRepo.findAll()));
final var initialGrantNames = from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
final var givenPartner = givenSomeTemporaryHostsharingPartner(20034, "Erben Bessler", "twelfth");
// when
@@ -499,8 +497,6 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
private String[] distinct(final String[] strings) {
// TODO: alternatively cleanup all rbac objects in @AfterEach?
final var set = new HashSet<String>();
set.addAll(List.of(strings));
return set.toArray(new String[0]);
return Arrays.stream(strings).filter(Objects::nonNull).distinct().toList().toArray(new String[0]);
}
}

View File

@@ -362,7 +362,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
assertThat(givenRelation.getContact().getLabel()).isEqualTo("seventh contact");
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
final var location = RestAssured // @formatter:off
RestAssured // @formatter:off
.given()
.header("current-user", "superuser-alex@hostsharing.net")
.contentType(ContentType.JSON)

View File

@@ -140,9 +140,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
"{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to role:hs_office_person#BesslerBert:ADMIN by system and assume }",
"{ grant role:hs_office_person#ErbenBesslerMelBessler:OWNER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }",
"{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }",
@@ -153,8 +154,6 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
// REPRESENTATIVE holder person -> (represented) anchor person
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }",
"{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_person#BesslerBert:ADMIN by system and assume }",
null)
);
}
@@ -217,10 +216,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
context("superuser-alex@hostsharing.net");
final var givenRelation = givenSomeTemporaryRelationBessler(
"Bert", "fifth contact");
assertThatRelationActuallyInDatabase(givenRelation);
assertThatRelationIsVisibleForUserWithRole(
givenRelation,
"hs_office_person#ErbenBesslerMelBessler:ADMIN");
assertThatRelationActuallyInDatabase(givenRelation);
context("superuser-alex@hostsharing.net");
final var givenContact = contactRepo.findContactByOptionalLabelLike("sixth contact").stream().findFirst().orElseThrow();
@@ -249,19 +248,19 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
}
@Test
public void holderAdmin_canNotUpdateRelatedRelation() {
public void relationAgent_canSelectButNotUpdateRelatedRelation() {
// given
context("superuser-alex@hostsharing.net");
final var givenRelation = givenSomeTemporaryRelationBessler(
"Anita", "eighth");
assertThatRelationIsVisibleForUserWithRole(
givenRelation,
"hs_office_person#BesslerAnita:ADMIN");
"hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT");
assertThatRelationActuallyInDatabase(givenRelation);
// when
final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita:ADMIN");
context("superuser-alex@hostsharing.net", "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT");
givenRelation.setContact(null);
return relationRepo.save(givenRelation);
});

View File

@@ -17,7 +17,6 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import jakarta.persistence.*;
import java.lang.reflect.Method;
import java.util.*;
import static java.lang.System.out;
@@ -272,12 +271,11 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
/**
* Generates a diagram of the RBAC-Grants to the current subjects (user or assumed roles).
*/
protected void generateRbacDiagramForCurrentSubjects(final EnumSet<RbacGrantsDiagramService.Include> include) {
final var title = testInfo.getTestMethod().map(Method::getName).orElseThrow();
protected void generateRbacDiagramForCurrentSubjects(final EnumSet<RbacGrantsDiagramService.Include> include, final String name) {
RbacGrantsDiagramService.writeToFile(
title,
name,
diagramService.allGrantsToCurrentUser(include),
"doc/" + title + ".md"
"doc/temp/" + name + ".md"
);
}