1
0

assuming-long-roleidnames + object-uuid-based-rolenames (#139)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/139
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-12-30 10:00:12 +01:00
parent d89b4b4992
commit 9debaa1fc0
26 changed files with 301 additions and 127 deletions

View File

@@ -97,7 +97,7 @@ class HsOfficeBankAccountControllerAcceptanceTest extends ContextBasedTestWithCl
"bic": "INGDDEFF"
},
{
"holder": "Second e.K.",
"holder": "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.",
"iban": "DE02100500000054540402",
"bic": "BELADEBE"
},

View File

@@ -147,7 +147,7 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC
"Mel Bessler",
"Paul Winkler",
"Peter Smith",
"Second e.K.",
"Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.",
"Third OHG");
}

View File

@@ -227,8 +227,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
},
{
"debitorRel": {
"anchor": {"tradeName": "Second e.K."},
"holder": {"tradeName": "Second e.K."},
"anchor": {"tradeName": "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K."},
"holder": {"tradeName": "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K."},
"type": "DEBITOR",
"contact": {
"emailAddresses": { "main": "contact-admin@secondcontact.example.com" }
@@ -240,7 +240,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
"partnerNumber": "P-10002",
"partnerRel": {
"anchor": {"tradeName": "Hostsharing eG"},
"holder": {"tradeName": "Second e.K."},
"holder": {"tradeName": "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K."},
"type": "PARTNER",
"contact": {
"emailAddresses": { "main": "contact-admin@secondcontact.example.com" }

View File

@@ -240,7 +240,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
allTheseDebitorsAreReturned(
result,
"debitor(D-1000111: rel(anchor='LP First GmbH', type='DEBITOR', holder='LP First GmbH'), fir)",
"debitor(D-1000212: rel(anchor='LP Second e.K.', type='DEBITOR', holder='LP Second e.K.'), sec)",
"debitor(D-1000212: rel(anchor='LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.', type='DEBITOR', holder='LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.'), sec)",
"debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
}

View File

@@ -411,7 +411,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
// and an ex-partner-relation got created
final var anchorpartnerPersonUUid = givenPartner.getPartnerRel().getAnchor().getUuid();
assertThat(relationRepo.findRelationRelatedToPersonUuidAndRelationType(anchorpartnerPersonUUid, EX_PARTNER))
assertThat(relationRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(anchorpartnerPersonUUid, EX_PARTNER, null, null, null))
.map(HsOfficeRelation::toShortString)
.contains("rel(anchor='LP Hostsharing eG', type='EX_PARTNER', holder='UF Erben Bessler')");
}

View File

@@ -199,7 +199,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
allThesePartnersAreReturned(
result,
"partner(P-10001: LP First GmbH, first contact)",
"partner(P-10002: LP Second e.K., second contact)",
"partner(P-10002: LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K., second contact)",
"partner(P-10003: IF Third OHG, third contact)",
"partner(P-10004: LP Fourth eG, fourth contact)",
"partner(P-10010: NP Smith, Peter, sixth contact)");

View File

@@ -143,7 +143,7 @@ class HsOfficePersonRbacRepositoryIntegrationTest extends ContextBasedTestWithCl
allThesePersonsAreReturned(
result,
"NP Smith, Peter",
"LP Second e.K.",
"LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.",
"IF Third OHG",
"UF Erben Bessler");
}
@@ -171,10 +171,10 @@ class HsOfficePersonRbacRepositoryIntegrationTest extends ContextBasedTestWithCl
context("superuser-alex@hostsharing.net", null);
// when
final var result = personRbacRepo.findPersonByOptionalNameLike("Second");
final var result = personRbacRepo.findPersonByOptionalNameLike("Peter Smith - The Second Hand%");
// then
exactlyThesePersonsAreReturned(result, "Second e.K.");
exactlyThesePersonsAreReturned(result, "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.");
}
@Test
@@ -272,7 +272,7 @@ class HsOfficePersonRbacRepositoryIntegrationTest extends ContextBasedTestWithCl
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, Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K., null]",
"[creating person test-data, hs_office.person, INSERT, Third OHG, null]");
}

View File

@@ -126,7 +126,7 @@ class HsOfficePersonRealRepositoryIntegrationTest extends ContextBasedTestWithCl
allThesePersonsAreReturned(
result,
"NP Smith, Peter",
"LP Second e.K.",
"LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.",
"IF Third OHG",
"UF Erben Bessler");
}
@@ -141,10 +141,10 @@ class HsOfficePersonRealRepositoryIntegrationTest extends ContextBasedTestWithCl
context("selfregistered-user-drew@hostsharing.org");
// when
final var result = personRealRepo.findPersonByOptionalNameLike("Second");
final var result = personRealRepo.findPersonByOptionalNameLike("Peter Smith - The Second Hand%");
// then
exactlyThesePersonsAreReturned(result, "Second e.K.");
exactlyThesePersonsAreReturned(result, "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.");
}
}
@@ -164,7 +164,7 @@ class HsOfficePersonRealRepositoryIntegrationTest extends ContextBasedTestWithCl
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, Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K., null]",
"[creating person test-data, hs_office.person, INSERT, Third OHG, null]");
}

View File

@@ -47,13 +47,13 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith
final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith");
// when
final var result = relationRealRepo.findRelationRelatedToPersonUuidAndRelationType(personUuid, null);
final var result = relationRealRepo.findRelationRelatedToPersonUuid(personUuid);
// then
context("superuser-alex@hostsharing.net"); // just to be able to access RBAc-entities persons+contact
exactlyTheseRelationsAreReturned(
result,
"rel(anchor='LP Second e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
"rel(anchor='LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
"rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Smith, Peter', contact='sixth contact')",
"rel(anchor='NP Smith, Peter', type='DEBITOR', holder='NP Smith, Peter', contact='third contact')",
"rel(anchor='IF Third OHG', type='SUBSCRIBER', mark='members-announce', holder='NP Smith, Peter', contact='third contact')"
@@ -66,13 +66,13 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith
final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith");
// when:
final var result = relationRealRepo.findRelationRelatedToPersonUuidAndRelationType(personUuid, REPRESENTATIVE);
final var result = relationRealRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(personUuid, REPRESENTATIVE, null, null, null);
// then:
context("superuser-alex@hostsharing.net"); // just to be able to access RBAc-entities persons+contact
exactlyTheseRelationsAreReturned(
result,
"rel(anchor='LP Second e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')"
"rel(anchor='LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')"
);
}
}

View File

@@ -90,7 +90,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
},
{
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
"holder": { "personType": "LEGAL_PERSON", "tradeName": "Second e.K.", "givenName": "Peter", "familyName": "Smith" },
"holder": { "personType": "LEGAL_PERSON", "tradeName": "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.", "givenName": "Peter", "familyName": "Smith" },
"type": "PARTNER",
"mark": null,
"contact": { "caption": "second contact" }

View File

@@ -3,10 +3,11 @@ package net.hostsharing.hsadminng.hs.office.relation;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealRepository;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository;
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
import net.hostsharing.hsadminng.lambda.Reducer;
import net.hostsharing.hsadminng.mapper.Array;
import net.hostsharing.hsadminng.rbac.grant.RawRbacGrantRepository;
import net.hostsharing.hsadminng.rbac.role.RawRbacRoleRepository;
import net.hostsharing.hsadminng.mapper.Array;
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;
@@ -30,17 +31,20 @@ import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@Import( { Context.class, JpaAttempt.class })
@Import({ Context.class, JpaAttempt.class })
class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
@Autowired
HsOfficeRelationRbacRepository relationRbacRepo;
@Autowired
HsOfficeRelationRealRepository relationRealRepo;
@Autowired
HsOfficePersonRealRepository personRepo;
@Autowired
HsOfficeContactRealRepository contactrealRepo;
HsOfficeContactRealRepository contactRealRepo;
@Autowired
RawRbacRoleRepository rawRoleRepo;
@@ -57,6 +61,29 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
@MockBean
HttpServletRequest request;
@Nested
class AssumeRelationRole {
// TODO.test: these tests would be better placed in the rbac module,
// but for this we need an extra long object-idname in the rbac test data
@Test
public void testHostsharingAdminCanAssumeRelationRoleWithLongIdName() {
context(
"superuser-alex@hostsharing.net",
"hs_office.relation#HostsharingeG-with-PARTNER-PeterSmith-TheSecondHandandThriftStores-n-Shippinge.K.SmithPeter:AGENT");
}
@Test
public void testHostsharingAdminCanAssumeRelationRoleWithUuid() {
final var relationUuid = relationRealRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(
null, HsOfficeRelationType.PARTNER, null, "%Second%", null)
.stream().reduce(Reducer::toSingleElement).orElseThrow().getUuid();
context("superuser-alex@hostsharing.net", "hs_office.relation#" + relationUuid + ":AGENT");
}
}
@Nested
class CreateRelation {
@@ -64,6 +91,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
public void testHostsharingAdmin_withoutAssumedRole_canCreateNewRelation() {
// given
context("superuser-alex@hostsharing.net");
final var count = relationRbacRepo.count();
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream()
.filter(p -> p.getPersonType() == UNINCORPORATED_FIRM)
@@ -71,20 +99,21 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Paul").stream()
.filter(p -> p.getPersonType() == NATURAL_PERSON)
.findFirst().orElseThrow();
final var givenContact = contactrealRepo.findContactByOptionalCaptionLike("fourth contact").stream()
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("fourth contact").stream()
.findFirst().orElseThrow();
// when
final var result = attempt(em, () -> {
final var newRelation = HsOfficeRelationRbacEntity.builder()
.anchor(givenAnchorPerson)
.holder(givenHolderPerson)
.type(HsOfficeRelationType.SUBSCRIBER)
.mark("operations-announce")
.contact(givenContact)
.build();
return toCleanup(relationRbacRepo.save(newRelation));
});
final var result = attempt(
em, () -> {
final var newRelation = HsOfficeRelationRbacEntity.builder()
.anchor(givenAnchorPerson)
.holder(givenHolderPerson)
.type(HsOfficeRelationType.SUBSCRIBER)
.mark("operations-announce")
.contact(givenContact)
.build();
return toCleanup(relationRbacRepo.save(newRelation));
});
// then
result.assertSuccessful();
@@ -93,7 +122,8 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
assertThat(relationRbacRepo.count()).isEqualTo(count + 1);
final var stored = relationRbacRepo.findByUuid(result.returnedValue().getUuid());
assertThat(stored).isNotEmpty().map(HsOfficeRelation::toString).get()
.isEqualTo("rel(anchor='UF Erben Bessler', type='SUBSCRIBER', mark='operations-announce', holder='NP Winkler, Paul', contact='fourth contact')");
.isEqualTo(
"rel(anchor='UF Erben Bessler', type='SUBSCRIBER', mark='operations-announce', holder='NP Winkler, Paul', contact='fourth contact')");
}
@Test
@@ -104,23 +134,24 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll());
// when
attempt(em, () -> {
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream()
.filter(p -> p.getPersonType() == UNINCORPORATED_FIRM)
.findFirst().orElseThrow();
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Bert").stream()
.filter(p -> p.getPersonType() == NATURAL_PERSON)
.findFirst().orElseThrow();
final var givenContact = contactrealRepo.findContactByOptionalCaptionLike("fourth contact").stream()
.findFirst().orElseThrow();
final var newRelation = HsOfficeRelationRbacEntity.builder()
.anchor(givenAnchorPerson)
.holder(givenHolderPerson)
.type(HsOfficeRelationType.REPRESENTATIVE)
.contact(givenContact)
.build();
return toCleanup(relationRbacRepo.save(newRelation));
});
attempt(
em, () -> {
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream()
.filter(p -> p.getPersonType() == UNINCORPORATED_FIRM)
.findFirst().orElseThrow();
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Bert").stream()
.filter(p -> p.getPersonType() == NATURAL_PERSON)
.findFirst().orElseThrow();
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("fourth contact").stream()
.findFirst().orElseThrow();
final var newRelation = HsOfficeRelationRbacEntity.builder()
.anchor(givenAnchorPerson)
.holder(givenHolderPerson)
.type(HsOfficeRelationType.REPRESENTATIVE)
.contact(givenContact)
.build();
return toCleanup(relationRbacRepo.save(newRelation));
});
// then
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
@@ -180,7 +211,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
allTheseRelationsAreReturned(
result,
"rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Smith, Peter', contact='sixth contact')",
"rel(anchor='LP Second e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
"rel(anchor='LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
"rel(anchor='IF Third OHG', type='SUBSCRIBER', mark='members-announce', holder='NP Smith, Peter', contact='third contact')");
}
@@ -193,12 +224,17 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
.findFirst().orElseThrow();
// when:
final var result = relationRbacRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(person.getUuid(), null, null, null, null);
final var result = relationRbacRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(
person.getUuid(),
null,
null,
null,
null);
// then:
exactlyTheseRelationsAreReturned(
result,
"rel(anchor='LP Second e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
"rel(anchor='LP Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
"rel(anchor='IF Third OHG', type='SUBSCRIBER', mark='members-announce', holder='NP Smith, Peter', contact='third contact')",
"rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Smith, Peter', contact='sixth contact')",
"rel(anchor='NP Smith, Peter', type='DEBITOR', holder='NP Smith, Peter', contact='third contact')");
@@ -219,7 +255,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
givenRelation,
"hs_office.person#ErbenBesslerMelBessler:ADMIN");
context("superuser-alex@hostsharing.net");
final var givenContact = contactrealRepo.findContactByOptionalCaptionLike("sixth contact").stream().findFirst().orElseThrow();
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("sixth contact")
.stream()
.findFirst()
.orElseThrow();
// when
final var result = jpaAttempt.transacted(() -> {
@@ -258,13 +297,16 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
// when
final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net", "hs_office.relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT");
context(
"superuser-alex@hostsharing.net",
"hs_office.relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT");
givenRelation.setContact(null);
return relationRbacRepo.save(givenRelation);
});
// then
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
result.assertExceptionWithRootCauseMessage(
JpaSystemException.class,
"[403] Subject ", " is not allowed to update hs_office.relation uuid");
}
@@ -287,7 +329,8 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
});
// then
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
result.assertExceptionWithRootCauseMessage(
JpaSystemException.class,
"[403] Subject ", " is not allowed to update hs_office.relation uuid");
}
@@ -397,7 +440,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
select currentTask, targetTable, targetOp, targetdelta->>'mark'
from base.tx_journal_v
where targettable = 'hs_office.relation';
""");
""");
// when
@SuppressWarnings("unchecked") final List<Object[]> customerLogEntries = query.getResultList();
@@ -412,7 +455,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
context("superuser-alex@hostsharing.net");
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0);
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike(holderPerson).get(0);
final var givenContact = contactrealRepo.findContactByOptionalCaptionLike(contact).get(0);
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike(contact).get(0);
final var newRelation = HsOfficeRelationRbacEntity.builder()
.type(HsOfficeRelationType.REPRESENTATIVE)
.anchor(givenAnchorPerson)

View File

@@ -83,7 +83,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
},
{
"debitor": { "debitorNumber": "D-1000212" },
"bankAccount": { "holder": "Second e.K." },
"bankAccount": { "holder": "Peter Smith - The Second Hand and Thrift Stores-n-Shipping e.K." },
"reference": "ref-10002-12",
"validFrom": "2022-10-01",
"validTo": "2026-12-31"

View File

@@ -32,7 +32,7 @@ class ContextUnitTest {
cast(:currentTask as varchar(127)),
cast(:currentRequest as text),
cast(:currentSubject as varchar(63)),
cast(:assumedRoles as varchar(1023)));
cast(:assumedRoles as text));
""";
@Nested

View File

@@ -68,7 +68,7 @@ class RbacRoleRepositoryIntegrationTest {
}
@Test
public void globalAdmin_withAssumedglobalAdminRole_canViewAllRbacRoles() {
public void globalAdmin_withAssumedGlobalAdminRole_canViewAllRbacRoles() {
given:
context.define("superuser-alex@hostsharing.net", "rbac.global#global:ADMIN");