bugfix/only-one-partner-per-person (#143)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: #143
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig 2025-01-07 09:30:25 +01:00
parent b3f1171561
commit 6b09ad0003
14 changed files with 100 additions and 54 deletions

View File

@ -13,10 +13,16 @@ if [ "$1" == "--trace" ]; then
} }
function doCurl() { function doCurl() {
set -x set -x
curl --fail-with-body \ if [ -z "$HSADMINNG_CAS_ASSUME" ]; then
--header "Authorization: $HSADMINNG_CAS_TICKET" \ curl --fail-with-body \
--header "assumed-roles: $HSADMINNG_CAS_ASSUME" \ --header "Authorization: $HSADMINNG_CAS_TICKET" \
"$@" "$@"
else
curl --fail-with-body \
--header "Authorization: $HSADMINNG_CAS_TICKET" \
--header "assumed-roles: $HSADMINNG_CAS_ASSUME" \
"$@"
fi
set +x set +x
} }
shift shift

View File

@ -45,13 +45,13 @@ public class CasAuthenticator implements Authenticator {
private String casValidation(final HttpServletRequest httpRequest) private String casValidation(final HttpServletRequest httpRequest)
throws SAXException, IOException, ParserConfigurationException { throws SAXException, IOException, ParserConfigurationException {
System.err.println("CasAuthenticator.casValidation using CAS-server: " + casServerUrl);
final var ticket = httpRequest.getHeader("Authorization"); final var ticket = httpRequest.getHeader("Authorization");
final var url = casServerUrl + "/p3/serviceValidate" + final var url = casServerUrl + "/p3/serviceValidate" +
"?service=" + serviceUrl + "?service=" + serviceUrl +
"&ticket=" + ticket; "&ticket=" + ticket;
System.err.println("CasAuthenticator.casValidation using URL: " + url);
final var response = restTemplate.getForObject(url, String.class); final var response = restTemplate.getForObject(url, String.class);
final var doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() final var doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()

View File

@ -88,9 +88,9 @@ public class HsOfficeDebitorEntity implements BaseEntity<HsOfficeDebitorEntity>,
( (
SELECT DISTINCT partner.uuid SELECT DISTINCT partner.uuid
FROM hs_office.partner_rv partner FROM hs_office.partner_rv partner
JOIN hs_office.relation_rv dRel JOIN hs_office.relation dRel
ON dRel.uuid = debitorreluuid AND dRel.type = 'DEBITOR' ON dRel.uuid = debitorreluuid AND dRel.type = 'DEBITOR'
JOIN hs_office.relation_rv pRel JOIN hs_office.relation pRel
ON pRel.uuid = partner.partnerRelUuid AND pRel.type = 'PARTNER' ON pRel.uuid = partner.partnerRelUuid AND pRel.type = 'PARTNER'
WHERE pRel.holderUuid = dRel.anchorUuid WHERE pRel.holderUuid = dRel.anchorUuid
) )

View File

@ -9,6 +9,7 @@ import lombok.experimental.FieldNameConstants;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.errors.DisplayAs; import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.persistence.BaseEntity; import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.role.WithRoleId;
import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable; import net.hostsharing.hsadminng.repr.Stringifyable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -30,7 +31,7 @@ import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@SuperBuilder(toBuilder = true) @SuperBuilder(toBuilder = true)
@FieldNameConstants @FieldNameConstants
@DisplayAs("Person") @DisplayAs("Person")
public class HsOfficePerson<T extends HsOfficePerson<?> & BaseEntity<?>> implements BaseEntity<T>, Stringifyable { public class HsOfficePerson<T extends HsOfficePerson<?> & BaseEntity<?>> implements BaseEntity<T>, Stringifyable, WithRoleId {
private static Stringify<HsOfficePerson> toString = stringify(HsOfficePerson.class, "person") private static Stringify<HsOfficePerson> toString = stringify(HsOfficePerson.class, "person")
.withProp(Fields.personType, HsOfficePerson::getPersonType) .withProp(Fields.personType, HsOfficePerson::getPersonType)

View File

@ -6,6 +6,7 @@ import lombok.experimental.SuperBuilder;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
import net.hostsharing.hsadminng.persistence.BaseEntity; import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.role.WithRoleId;
import net.hostsharing.hsadminng.repr.Stringify; import net.hostsharing.hsadminng.repr.Stringify;
import net.hostsharing.hsadminng.repr.Stringifyable; import net.hostsharing.hsadminng.repr.Stringifyable;
@ -22,7 +23,7 @@ import static net.hostsharing.hsadminng.repr.Stringify.stringify;
@Setter @Setter
@SuperBuilder(toBuilder = true) @SuperBuilder(toBuilder = true)
@FieldNameConstants @FieldNameConstants
public class HsOfficeRelation implements BaseEntity<HsOfficeRelation>, Stringifyable { public class HsOfficeRelation implements BaseEntity<HsOfficeRelation>, Stringifyable, WithRoleId {
private static Stringify<HsOfficeRelation> toString = stringify(HsOfficeRelation.class, "rel") private static Stringify<HsOfficeRelation> toString = stringify(HsOfficeRelation.class, "rel")
.withProp(Fields.anchor, HsOfficeRelation::getAnchor) .withProp(Fields.anchor, HsOfficeRelation::getAnchor)

View File

@ -0,0 +1,20 @@
package net.hostsharing.hsadminng.rbac.role;
import jakarta.persistence.Table;
import java.util.UUID;
public interface WithRoleId {
UUID getUuid();
/**
* @return the RBAC-Role-Id of the given `rbacRoleType` for this entity instance.
*/
default String roleId(final RbacRoleType rbacRoleType) {
if ( getUuid() == null ) {
throw new IllegalStateException("UUID missing => role can't be determined");
}
final Table tableAnnot = getClass().getAnnotation(Table.class);
final var qualifiedTableName = tableAnnot.schema() + "." + tableAnnot.name();
return qualifiedTableName + "#" + getUuid() + ":" + rbacRoleType.name();
}
}

View File

@ -251,7 +251,7 @@ begin
execute sql into uuid; execute sql into uuid;
exception exception
when others then when others then
raise exception 'function %_uuid_by_id_name(''%'') failed: %, SQLSTATE: %. If it could not be found, add identity view support to %\nSQL:%', raise exception 'function %_uuid_by_id_name(''%'') failed: %, SQLSTATE: %. If the function itself could not be found, add identity view support to %\nSQL:%',
objectTable, objectIdName, SQLERRM, SQLSTATE, objectTable, sql; objectTable, objectIdName, SQLERRM, SQLSTATE, objectTable, sql;
end; end;
if uuid is null then if uuid is null then
@ -275,7 +275,7 @@ begin
execute sql into idName; execute sql into idName;
exception exception
when others then when others then
raise exception 'function %_id_name_by_uuid(''%'') failed: %, SQLSTATE: %. If it could not be found, add identity view support to %', raise exception 'function %_id_name_by_uuid(''%'') failed: %, SQLSTATE: %. If the function itself could not be found, add identity view support to %',
objectTable, objectUuid, SQLERRM, SQLSTATE, objectTable; objectTable, objectUuid, SQLERRM, SQLSTATE, objectTable;
end; end;
return idName; return idName;

View File

@ -29,8 +29,24 @@ create table if not exists hs_office.relation
); );
--// --//
-- TODO.impl: unique constraint, to prevent using the same person multiple times as a partner, or better:
-- ( anchorUuid, holderUuid, type) -- ============================================================================
--changeset michael.hoennig:hs-office-relation-unique-constraints endDelimiter:--//
-- ----------------------------------------------------------------------------
CREATE UNIQUE INDEX unique_relation_with_mark
ON hs_office.relation (type, anchorUuid, holderUuid, contactUuid, mark)
WHERE mark IS NOT NULL;
CREATE UNIQUE INDEX unique_relation_without_mark
ON hs_office.relation (type, anchorUuid, holderUuid, contactUuid)
WHERE mark IS NULL;
CREATE UNIQUE INDEX unique_partner_relation
ON hs_office.relation (type, anchorUuid, holderUuid)
WHERE mark IS NULL AND type = 'PARTNER';
--//
-- ============================================================================ -- ============================================================================

View File

@ -100,8 +100,8 @@ do language plpgsql $$
call hs_office.relation_create_test_data('Third OHG', 'DEBITOR', 'Third OHG', 'third contact'); call hs_office.relation_create_test_data('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
call hs_office.relation_create_test_data('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact'); call hs_office.relation_create_test_data('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact');
call hs_office.relation_create_test_data('Fouler', 'REPRESENTATIVE', 'Third OHG', 'third contact'); call hs_office.relation_create_test_data('Fouler', 'REPRESENTATIVE', 'Fourth eG', 'fourth contact');
call hs_office.relation_create_test_data('Third OHG', 'DEBITOR', 'Third OHG', 'third contact'); call hs_office.relation_create_test_data('Fourth eG', 'DEBITOR', 'Fourth eG', 'fourth contact');
call hs_office.relation_create_test_data('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact'); call hs_office.relation_create_test_data('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact');
call hs_office.relation_create_test_data('Smith', 'DEBITOR', 'Smith', 'third contact'); call hs_office.relation_create_test_data('Smith', 'DEBITOR', 'Smith', 'third contact');

View File

@ -170,19 +170,18 @@ public class CsvDataImport extends ContextBasedTest {
} }
public <T extends BaseEntity> T persistViaEM(final Integer id, final T entity) { public <T extends BaseEntity> T persistViaEM(final Integer id, final T entity) {
//System.out.println("persisting #" + entity.hashCode() + ": " + entity); if (em.contains(entity)) {
if (!em.contains(entity)) { return entity;
em.persist(entity); }
try {
em.persist(entity);
em.flush(); // makes it a bit slower, but produces better error messages
System.out.println("persisted #" + id + " as " + entity.getUuid());
return entity;
} catch (final Exception exc) {
System.err.println("persist failed for #" + id + " as " + entity);
throw exc; // for breakpoints
} }
// uncomment for debugging purposes
// try {
// em.flush(); // makes it slow, but produces better error messages
// System.out.println("persisted #" + entity.hashCode() + " as " + entity.getUuid());
// return entity;
// } catch (final Exception exc) {
// throw exc; // for breakpoints
// }
return entity;
} }
@SneakyThrows @SneakyThrows

View File

@ -616,7 +616,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor(); final var givenDebitor = givenSomeTemporaryDebitor();
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("fourth").get(0); final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("tenth").get(0);
final var location = RestAssured // @formatter:off final var location = RestAssured // @formatter:off
.given() .given()
@ -644,7 +644,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
"holder": { "tradeName": "Fourth eG" }, "holder": { "tradeName": "Fourth eG" },
"type": "DEBITOR", "type": "DEBITOR",
"mark": null, "mark": null,
"contact": { "caption": "fourth contact" } "contact": { "caption": "tenth contact" }
}, },
"debitorNumber": "D-10004${debitorNumberSuffix}", "debitorNumber": "D-10004${debitorNumberSuffix}",
"debitorNumberSuffix": "${debitorNumberSuffix}", "debitorNumberSuffix": "${debitorNumberSuffix}",
@ -685,7 +685,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
.matches(debitor -> { .matches(debitor -> {
assertThat(debitor.getDebitorRel().getHolder().getTradeName()) assertThat(debitor.getDebitorRel().getHolder().getTradeName())
.isEqualTo(givenDebitor.getDebitorRel().getHolder().getTradeName()); .isEqualTo(givenDebitor.getDebitorRel().getHolder().getTradeName());
assertThat(debitor.getDebitorRel().getContact().getCaption()).isEqualTo("fourth contact"); assertThat(debitor.getDebitorRel().getContact().getCaption()).isEqualTo("tenth contact");
assertThat(debitor.getVatId()).isEqualTo("VAT222222"); assertThat(debitor.getVatId()).isEqualTo("VAT222222");
assertThat(debitor.getVatCountryCode()).isEqualTo("AA"); assertThat(debitor.getVatCountryCode()).isEqualTo("AA");
assertThat(debitor.isVatBusiness()).isEqualTo(true); assertThat(debitor.isVatBusiness()).isEqualTo(true);
@ -704,7 +704,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
.header("current-subject", "superuser-alex@hostsharing.net") .header("current-subject", "superuser-alex@hostsharing.net")
.header("assumed-roles", "hs_office.contact#fourthcontact:ADMIN") .header("assumed-roles", "hs_office.contact#tenthcontact:ADMIN")
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(""" .body("""
{ {
@ -747,11 +747,11 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
void contactAdminUser_canNotDeleteRelatedDebitor() { void contactAdminUser_canNotDeleteRelatedDebitor() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor(); final var givenDebitor = givenSomeTemporaryDebitor();
assertThat(givenDebitor.getDebitorRel().getContact().getCaption()).isEqualTo("fourth contact"); assertThat(givenDebitor.getDebitorRel().getContact().getCaption()).isEqualTo("tenth contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
.header("current-subject", "contact-admin@fourthcontact.example.com") .header("current-subject", "contact-admin@tenthcontact.example.com")
.port(port) .port(port)
.when() .when()
.delete("http://localhost/api/hs/office/debitors/" + givenDebitor.getUuid()) .delete("http://localhost/api/hs/office/debitors/" + givenDebitor.getUuid())
@ -766,7 +766,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
void normalUser_canNotDeleteUnrelatedDebitor() { void normalUser_canNotDeleteUnrelatedDebitor() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor(); final var givenDebitor = givenSomeTemporaryDebitor();
assertThat(givenDebitor.getDebitorRel().getContact().getCaption()).isEqualTo("fourth contact"); assertThat(givenDebitor.getDebitorRel().getContact().getCaption()).isEqualTo("tenth contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -786,7 +786,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
return jpaAttempt.transacted(() -> { return jpaAttempt.transacted(() -> {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Fourth").get(0).load(); final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Fourth").get(0).load();
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("fourth contact").get(0); final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("tenth contact").get(0);
final var newDebitor = HsOfficeDebitorEntity.builder() final var newDebitor = HsOfficeDebitorEntity.builder()
.debitorNumberSuffix(nextDebitorSuffix()) .debitorNumberSuffix(nextDebitorSuffix())
.billable(true) .billable(true)

View File

@ -33,6 +33,7 @@ import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static net.hostsharing.hsadminng.rbac.role.RbacRoleType.ADMIN;
import static net.hostsharing.hsadminng.rbac.test.EntityList.one; import static net.hostsharing.hsadminng.rbac.test.EntityList.one;
import static net.hostsharing.hsadminng.rbac.grant.RawRbacGrantEntity.distinctGrantDisplaysOf; import static net.hostsharing.hsadminng.rbac.grant.RawRbacGrantEntity.distinctGrantDisplaysOf;
import static net.hostsharing.hsadminng.rbac.role.RawRbacRoleEntity.distinctRoleNamesOf; import static net.hostsharing.hsadminng.rbac.role.RawRbacRoleEntity.distinctRoleNamesOf;
@ -85,7 +86,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
final var count = debitorRepo.count(); final var count = debitorRepo.count();
final var givenPartner = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow(); final var givenPartner = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow();
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH")); final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("first contact")); final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("eleventh contact"));
// when // when
final var result = attempt(em, () -> { final var result = attempt(em, () -> {
@ -119,7 +120,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH")); final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("first contact")); final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("eleventh contact"));
// when // when
final var result = attempt(em, () -> { final var result = attempt(em, () -> {
@ -335,10 +336,11 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fif"); final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fif");
final var originalDebitorRel = givenDebitor.getDebitorRel();
assertThatDebitorIsVisibleForUserWithRole( assertThatDebitorIsVisibleForUserWithRole(
givenDebitor, givenDebitor,
"hs_office.relation#FourtheG-with-DEBITOR-FourtheG:ADMIN", true); givenDebitor.getDebitorRel().roleId(ADMIN), true);
final var givenNewPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First")); final var givenNewPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First"));
final var givenNewBillingPerson = one(personRepo.findPersonByOptionalNameLike("Firby")); final var givenNewBillingPerson = one(personRepo.findPersonByOptionalNameLike("Firby"));
final var givenNewContact = one(contactRealRepo.findContactByOptionalCaptionLike("sixth contact")); final var givenNewContact = one(contactRealRepo.findContactByOptionalCaptionLike("sixth contact"));
@ -371,10 +373,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
// ... partner role was reassigned: // ... partner role was reassigned:
assertThatDebitorIsNotVisibleForUserWithRole( assertThatDebitorIsNotVisibleForUserWithRole(
result.returnedValue(), result.returnedValue(),
"hs_office.relation#FourtheG-with-DEBITOR-FourtheG:ADMIN"); originalDebitorRel.roleId(ADMIN));
assertThatDebitorIsVisibleForUserWithRole( assertThatDebitorIsVisibleForUserWithRole(
result.returnedValue(), result.returnedValue(),
"hs_office.relation#FirstGmbH-with-DEBITOR-FirbySusan:AGENT", true); result.returnedValue().getDebitorRel().roleId(ADMIN), true);
// ... contact role was reassigned: // ... contact role was reassigned:
assertThatDebitorIsNotVisibleForUserWithRole( assertThatDebitorIsNotVisibleForUserWithRole(
@ -397,10 +399,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
public void globalAdmin_canUpdateNullRefundBankAccountToNotNullBankAccountForArbitraryDebitor() { public void globalAdmin_canUpdateNullRefundBankAccountToNotNullBankAccountForArbitraryDebitor() {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", null, "fig"); final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "tenth contact", null, "fig");
assertThatDebitorIsVisibleForUserWithRole( assertThatDebitorIsVisibleForUserWithRole(
givenDebitor, givenDebitor,
"hs_office.relation#FourtheG-with-DEBITOR-FourtheG:ADMIN", true); givenDebitor.getDebitorRel().roleId(ADMIN), true);
assertThatDebitorActuallyInDatabase(givenDebitor, true); assertThatDebitorActuallyInDatabase(givenDebitor, true);
final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first")); final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first"));
@ -564,7 +566,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net", "hs_office.relation#FourtheG-with-DEBITOR-FourtheG:ADMIN"); context("superuser-alex@hostsharing.net", givenDebitor.getDebitorRel().roleId(ADMIN));
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent(); assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent();
debitorRepo.deleteByUuid(givenDebitor.getUuid()); debitorRepo.deleteByUuid(givenDebitor.getUuid());

View File

@ -94,7 +94,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenMandantPerson = personRealRepo.findPersonByOptionalNameLike("Hostsharing eG").stream().findFirst().orElseThrow(); final var givenMandantPerson = personRealRepo.findPersonByOptionalNameLike("Hostsharing eG").stream().findFirst().orElseThrow();
final var givenPerson = personRealRepo.findPersonByOptionalNameLike("Third").stream().findFirst().orElseThrow(); final var givenPerson = personRealRepo.findPersonByOptionalNameLike("Winkler").stream().findFirst().orElseThrow();
final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("fourth").stream().findFirst().orElseThrow(); final var givenContact = contactRealRepo.findContactByOptionalCaptionLike("fourth").stream().findFirst().orElseThrow();
final var location = RestAssured // @formatter:off final var location = RestAssured // @formatter:off
@ -129,7 +129,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
"partnerNumber": "P-20002", "partnerNumber": "P-20002",
"partnerRel": { "partnerRel": {
"anchor": { "tradeName": "Hostsharing eG" }, "anchor": { "tradeName": "Hostsharing eG" },
"holder": { "tradeName": "Third OHG" }, "holder": { "familyName": "Winkler" },
"type": "PARTNER", "type": "PARTNER",
"mark": null, "mark": null,
"contact": { "caption": "fourth contact" } "contact": { "caption": "fourth contact" }
@ -315,7 +315,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenPartner = givenSomeTemporaryPartnerBessler(20011); final var givenPartner = givenSomeTemporaryPartnerBessler(20011);
final var givenPartnerRel = givenSomeTemporaryPartnerRel("Third OHG", "third contact"); final var givenPartnerRel = givenSomeTemporaryPartnerRel("Winkler", "third contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -345,7 +345,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
"partnerNumber": "P-20011", "partnerNumber": "P-20011",
"partnerRel": { "partnerRel": {
"anchor": { "tradeName": "Hostsharing eG" }, "anchor": { "tradeName": "Hostsharing eG" },
"holder": { "tradeName": "Third OHG" }, "holder": { "familyName": "Winkler" },
"type": "PARTNER", "type": "PARTNER",
"contact": { "caption": "third contact" } "contact": { "caption": "third contact" }
}, },
@ -366,7 +366,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get() assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get()
.matches(partner -> { .matches(partner -> {
assertThat(partner.getPartnerNumber()).isEqualTo(givenPartner.getPartnerNumber()); assertThat(partner.getPartnerNumber()).isEqualTo(givenPartner.getPartnerNumber());
assertThat(partner.getPartnerRel().getHolder().getTradeName()).isEqualTo("Third OHG"); assertThat(partner.getPartnerRel().getHolder().getFamilyName()).isEqualTo("Winkler");
assertThat(partner.getPartnerRel().getContact().getCaption()).isEqualTo("third contact"); assertThat(partner.getPartnerRel().getContact().getCaption()).isEqualTo("third contact");
assertThat(partner.getDetails().getRegistrationOffice()).isEqualTo("Temp Registergericht Aurich"); assertThat(partner.getDetails().getRegistrationOffice()).isEqualTo("Temp Registergericht Aurich");
assertThat(partner.getDetails().getRegistrationNumber()).isEqualTo("222222"); assertThat(partner.getDetails().getRegistrationNumber()).isEqualTo("222222");
@ -382,7 +382,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenPartner = givenSomeTemporaryPartnerBessler(20011); final var givenPartner = givenSomeTemporaryPartnerBessler(20011);
final var givenPartnerRel = givenSomeTemporaryPartnerRel("Third OHG", "third contact"); final var givenPartnerRel = givenSomeTemporaryPartnerRel("Winkler", "third contact");
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -404,7 +404,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get() assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get()
.matches(partner -> { .matches(partner -> {
assertThat(partner.getPartnerRel().getHolder().getTradeName()).isEqualTo("Third OHG"); assertThat(partner.getPartnerRel().getHolder().getFamilyName()).isEqualTo("Winkler");
assertThat(partner.getPartnerRel().getContact().getCaption()).isEqualTo("third contact"); assertThat(partner.getPartnerRel().getContact().getCaption()).isEqualTo("third contact");
return true; return true;
}); });

View File

@ -31,6 +31,7 @@ import static net.hostsharing.hsadminng.rbac.grant.RawRbacGrantEntity.distinctGr
import static net.hostsharing.hsadminng.rbac.role.RawRbacObjectEntity.objectDisplaysOf; import static net.hostsharing.hsadminng.rbac.role.RawRbacObjectEntity.objectDisplaysOf;
import static net.hostsharing.hsadminng.rbac.role.RawRbacRoleEntity.distinctRoleNamesOf; import static net.hostsharing.hsadminng.rbac.role.RawRbacRoleEntity.distinctRoleNamesOf;
import static net.hostsharing.hsadminng.mapper.Array.from; import static net.hostsharing.hsadminng.mapper.Array.from;
import static net.hostsharing.hsadminng.rbac.role.RbacRoleType.ADMIN;
import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt; import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -76,7 +77,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var count = partnerRepo.count(); final var count = partnerRepo.count();
final var partnerRel = givenSomeTemporaryHostsharingPartnerRel("First GmbH", "first contact"); final var partnerRel = givenSomeTemporaryHostsharingPartnerRel("Winkler", "first contact");
// when // when
final var result = attempt(em, () -> { final var result = attempt(em, () -> {
@ -269,7 +270,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
givenPartner.setPartnerRel(givenSomeTemporaryHostsharingPartnerRel("Third OHG", "sixth contact")); givenPartner.setPartnerRel(givenSomeTemporaryHostsharingPartnerRel("Winkler", "sixth contact"));
return partnerRepo.save(givenPartner); return partnerRepo.save(givenPartner);
}); });
@ -281,7 +282,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
"rbac.global#global:ADMIN"); "rbac.global#global:ADMIN");
assertThatPartnerIsVisibleForUserWithRole( assertThatPartnerIsVisibleForUserWithRole(
givenPartner, givenPartner,
"hs_office.person#ThirdOHG:ADMIN"); givenPartner.getPartnerRel().getHolder().roleId(ADMIN));
assertThatPartnerIsNotVisibleForUserWithRole( assertThatPartnerIsNotVisibleForUserWithRole(
givenPartner, givenPartner,
"hs_office.person#ErbenBesslerMelBessler:ADMIN"); "hs_office.person#ErbenBesslerMelBessler:ADMIN");