Compare commits
No commits in common. "37f00a19f0a4336e0947469f7ab7e3b23d7b389b" and "ae2672e8452ed312f090a2fabdb023db3be8a546" have entirely different histories.
37f00a19f0
...
ae2672e845
@ -10,7 +10,7 @@ classDiagram
|
|||||||
|
|
||||||
namespace Partner {
|
namespace Partner {
|
||||||
class partner-MeierGmbH
|
class partner-MeierGmbH
|
||||||
class rel-MeierGmbH
|
class role-MeierGmbH
|
||||||
class personDetails-MeierGmbH
|
class personDetails-MeierGmbH
|
||||||
class contactData-MeierGmbH
|
class contactData-MeierGmbH
|
||||||
class person-MeierGmbH
|
class person-MeierGmbH
|
||||||
@ -19,29 +19,28 @@ classDiagram
|
|||||||
namespace Representatives {
|
namespace Representatives {
|
||||||
class person-FrankMeier
|
class person-FrankMeier
|
||||||
class contactData-FrankMeier
|
class contactData-FrankMeier
|
||||||
class rel-MeierGmbH-FrankMeier
|
class role-MeierGmbH-FrankMeier
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Debitors {
|
namespace Debitors {
|
||||||
class debitor-MeierGmbH
|
class debitor-MeierGmbH
|
||||||
class contactData-MeierGmbH-Buha
|
class contactData-MeierGmbH-Buha
|
||||||
class rel-MeierGmbH-Buha
|
class role-MeierGmbH-Buha
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Operations {
|
namespace Operations {
|
||||||
class person-SabineMeier
|
class person-SabineMeier
|
||||||
class contactData-SabineMeier
|
class contactData-SabineMeier
|
||||||
class rel-MeierGmbH-SabineMeier
|
class role-MeierGmbH-SabineMeier
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Enums {
|
namespace Enums {
|
||||||
|
|
||||||
class RelationType {
|
class RoleType {
|
||||||
<<enumeration>>
|
<<enumeration>>
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
PARTNER
|
|
||||||
DEBITOR
|
|
||||||
REPRESENTATIVE
|
REPRESENTATIVE
|
||||||
|
ACCOUNTING
|
||||||
OPERATIONS
|
OPERATIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,9 +64,9 @@ classDiagram
|
|||||||
|
|
||||||
class partner-MeierGmbH {
|
class partner-MeierGmbH {
|
||||||
+Numeric partnerNumber: 12345
|
+Numeric partnerNumber: 12345
|
||||||
+Relation partnerRel
|
+Role partnerRole
|
||||||
}
|
}
|
||||||
partner-MeierGmbH *-- rel-MeierGmbH
|
partner-MeierGmbH *-- role-MeierGmbH
|
||||||
|
|
||||||
class person-MeierGmbH {
|
class person-MeierGmbH {
|
||||||
+personType: LEGAL
|
+personType: LEGAL
|
||||||
@ -91,32 +90,32 @@ classDiagram
|
|||||||
+emailAddresses: office@meier-gmbh.de
|
+emailAddresses: office@meier-gmbh.de
|
||||||
}
|
}
|
||||||
|
|
||||||
class rel-MeierGmbH {
|
class role-MeierGmbH {
|
||||||
+RelationType type PARTNER
|
+RoleType RoleType PARTNER
|
||||||
+Person anchor
|
+Person anchor
|
||||||
+Person holder
|
+Person holder
|
||||||
+Contact contact
|
+Contact roleContact
|
||||||
}
|
}
|
||||||
rel-MeierGmbH o-- person-HostsharingEG : anchor
|
role-MeierGmbH o-- person-HostsharingEG : anchor
|
||||||
rel-MeierGmbH o-- person-MeierGmbH : holder
|
role-MeierGmbH o-- person-MeierGmbH : holder
|
||||||
rel-MeierGmbH o-- contactData-MeierGmbH
|
role-MeierGmbH o-- contactData-MeierGmbH
|
||||||
|
|
||||||
%% --- Debitors ---
|
%% --- Debitors ---
|
||||||
|
|
||||||
class debitor-MeierGmbH {
|
class debitor-MeierGmbH {
|
||||||
+Partner partner
|
+Partner partner
|
||||||
+Numeric[2] debitorNumberSuffix: 00
|
+Numeric[2] debitorNumberSuffix: 00
|
||||||
+Relation debitorRel
|
+Role billingRole
|
||||||
+boolean billable: true
|
+boolean billable: true
|
||||||
+String vatId: ID123456789
|
+String vatId: ID123456789
|
||||||
+String vatCountryCode: DE
|
+String vatCountryCode: DE
|
||||||
+boolean vatBusiness: true
|
+boolean vatBusiness: true
|
||||||
+boolean vatReverseCharge: false
|
+boolean vatReverseCharge: false
|
||||||
+BankAccount refundBankAccount
|
+BankAccount refundBankAccount
|
||||||
+String defaultPrefix: mei
|
+String defaultPrefix: mei
|
||||||
}
|
}
|
||||||
debitor-MeierGmbH o-- partner-MeierGmbH
|
debitor-MeierGmbH o-- partner-MeierGmbH
|
||||||
debitor-MeierGmbH *-- rel-MeierGmbH-Buha
|
debitor-MeierGmbH *-- role-MeierGmbH-Buha
|
||||||
|
|
||||||
class contactData-MeierGmbH-Buha {
|
class contactData-MeierGmbH-Buha {
|
||||||
+postalAddress: Hauptstraße 5, 22345 Hamburg
|
+postalAddress: Hauptstraße 5, 22345 Hamburg
|
||||||
@ -124,15 +123,15 @@ classDiagram
|
|||||||
+emailAddresses: buha@meier-gmbh.de
|
+emailAddresses: buha@meier-gmbh.de
|
||||||
}
|
}
|
||||||
|
|
||||||
class rel-MeierGmbH-Buha {
|
class role-MeierGmbH-Buha {
|
||||||
+RelationType type DEBITOR
|
+RoleType RoleType ACCOUNTING
|
||||||
+Person anchor
|
+Person anchor
|
||||||
+Person holder
|
+Person holder
|
||||||
+Contact contact
|
+Contact roleContact
|
||||||
}
|
}
|
||||||
rel-MeierGmbH-Buha o-- person-MeierGmbH : anchor
|
role-MeierGmbH-Buha o-- person-MeierGmbH : anchor
|
||||||
rel-MeierGmbH-Buha o-- person-MeierGmbH : holder
|
role-MeierGmbH-Buha o-- person-MeierGmbH : holder
|
||||||
rel-MeierGmbH-Buha o-- contactData-MeierGmbH-Buha
|
role-MeierGmbH-Buha o-- contactData-MeierGmbH-Buha
|
||||||
|
|
||||||
%% --- Representatives ---
|
%% --- Representatives ---
|
||||||
|
|
||||||
@ -149,15 +148,15 @@ classDiagram
|
|||||||
+emailAddresses: frank.meier@meier-gmbh.de
|
+emailAddresses: frank.meier@meier-gmbh.de
|
||||||
}
|
}
|
||||||
|
|
||||||
class rel-MeierGmbH-FrankMeier {
|
class role-MeierGmbH-FrankMeier {
|
||||||
+RelationType type REPRESENTATIVE
|
+RoleType RoleType REPRESENTATIVE
|
||||||
+Person anchor
|
+Person anchor
|
||||||
+Person holder
|
+Person holder
|
||||||
+Contact contact
|
+Contact roleContact
|
||||||
}
|
}
|
||||||
rel-MeierGmbH-FrankMeier o-- person-MeierGmbH : anchor
|
role-MeierGmbH-FrankMeier o-- person-MeierGmbH : anchor
|
||||||
rel-MeierGmbH-FrankMeier o-- person-FrankMeier : holder
|
role-MeierGmbH-FrankMeier o-- person-FrankMeier : holder
|
||||||
rel-MeierGmbH-FrankMeier o-- contactData-FrankMeier
|
role-MeierGmbH-FrankMeier o-- contactData-FrankMeier
|
||||||
|
|
||||||
%% --- Operations ---
|
%% --- Operations ---
|
||||||
|
|
||||||
@ -174,14 +173,14 @@ classDiagram
|
|||||||
+emailAddresses: sabine.meier@meier-gmbh.de
|
+emailAddresses: sabine.meier@meier-gmbh.de
|
||||||
}
|
}
|
||||||
|
|
||||||
class rel-MeierGmbH-SabineMeier {
|
class role-MeierGmbH-SabineMeier {
|
||||||
+RelationType type OPERATIONAL
|
+RoleType RoleType OPERATIONAL
|
||||||
+Person anchor
|
+Person anchor
|
||||||
+Person holder
|
+Person holder
|
||||||
+Contact contact
|
+Contact roleContact
|
||||||
}
|
}
|
||||||
rel-MeierGmbH-SabineMeier o-- person-MeierGmbH : anchor
|
role-MeierGmbH-SabineMeier o-- person-MeierGmbH : anchor
|
||||||
rel-MeierGmbH-SabineMeier o-- person-SabineMeier : holder
|
role-MeierGmbH-SabineMeier o-- person-SabineMeier : holder
|
||||||
rel-MeierGmbH-SabineMeier o-- contactData-SabineMeier
|
role-MeierGmbH-SabineMeier o-- contactData-SabineMeier
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -8,7 +8,7 @@ Vor einigen Wochen hatten wir schon einmal darüber geredet, ob wir dieses Gefle
|
|||||||
|
|
||||||
Und nun gehe ich noch einen Schritt weiter: Könnte es nicht auch andersherum sein? Also wenn jemand z.B. SELECT-Recht am Partner hat, dass wir davon ausgehen können, dass derjenige auch die Partner-Personen- und Kontaktdaten sehen darf, und zwar implizit durch seine Partner-SELECT-Permission und ohne dass er explizit Rollen für diese Partner-Personen oder Kontaktdaten inne hat?
|
Und nun gehe ich noch einen Schritt weiter: Könnte es nicht auch andersherum sein? Also wenn jemand z.B. SELECT-Recht am Partner hat, dass wir davon ausgehen können, dass derjenige auch die Partner-Personen- und Kontaktdaten sehen darf, und zwar implizit durch seine Partner-SELECT-Permission und ohne dass er explizit Rollen für diese Partner-Personen oder Kontaktdaten inne hat?
|
||||||
|
|
||||||
Im Halbschlaf kam mir nur die Idee, warum wir nicht einfach die komplexen JPA-Entitäten zwar auf die restricted View setzen, wie bisher, aber für die verknüpften Entitäten auf die direkten (bisher "Raw..." genannt) Entitäten gehen. Dann könnte jemand mit einer Rolle, welche die SELECT-Permission auf die komplexe JPA-Entität (z.B.) Partner inne hat, auch die dazugehörige Relation(ship) ["Relation" wurde vor kurzem auf kurz "Relation" umbenannt] und die wiederum dazu gehörigen Personen- und Kontaktdaten lesen, ohne dass in einem INSERT- und UPDATE-Trigger der Partner-Entität die ganzen Grants mit den verknüpften Entäten aufgebaut und aktualisiert werden müssen.
|
Im Halbschlaf kam mir nur die Idee, warum wir nicht einfach die komplexen JPA-Entitäten zwar auf die restricted View setzen, wie bisher, aber für die verknüpften Entitäten auf die direkten (bisher "Raw..." genannt) Entitäten gehen. Dann könnte jemand mit einer Rolle, welche die SELECT-Permission auf die komplexe JPA-Entität (z.B.) Partner inne hat, auch die dazugehörige Relation(ship) ["Relationship" wurde vor kurzem auf kurz "Relation" umbenannt] und die wiederum dazu gehörigen Personen- und Kontaktdaten lesen, ohne dass in einem INSERT- und UPDATE-Trigger der Partner-Entität die ganzen Grants mit den verknüpften Entäten aufgebaut und aktualisiert werden müssen.
|
||||||
|
|
||||||
Beim Debitor ist das nämlich selbst mit Generator die Hölle, zumal eben auch Querverbindungen gegranted werden müssen, z.B. von der Debitor-Person zum Sema-Mandat - jedenfalls wenn man nicht Gefahr laufen wollte, dass jemand mit Admin-Rechten an der Partner-Person (also z.B. ein Repräsentant des Partners) die Sepa-Mandate der Debitoren gar nicht mehr sehen kann. Natürlich bräuchte man immer noch die Agent-Rolle am Partner und Debitor (evtl. repräsentiert durch die jeweils zugehörigen Relation - falls dieser Trick überhaupt noch nötig wäre), sowie ein Grant vom Partner-Agent auf den Debitor-Agent und vom Debitor-Agent auf die Sepa-Mandate-Admins, aber eben ohne filigran die ganzen Neben-Entäten (Personen- und Kontaktdaten von Partner und Debitor sowie Bank-Account) in jedem Trigger berücksichtigen zu müssen. Beim Refund-Bank-Account sogar besonders ätzend, weil der optional ist und dadurch zig "if ...refundBankAccountUuid is not null then ..." im Code enstehen (wenn der auch generiert ist).
|
Beim Debitor ist das nämlich selbst mit Generator die Hölle, zumal eben auch Querverbindungen gegranted werden müssen, z.B. von der Debitor-Person zum Sema-Mandat - jedenfalls wenn man nicht Gefahr laufen wollte, dass jemand mit Admin-Rechten an der Partner-Person (also z.B. ein Repräsentant des Partners) die Sepa-Mandate der Debitoren gar nicht mehr sehen kann. Natürlich bräuchte man immer noch die Agent-Rolle am Partner und Debitor (evtl. repräsentiert durch die jeweils zugehörigen Relation - falls dieser Trick überhaupt noch nötig wäre), sowie ein Grant vom Partner-Agent auf den Debitor-Agent und vom Debitor-Agent auf die Sepa-Mandate-Admins, aber eben ohne filigran die ganzen Neben-Entäten (Personen- und Kontaktdaten von Partner und Debitor sowie Bank-Account) in jedem Trigger berücksichtigen zu müssen. Beim Refund-Bank-Account sogar besonders ätzend, weil der optional ist und dadurch zig "if ...refundBankAccountUuid is not null then ..." im Code enstehen (wenn der auch generiert ist).
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ Das folgende Schema soll dabei unterstützen, die richtigen Permissions, Rollen
|
|||||||
|
|
||||||
An einigen Stellen ist vom *Initiator* die Rede. Als *Initiator* gilt derjenige User, der die Operation (INSERT oder UPDATE) durchführt bzw. dessen primary assumed Rol. (TODO: bisher gibt es nur assumed roles, das Konzept einer primary assumed Role müsste noch eingeführt werden, derzeit nehmen wir dafür immer den `globalAdmin()`. Bevor Kunden aber selbst Objekte anlegen können, muss das geklärt sein.)
|
An einigen Stellen ist vom *Initiator* die Rede. Als *Initiator* gilt derjenige User, der die Operation (INSERT oder UPDATE) durchführt bzw. dessen primary assumed Rol. (TODO: bisher gibt es nur assumed roles, das Konzept einer primary assumed Role müsste noch eingeführt werden, derzeit nehmen wir dafür immer den `globalAdmin()`. Bevor Kunden aber selbst Objekte anlegen können, muss das geklärt sein.)
|
||||||
|
|
||||||
#### Typ Root: Objekte, welche nur eine Spezialisierung bzw. Zusatzdaten für andere Objekte bereitstellen (z.B. Partner für Relations vom Typ Partner oder Partner Details für Partner)
|
#### Typ Root: Objekte, welche nur eine Spezialisierung bzw. Zusatzdaten für andere Objekte bereitstellen (z.B. Partner für Relationships vom Typ Partner oder Partner Details für Partner)
|
||||||
|
|
||||||
Objektorientiert gedacht, enthalten solche Objekte die Zusatzdaten einer Subklasse; die Daten im Partner erweitern also eine Relation vom Typ `partner`.
|
Objektorientiert gedacht, enthalten solche Objekte die Zusatzdaten einer Subklasse; die Daten im Partner erweitern also eine Relationship vom Typ `partner`.
|
||||||
|
|
||||||
- Dann muss dieses Objekt zeitlich nach dem Objekt erzeugt werden, auf dass es sich bezieht, also z.B. zeitlich nach der Relation.
|
- Dann muss dieses Objekt zeitlich nach dem Objekt erzeugt werden, auf dass es sich bezieht, also z.B. zeitlich nach der Relationship.
|
||||||
- Es werden Delete (\*), Edit und View Permissions für dieses Objekt erzeugt.
|
- Es werden Delete (\*), Edit und View Permissions für dieses Objekt erzeugt.
|
||||||
- Es werden **keine** Rollen für dieses Objekt erzeugt.
|
- Es werden **keine** Rollen für dieses Objekt erzeugt.
|
||||||
- Statt eigener Rollen werden die o.g. Permissions passenden Rollen des Hauptobjekts zugewiesen (granted) bzw. aus denen entfernt (revoked).
|
- Statt eigener Rollen werden die o.g. Permissions passenden Rollen des Hauptobjekts zugewiesen (granted) bzw. aus denen entfernt (revoked).
|
||||||
@ -33,7 +33,7 @@ Objektorientiert gedacht, enthalten solche Objekte die Zusatzdaten einer Subklas
|
|||||||
Anmerkung: Der Typ-Begriff *Root* bezieht sich auf die Rolle im fachlichen Datenmodell. Im Bezug auf den Teilgraphen eines fachlichen Kontexts ist dies auch eine Wurzel im Sinne der Graphentheorie. Aber in anderen fachlichen Kontexten können auch diese Objekte von anderen Teilgraphen referenziert werden und werden dann zum inneren Knoten.
|
Anmerkung: Der Typ-Begriff *Root* bezieht sich auf die Rolle im fachlichen Datenmodell. Im Bezug auf den Teilgraphen eines fachlichen Kontexts ist dies auch eine Wurzel im Sinne der Graphentheorie. Aber in anderen fachlichen Kontexten können auch diese Objekte von anderen Teilgraphen referenziert werden und werden dann zum inneren Knoten.
|
||||||
|
|
||||||
|
|
||||||
#### Typ Aggregator: Objekte, welche weitere Objekte zusammenfassen (z.B. Relation fasst zwei Persons und einen Contact zusammen)
|
#### Typ Aggregator: Objekte, welche weitere Objekte zusammenfassen (z.B. Relationship fasst zwei Persons und einen Contact zusammen)
|
||||||
|
|
||||||
Solche Objekte verweisen üblicherweise auf Objekte vom Typ Leaf und werden oft von Objekten des Typs Root referenziert.
|
Solche Objekte verweisen üblicherweise auf Objekte vom Typ Leaf und werden oft von Objekten des Typs Root referenziert.
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeDebitors
|
|||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorInsertResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorInsertResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRepository;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipRepository;
|
||||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -21,7 +21,7 @@ import jakarta.persistence.PersistenceContext;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR;
|
import static net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType.ACCOUNTING;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
|
|||||||
private HsOfficeDebitorRepository debitorRepo;
|
private HsOfficeDebitorRepository debitorRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HsOfficeRelationRepository relRepo;
|
private HsOfficeRelationshipRepository relRepo;
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager em;
|
private EntityManager em;
|
||||||
@ -73,15 +73,15 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
|
|||||||
Validate.isTrue(body.getDebitorRel() != null || body.getDebitorRelUuid() != null,
|
Validate.isTrue(body.getDebitorRel() != null || body.getDebitorRelUuid() != null,
|
||||||
"ERROR: [400] exactly one of debitorRel and debitorRelUuid must be supplied, but found none");
|
"ERROR: [400] exactly one of debitorRel and debitorRelUuid must be supplied, but found none");
|
||||||
Validate.isTrue(body.getDebitorRel() == null ||
|
Validate.isTrue(body.getDebitorRel() == null ||
|
||||||
body.getDebitorRel().getType() == null || DEBITOR.name().equals(body.getDebitorRel().getType()),
|
body.getDebitorRel().getRelType() == null || ACCOUNTING.name().equals(body.getDebitorRel().getRelType()),
|
||||||
"ERROR: [400] debitorRel.type must be '"+DEBITOR.name()+"' or null for default");
|
"ERROR: [400] debitorRel.relType must be '"+ACCOUNTING.name()+"' or null for default");
|
||||||
Validate.isTrue(body.getDebitorRel() == null || body.getDebitorRel().getMark() == null,
|
Validate.isTrue(body.getDebitorRel() == null || body.getDebitorRel().getRelMark() == null,
|
||||||
"ERROR: [400] debitorRel.mark must be null");
|
"ERROR: [400] debitorRel.relMark must be null");
|
||||||
|
|
||||||
final var entityToSave = mapper.map(body, HsOfficeDebitorEntity.class);
|
final var entityToSave = mapper.map(body, HsOfficeDebitorEntity.class);
|
||||||
if ( body.getDebitorRel() != null ) {
|
if ( body.getDebitorRel() != null ) {
|
||||||
body.getDebitorRel().setType(DEBITOR.name());
|
body.getDebitorRel().setRelType(ACCOUNTING.name());
|
||||||
final var debitorRel = mapper.map(body.getDebitorRel(), HsOfficeRelationEntity.class);
|
final var debitorRel = mapper.map(body.getDebitorRel(), HsOfficeRelationshipEntity.class);
|
||||||
entityToSave.setDebitorRel(relRepo.save(debitorRel));
|
entityToSave.setDebitorRel(relRepo.save(debitorRel));
|
||||||
// FIXME em.flush();
|
// FIXME em.flush();
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,8 +3,8 @@ package net.hostsharing.hsadminng.hs.office.debitor;
|
|||||||
import lombok.*;
|
import lombok.*;
|
||||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
|
||||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||||
@ -43,7 +43,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
private static Stringify<HsOfficeDebitorEntity> stringify =
|
private static Stringify<HsOfficeDebitorEntity> stringify =
|
||||||
stringify(HsOfficeDebitorEntity.class, "debitor")
|
stringify(HsOfficeDebitorEntity.class, "debitor")
|
||||||
.withIdProp(HsOfficeDebitorEntity::toShortString)
|
.withIdProp(HsOfficeDebitorEntity::toShortString)
|
||||||
.withProp(e -> ofNullable(e.getDebitorRel()).map(HsOfficeRelationEntity::toShortString).orElse(null))
|
.withProp(e -> ofNullable(e.getDebitorRel()).map(HsOfficeRelationshipEntity::toShortString).orElse(null))
|
||||||
.withProp(HsOfficeDebitorEntity::getDefaultPrefix)
|
.withProp(HsOfficeDebitorEntity::getDefaultPrefix)
|
||||||
.quotedValues(false);
|
.quotedValues(false);
|
||||||
|
|
||||||
@ -60,11 +60,11 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
(
|
(
|
||||||
SELECT DISTINCT partner.uuid
|
SELECT DISTINCT partner.uuid
|
||||||
FROM hs_office_partner partner
|
FROM hs_office_partner partner
|
||||||
JOIN hs_office_relation dRel
|
JOIN hs_office_relationship dRel
|
||||||
ON dRel.uuid = debitorreluuid AND dRel.type = 'DEBITOR'
|
ON dRel.uuid = debitorreluuid AND dRel.relType = 'ACCOUNTING'
|
||||||
JOIN hs_office_relation pRel
|
JOIN hs_office_relationship pRel
|
||||||
ON pRel.uuid = partner.partnerRelUuid AND pRel.type = 'PARTNER'
|
ON pRel.uuid = partner.partnerRoleUuid AND pRel.relType = 'PARTNER'
|
||||||
WHERE pRel.holderUuid = dRel.anchorUuid
|
WHERE pRel.relHolderUuid = dRel.relAnchorUuid
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
@NotFound(action = NotFoundAction.IGNORE)
|
@NotFound(action = NotFoundAction.IGNORE)
|
||||||
@ -75,7 +75,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
|
|
||||||
@ManyToOne(cascade = CascadeType.ALL)
|
@ManyToOne(cascade = CascadeType.ALL)
|
||||||
@JoinColumn(name = "debitorreluuid", nullable = false)
|
@JoinColumn(name = "debitorreluuid", nullable = false)
|
||||||
private HsOfficeRelationEntity debitorRel;
|
private HsOfficeRelationshipEntity debitorRel;
|
||||||
|
|
||||||
@Column(name = "billable", nullable = false)
|
@Column(name = "billable", nullable = false)
|
||||||
private Boolean billable; // not a primitive because otherwise the default would be false
|
private Boolean billable; // not a primitive because otherwise the default would be false
|
||||||
@ -128,10 +128,10 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
SELECT debitor.uuid AS uuid,
|
SELECT debitor.uuid AS uuid,
|
||||||
'D-' || (SELECT partner.partnerNumber
|
'D-' || (SELECT partner.partnerNumber
|
||||||
FROM hs_office_partner partner
|
FROM hs_office_partner partner
|
||||||
JOIN hs_office_relation partnerRel
|
JOIN hs_office_relationship partnerRel
|
||||||
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
|
ON partnerRel.uuid = partner.partnerRoleUUid AND partnerRel.relType = 'PARTNER'
|
||||||
JOIN hs_office_relation debitorRel
|
JOIN hs_office_relationship debitorRel
|
||||||
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
ON debitorRel.relAnchorUuid = partnerRel.relHolderUuid AND debitorRel.relType = 'ACCOUNTING'
|
||||||
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
||||||
|| to_char(debitorNumberSuffix, 'fm00') as idName
|
|| to_char(debitorNumberSuffix, 'fm00') as idName
|
||||||
FROM hs_office_debitor AS debitor
|
FROM hs_office_debitor AS debitor
|
||||||
@ -148,11 +148,11 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
"defaultPrefix" /* TODO: do we want that updatable? */)
|
"defaultPrefix" /* TODO: do we want that updatable? */)
|
||||||
.toRole("global", ADMIN).grantPermission(INSERT)
|
.toRole("global", ADMIN).grantPermission(INSERT)
|
||||||
|
|
||||||
.importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class,
|
.importRootEntityAliasProxy("debitorRel", HsOfficeRelationshipEntity.class,
|
||||||
fetchedBySql("""
|
fetchedBySql("""
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM hs_office_relation AS r
|
FROM hs_office_relationship AS r
|
||||||
WHERE r.type = 'DEBITOR' AND r.uuid = ${REF}.debitorRelUuid
|
WHERE r.relType = 'ACCOUNTING' AND r.uuid = ${REF}.debitorRelUuid
|
||||||
"""),
|
"""),
|
||||||
dependsOnColumn("debitorRelUuid"))
|
dependsOnColumn("debitorRelUuid"))
|
||||||
.createPermission(DELETE).grantedTo("debitorRel", OWNER)
|
.createPermission(DELETE).grantedTo("debitorRel", OWNER)
|
||||||
@ -171,14 +171,14 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
.toRole("refundBankAccount", ADMIN).grantRole("debitorRel", AGENT)
|
.toRole("refundBankAccount", ADMIN).grantRole("debitorRel", AGENT)
|
||||||
.toRole("debitorRel", AGENT).grantRole("refundBankAccount", REFERRER)
|
.toRole("debitorRel", AGENT).grantRole("refundBankAccount", REFERRER)
|
||||||
|
|
||||||
.importEntityAlias("partnerRel", HsOfficeRelationEntity.class,
|
.importEntityAlias("partnerRel", HsOfficeRelationshipEntity.class,
|
||||||
dependsOnColumn("debitorRelUuid"),
|
dependsOnColumn("debitorRelUuid"),
|
||||||
fetchedBySql("""
|
fetchedBySql("""
|
||||||
SELECT partnerRel.*
|
SELECT partnerRel.*
|
||||||
FROM hs_office_relation AS partnerRel
|
FROM hs_office_relationship AS partnerRel
|
||||||
JOIN hs_office_relation AS debitorRel
|
JOIN hs_office_relationship AS debitorRel
|
||||||
ON debitorRel.type = 'DEBITOR' AND debitorRel.anchorUuid = partnerRel.holderUuid
|
ON debitorRel.relType = 'ACCOUNTING' AND debitorRel.relAnchorUuid = partnerRel.relHolderUuid
|
||||||
WHERE partnerRel.type = 'PARTNER'
|
WHERE partnerRel.relType = 'PARTNER'
|
||||||
AND ${REF}.debitorRelUuid = debitorRel.uuid
|
AND ${REF}.debitorRelUuid = debitorRel.uuid
|
||||||
""")
|
""")
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.office.debitor;
|
|||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ class HsOfficeDebitorEntityPatcher implements EntityPatcher<HsOfficeDebitorPatch
|
|||||||
public void apply(final HsOfficeDebitorPatchResource resource) {
|
public void apply(final HsOfficeDebitorPatchResource resource) {
|
||||||
OptionalFromJson.of(resource.getDebitorRelUuid()).ifPresent(newValue -> {
|
OptionalFromJson.of(resource.getDebitorRelUuid()).ifPresent(newValue -> {
|
||||||
verifyNotNull(newValue, "debitorRel");
|
verifyNotNull(newValue, "debitorRel");
|
||||||
entity.setDebitorRel(em.getReference(HsOfficeRelationEntity.class, newValue));
|
entity.setDebitorRel(em.getReference(HsOfficeRelationshipEntity.class, newValue));
|
||||||
});
|
});
|
||||||
Optional.ofNullable(resource.getBillable()).ifPresent(entity::setBillable);
|
Optional.ofNullable(resource.getBillable()).ifPresent(entity::setBillable);
|
||||||
OptionalFromJson.of(resource.getVatId()).ifPresent(entity::setVatId);
|
OptionalFromJson.of(resource.getVatId()).ifPresent(entity::setVatId);
|
||||||
|
@ -14,8 +14,8 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
|
|||||||
@Query("""
|
@Query("""
|
||||||
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
||||||
JOIN HsOfficePartnerEntity partner
|
JOIN HsOfficePartnerEntity partner
|
||||||
ON partner.partnerRel.holder = debitor.debitorRel.anchor
|
ON partner.partnerRole.relHolder = debitor.debitorRel.relAnchor
|
||||||
AND partner.partnerRel.type = 'PARTNER' AND debitor.debitorRel.type = 'DEBITOR'
|
AND partner.partnerRole.relType = 'PARTNER' AND debitor.debitorRel.relType = 'ACCOUNTING'
|
||||||
WHERE cast(partner.partnerNumber as integer) = :partnerNumber
|
WHERE cast(partner.partnerNumber as integer) = :partnerNumber
|
||||||
AND cast(debitor.debitorNumberSuffix as integer) = :debitorNumberSuffix
|
AND cast(debitor.debitorNumberSuffix as integer) = :debitorNumberSuffix
|
||||||
""")
|
""")
|
||||||
@ -28,14 +28,14 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
|
|||||||
@Query("""
|
@Query("""
|
||||||
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
SELECT debitor FROM HsOfficeDebitorEntity debitor
|
||||||
JOIN HsOfficePartnerEntity partner
|
JOIN HsOfficePartnerEntity partner
|
||||||
ON partner.partnerRel.holder = debitor.debitorRel.anchor
|
ON partner.partnerRole.relHolder = debitor.debitorRel.relAnchor
|
||||||
AND partner.partnerRel.type = 'PARTNER' AND debitor.debitorRel.type = 'DEBITOR'
|
AND partner.partnerRole.relType = 'PARTNER' AND debitor.debitorRel.relType = 'ACCOUNTING'
|
||||||
JOIN HsOfficePersonEntity person
|
JOIN HsOfficePersonEntity person
|
||||||
ON person.uuid = partner.partnerRel.holder.uuid
|
ON person.uuid = partner.partnerRole.relHolder.uuid
|
||||||
OR person.uuid = debitor.debitorRel.holder.uuid
|
OR person.uuid = debitor.debitorRel.relHolder.uuid
|
||||||
JOIN HsOfficeContactEntity contact
|
JOIN HsOfficeContactEntity contact
|
||||||
ON contact.uuid = debitor.debitorRel.contact.uuid
|
ON contact.uuid = debitor.debitorRel.contact.uuid
|
||||||
OR contact.uuid = partner.partnerRel.contact.uuid
|
OR contact.uuid = partner.partnerRole.contact.uuid
|
||||||
WHERE :name is null
|
WHERE :name is null
|
||||||
OR partner.details.birthName like concat(cast(:name as text), '%')
|
OR partner.details.birthName like concat(cast(:name as text), '%')
|
||||||
OR person.tradeName like concat(cast(:name as text), '%')
|
OR person.tradeName like concat(cast(:name as text), '%')
|
||||||
|
@ -4,7 +4,7 @@ import com.vladmihalcea.hibernate.type.range.PostgreSQLRangeType;
|
|||||||
import com.vladmihalcea.hibernate.type.range.Range;
|
import com.vladmihalcea.hibernate.type.range.Range;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
@ -128,12 +128,12 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
|
|||||||
.withRestrictedViewOrderBy(SQL.projection("validity"))
|
.withRestrictedViewOrderBy(SQL.projection("validity"))
|
||||||
.withUpdatableColumns("validity", "membershipFeeBillable", "reasonForTermination")
|
.withUpdatableColumns("validity", "membershipFeeBillable", "reasonForTermination")
|
||||||
|
|
||||||
.importEntityAlias("partnerRel", HsOfficeRelationEntity.class,
|
.importEntityAlias("partnerRel", HsOfficeRelationshipEntity.class,
|
||||||
dependsOnColumn("partnerUuid"),
|
dependsOnColumn("partnerUuid"),
|
||||||
fetchedBySql("""
|
fetchedBySql("""
|
||||||
SELECT r.*
|
SELECT r.*
|
||||||
FROM hs_office_partner AS p
|
FROM hs_office_partner AS p
|
||||||
JOIN hs_office_relation AS r ON r.uuid = p.partnerRelUuid
|
JOIN hs_office_relationship AS r ON r.uuid = p.partnerRoleUuid
|
||||||
WHERE p.uuid = ${REF}.partnerUuid
|
WHERE p.uuid = ${REF}.partnerUuid
|
||||||
"""))
|
"""))
|
||||||
.toRole("partnerRel", ADMIN).grantPermission(INSERT)
|
.toRole("partnerRel", ADMIN).grantPermission(INSERT)
|
||||||
|
@ -7,11 +7,11 @@ import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartners
|
|||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerRelInsertResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerRoleInsertResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRepository;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -40,7 +40,7 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
|
|||||||
private HsOfficePartnerRepository partnerRepo;
|
private HsOfficePartnerRepository partnerRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HsOfficeRelationRepository relationRepo;
|
private HsOfficeRelationshipRepository relationshipRepo;
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager em;
|
private EntityManager em;
|
||||||
@ -139,16 +139,16 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
|
|||||||
private HsOfficePartnerEntity createPartnerEntity(final HsOfficePartnerInsertResource body) {
|
private HsOfficePartnerEntity createPartnerEntity(final HsOfficePartnerInsertResource body) {
|
||||||
final var entityToSave = new HsOfficePartnerEntity();
|
final var entityToSave = new HsOfficePartnerEntity();
|
||||||
entityToSave.setPartnerNumber(body.getPartnerNumber());
|
entityToSave.setPartnerNumber(body.getPartnerNumber());
|
||||||
entityToSave.setPartnerRel(persistPartnerRel(body.getPartnerRel()));
|
entityToSave.setPartnerRole(persistPartnerRole(body.getPartnerRole()));
|
||||||
entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class));
|
entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class));
|
||||||
return entityToSave;
|
return entityToSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity persistPartnerRel(final HsOfficePartnerRelInsertResource resource) {
|
private HsOfficeRelationshipEntity persistPartnerRole(final HsOfficePartnerRoleInsertResource resource) {
|
||||||
final var entity = new HsOfficeRelationEntity();
|
final var entity = new HsOfficeRelationshipEntity();
|
||||||
entity.setType(HsOfficeRelationType.PARTNER);
|
entity.setRelType(HsOfficeRelationshipType.PARTNER);
|
||||||
entity.setAnchor(ref(HsOfficePersonEntity.class, resource.getAnchorUuid()));
|
entity.setRelAnchor(ref(HsOfficePersonEntity.class, resource.getRelAnchorUuid()));
|
||||||
entity.setHolder(ref(HsOfficePersonEntity.class, resource.getHolderUuid()));
|
entity.setRelHolder(ref(HsOfficePersonEntity.class, resource.getRelHolderUuid()));
|
||||||
entity.setContact(ref(HsOfficeContactEntity.class, resource.getContactUuid()));
|
entity.setContact(ref(HsOfficeContactEntity.class, resource.getContactUuid()));
|
||||||
em.persist(entity);
|
em.persist(entity);
|
||||||
return entity;
|
return entity;
|
||||||
|
@ -9,7 +9,7 @@ import net.hostsharing.hsadminng.errors.DisplayName;
|
|||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||||
@ -51,12 +51,12 @@ public class HsOfficePartnerEntity implements Stringifyable, HasUuid {
|
|||||||
|
|
||||||
private static Stringify<HsOfficePartnerEntity> stringify = stringify(HsOfficePartnerEntity.class, "partner")
|
private static Stringify<HsOfficePartnerEntity> stringify = stringify(HsOfficePartnerEntity.class, "partner")
|
||||||
.withIdProp(HsOfficePartnerEntity::toShortString)
|
.withIdProp(HsOfficePartnerEntity::toShortString)
|
||||||
.withProp(p -> ofNullable(p.getPartnerRel())
|
.withProp(p -> ofNullable(p.getPartnerRole())
|
||||||
.map(HsOfficeRelationEntity::getHolder)
|
.map(HsOfficeRelationshipEntity::getRelHolder)
|
||||||
.map(HsOfficePersonEntity::toShortString)
|
.map(HsOfficePersonEntity::toShortString)
|
||||||
.orElse(null))
|
.orElse(null))
|
||||||
.withProp(p -> ofNullable(p.getPartnerRel())
|
.withProp(p -> ofNullable(p.getPartnerRole())
|
||||||
.map(HsOfficeRelationEntity::getContact)
|
.map(HsOfficeRelationshipEntity::getContact)
|
||||||
.map(HsOfficeContactEntity::toShortString)
|
.map(HsOfficeContactEntity::toShortString)
|
||||||
.orElse(null))
|
.orElse(null))
|
||||||
.quotedValues(false);
|
.quotedValues(false);
|
||||||
@ -69,8 +69,8 @@ public class HsOfficePartnerEntity implements Stringifyable, HasUuid {
|
|||||||
private Integer partnerNumber;
|
private Integer partnerNumber;
|
||||||
|
|
||||||
@ManyToOne(cascade = CascadeType.ALL)
|
@ManyToOne(cascade = CascadeType.ALL)
|
||||||
@JoinColumn(name = "partnerReluuid", nullable = false)
|
@JoinColumn(name = "partnerroleuuid", nullable = false)
|
||||||
private HsOfficeRelationEntity partnerRel;
|
private HsOfficeRelationshipEntity partnerRole;
|
||||||
|
|
||||||
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH }, optional = true)
|
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH }, optional = true)
|
||||||
@JoinColumn(name = "detailsuuid")
|
@JoinColumn(name = "detailsuuid")
|
||||||
@ -94,12 +94,12 @@ public class HsOfficePartnerEntity implements Stringifyable, HasUuid {
|
|||||||
public static RbacView rbac() {
|
public static RbacView rbac() {
|
||||||
return rbacViewFor("partner", HsOfficePartnerEntity.class)
|
return rbacViewFor("partner", HsOfficePartnerEntity.class)
|
||||||
.withIdentityView(SQL.projection("'P-' || partnerNumber"))
|
.withIdentityView(SQL.projection("'P-' || partnerNumber"))
|
||||||
.withUpdatableColumns("partnerRelUuid")
|
.withUpdatableColumns("partnerRoleUuid")
|
||||||
.toRole("global", ADMIN).grantPermission(INSERT) // FIXME: global -> partnerRel.anchor?
|
.toRole("global", ADMIN).grantPermission(INSERT) // FIXME: global -> partnerRel.relAnchor?
|
||||||
|
|
||||||
.importRootEntityAliasProxy("partnerRel", HsOfficeRelationEntity.class,
|
.importRootEntityAliasProxy("partnerRel", HsOfficeRelationshipEntity.class,
|
||||||
fetchedBySql("SELECT * FROM hs_office_relation AS r WHERE r.uuid = ${ref}.partnerRelUuid"),
|
fetchedBySql("SELECT * FROM hs_office_relationship AS r WHERE r.uuid = ${ref}.partnerRoleUuid"),
|
||||||
dependsOnColumn("partnerRelUuid"))
|
dependsOnColumn("partnerRoleUuid"))
|
||||||
.createPermission(DELETE).grantedTo("partnerRel", ADMIN)
|
.createPermission(DELETE).grantedTo("partnerRel", ADMIN)
|
||||||
.createPermission(UPDATE).grantedTo("partnerRel", AGENT)
|
.createPermission(UPDATE).grantedTo("partnerRel", AGENT)
|
||||||
.createPermission(SELECT).grantedTo("partnerRel", TENANT)
|
.createPermission(SELECT).grantedTo("partnerRel", TENANT)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.partner;
|
package net.hostsharing.hsadminng.hs.office.partner;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||||
|
|
||||||
@ -19,9 +19,9 @@ class HsOfficePartnerEntityPatcher implements EntityPatcher<HsOfficePartnerPatch
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(final HsOfficePartnerPatchResource resource) {
|
public void apply(final HsOfficePartnerPatchResource resource) {
|
||||||
OptionalFromJson.of(resource.getPartnerRelUuid()).ifPresent(newValue -> {
|
OptionalFromJson.of(resource.getPartnerRoleUuid()).ifPresent(newValue -> {
|
||||||
verifyNotNull(newValue, "partnerRel");
|
verifyNotNull(newValue, "partnerRole");
|
||||||
entity.setPartnerRel(em.getReference(HsOfficeRelationEntity.class, newValue));
|
entity.setPartnerRole(em.getReference(HsOfficeRelationshipEntity.class, newValue));
|
||||||
});
|
});
|
||||||
|
|
||||||
new HsOfficePartnerDetailsEntityPatcher(em, entity.getDetails()).apply(resource.getDetails());
|
new HsOfficePartnerDetailsEntityPatcher(em, entity.getDetails()).apply(resource.getDetails());
|
||||||
|
@ -15,9 +15,9 @@ public interface HsOfficePartnerRepository extends Repository<HsOfficePartnerEnt
|
|||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
SELECT partner FROM HsOfficePartnerEntity partner
|
SELECT partner FROM HsOfficePartnerEntity partner
|
||||||
JOIN HsOfficeRelationEntity rel ON rel.uuid = partner.partnerRel.uuid
|
JOIN HsOfficeRelationshipEntity rel ON rel.uuid = partner.partnerRole.uuid
|
||||||
JOIN HsOfficeContactEntity contact ON contact.uuid = rel.contact.uuid
|
JOIN HsOfficeContactEntity contact ON contact.uuid = rel.contact.uuid
|
||||||
JOIN HsOfficePersonEntity person ON person.uuid = rel.holder.uuid
|
JOIN HsOfficePersonEntity person ON person.uuid = rel.relHolder.uuid
|
||||||
WHERE :name is null
|
WHERE :name is null
|
||||||
OR partner.details.birthName like concat(cast(:name as text), '%')
|
OR partner.details.birthName like concat(cast(:name as text), '%')
|
||||||
OR contact.label like concat(cast(:name as text), '%')
|
OR contact.label like concat(cast(:name as text), '%')
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.data.repository.Repository;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public interface HsOfficeRelationRepository extends Repository<HsOfficeRelationEntity, UUID> {
|
|
||||||
|
|
||||||
Optional<HsOfficeRelationEntity> findByUuid(UUID id);
|
|
||||||
|
|
||||||
default List<HsOfficeRelationEntity> findRelationRelatedToPersonUuidAndRelationType(@NotNull UUID personUuid, HsOfficeRelationType relationType) {
|
|
||||||
return findRelationRelatedToPersonUuidAndRelationTypeString(personUuid, relationType.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Query(value = """
|
|
||||||
SELECT p.* FROM hs_office_relation_rv AS p
|
|
||||||
WHERE p.anchorUuid = :personUuid OR p.holderUuid = :personUuid
|
|
||||||
""", nativeQuery = true)
|
|
||||||
List<HsOfficeRelationEntity> findRelationRelatedToPersonUuid(@NotNull UUID personUuid);
|
|
||||||
|
|
||||||
@Query(value = """
|
|
||||||
SELECT p.* FROM hs_office_relation_rv AS p
|
|
||||||
WHERE (:relationType IS NULL OR p.type = cast(:relationType AS HsOfficeRelationType))
|
|
||||||
AND ( p.anchorUuid = :personUuid OR p.holderUuid = :personUuid)
|
|
||||||
""", nativeQuery = true)
|
|
||||||
List<HsOfficeRelationEntity> findRelationRelatedToPersonUuidAndRelationTypeString(@NotNull UUID personUuid, String relationType);
|
|
||||||
|
|
||||||
HsOfficeRelationEntity save(final HsOfficeRelationEntity entity);
|
|
||||||
|
|
||||||
long count();
|
|
||||||
|
|
||||||
int deleteByUuid(UUID uuid);
|
|
||||||
}
|
|
@ -1,8 +1,8 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelationsApi;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelationshipsApi;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||||
@ -22,7 +22,7 @@ import java.util.function.BiConsumer;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|
||||||
public class HsOfficeRelationController implements HsOfficeRelationsApi {
|
public class HsOfficeRelationshipController implements HsOfficeRelationshipsApi {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Context context;
|
private Context context;
|
||||||
@ -31,10 +31,10 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
|
|||||||
private Mapper mapper;
|
private Mapper mapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HsOfficeRelationRepository relationRepo;
|
private HsOfficeRelationshipRepository relationshipRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HsOfficePersonRepository holderRepo;
|
private HsOfficePersonRepository relHolderRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HsOfficeContactRepository contactRepo;
|
private HsOfficeContactRepository contactRepo;
|
||||||
@ -44,79 +44,79 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseEntity<List<HsOfficeRelationResource>> listRelations(
|
public ResponseEntity<List<HsOfficeRelationshipResource>> listRelationships(
|
||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final UUID personUuid,
|
final UUID personUuid,
|
||||||
final HsOfficeRelationTypeResource relationType) {
|
final HsOfficeRelationshipTypeResource relationshipType) {
|
||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var entities = relationRepo.findRelationRelatedToPersonUuidAndRelationType(personUuid,
|
final var entities = relationshipRepo.findRelationshipRelatedToPersonUuidAndRelationshipType(personUuid,
|
||||||
mapper.map(relationType, HsOfficeRelationType.class));
|
mapper.map(relationshipType, HsOfficeRelationshipType.class));
|
||||||
|
|
||||||
final var resources = mapper.mapList(entities, HsOfficeRelationResource.class,
|
final var resources = mapper.mapList(entities, HsOfficeRelationshipResource.class,
|
||||||
RELATION_ENTITY_TO_RESOURCE_POSTMAPPER);
|
RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||||
return ResponseEntity.ok(resources);
|
return ResponseEntity.ok(resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public ResponseEntity<HsOfficeRelationResource> addRelation(
|
public ResponseEntity<HsOfficeRelationshipResource> addRelationship(
|
||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final HsOfficeRelationInsertResource body) {
|
final HsOfficeRelationshipInsertResource body) {
|
||||||
|
|
||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var entityToSave = new HsOfficeRelationEntity();
|
final var entityToSave = new HsOfficeRelationshipEntity();
|
||||||
entityToSave.setType(HsOfficeRelationType.valueOf(body.getType()));
|
entityToSave.setRelType(HsOfficeRelationshipType.valueOf(body.getRelType()));
|
||||||
entityToSave.setAnchor(holderRepo.findByUuid(body.getAnchorUuid()).orElseThrow(
|
entityToSave.setRelAnchor(relHolderRepo.findByUuid(body.getRelAnchorUuid()).orElseThrow(
|
||||||
() -> new NoSuchElementException("cannot find anchorUuid " + body.getAnchorUuid())
|
() -> new NoSuchElementException("cannot find relAnchorUuid " + body.getRelAnchorUuid())
|
||||||
));
|
));
|
||||||
entityToSave.setHolder(holderRepo.findByUuid(body.getHolderUuid()).orElseThrow(
|
entityToSave.setRelHolder(relHolderRepo.findByUuid(body.getRelHolderUuid()).orElseThrow(
|
||||||
() -> new NoSuchElementException("cannot find holderUuid " + body.getHolderUuid())
|
() -> new NoSuchElementException("cannot find relHolderUuid " + body.getRelHolderUuid())
|
||||||
));
|
));
|
||||||
entityToSave.setContact(contactRepo.findByUuid(body.getContactUuid()).orElseThrow(
|
entityToSave.setContact(contactRepo.findByUuid(body.getContactUuid()).orElseThrow(
|
||||||
() -> new NoSuchElementException("cannot find contactUuid " + body.getContactUuid())
|
() -> new NoSuchElementException("cannot find contactUuid " + body.getContactUuid())
|
||||||
));
|
));
|
||||||
|
|
||||||
final var saved = relationRepo.save(entityToSave);
|
final var saved = relationshipRepo.save(entityToSave);
|
||||||
|
|
||||||
final var uri =
|
final var uri =
|
||||||
MvcUriComponentsBuilder.fromController(getClass())
|
MvcUriComponentsBuilder.fromController(getClass())
|
||||||
.path("/api/hs/office/relations/{id}")
|
.path("/api/hs/office/relationships/{id}")
|
||||||
.buildAndExpand(saved.getUuid())
|
.buildAndExpand(saved.getUuid())
|
||||||
.toUri();
|
.toUri();
|
||||||
final var mapped = mapper.map(saved, HsOfficeRelationResource.class,
|
final var mapped = mapper.map(saved, HsOfficeRelationshipResource.class,
|
||||||
RELATION_ENTITY_TO_RESOURCE_POSTMAPPER);
|
RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||||
return ResponseEntity.created(uri).body(mapped);
|
return ResponseEntity.created(uri).body(mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseEntity<HsOfficeRelationResource> getRelationByUuid(
|
public ResponseEntity<HsOfficeRelationshipResource> getRelationshipByUuid(
|
||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final UUID relationUuid) {
|
final UUID relationshipUuid) {
|
||||||
|
|
||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var result = relationRepo.findByUuid(relationUuid);
|
final var result = relationshipRepo.findByUuid(relationshipUuid);
|
||||||
if (result.isEmpty()) {
|
if (result.isEmpty()) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeRelationResource.class, RELATION_ENTITY_TO_RESOURCE_POSTMAPPER));
|
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeRelationshipResource.class, RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public ResponseEntity<Void> deleteRelationByUuid(
|
public ResponseEntity<Void> deleteRelationshipByUuid(
|
||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final UUID relationUuid) {
|
final UUID relationshipUuid) {
|
||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var result = relationRepo.deleteByUuid(relationUuid);
|
final var result = relationshipRepo.deleteByUuid(relationshipUuid);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
@ -126,27 +126,27 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public ResponseEntity<HsOfficeRelationResource> patchRelation(
|
public ResponseEntity<HsOfficeRelationshipResource> patchRelationship(
|
||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final UUID relationUuid,
|
final UUID relationshipUuid,
|
||||||
final HsOfficeRelationPatchResource body) {
|
final HsOfficeRelationshipPatchResource body) {
|
||||||
|
|
||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var current = relationRepo.findByUuid(relationUuid).orElseThrow();
|
final var current = relationshipRepo.findByUuid(relationshipUuid).orElseThrow();
|
||||||
|
|
||||||
new HsOfficeRelationEntityPatcher(em, current).apply(body);
|
new HsOfficeRelationshipEntityPatcher(em, current).apply(body);
|
||||||
|
|
||||||
final var saved = relationRepo.save(current);
|
final var saved = relationshipRepo.save(current);
|
||||||
final var mapped = mapper.map(saved, HsOfficeRelationResource.class);
|
final var mapped = mapper.map(saved, HsOfficeRelationshipResource.class);
|
||||||
return ResponseEntity.ok(mapped);
|
return ResponseEntity.ok(mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final BiConsumer<HsOfficeRelationEntity, HsOfficeRelationResource> RELATION_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
final BiConsumer<HsOfficeRelationshipEntity, HsOfficeRelationshipResource> RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||||
resource.setAnchor(mapper.map(entity.getAnchor(), HsOfficePersonResource.class));
|
resource.setRelAnchor(mapper.map(entity.getRelAnchor(), HsOfficePersonResource.class));
|
||||||
resource.setHolder(mapper.map(entity.getHolder(), HsOfficePersonResource.class));
|
resource.setRelHolder(mapper.map(entity.getRelHolder(), HsOfficePersonResource.class));
|
||||||
resource.setContact(mapper.map(entity.getContact(), HsOfficeContactResource.class));
|
resource.setContact(mapper.map(entity.getContact(), HsOfficeContactResource.class));
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
@ -24,49 +24,49 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
|||||||
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "hs_office_relation_rv")
|
@Table(name = "hs_office_relationship_rv")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@FieldNameConstants
|
@FieldNameConstants
|
||||||
public class HsOfficeRelationEntity implements HasUuid, Stringifyable {
|
public class HsOfficeRelationshipEntity implements HasUuid, Stringifyable {
|
||||||
|
|
||||||
private static Stringify<HsOfficeRelationEntity> toString = stringify(HsOfficeRelationEntity.class, "rel")
|
private static Stringify<HsOfficeRelationshipEntity> toString = stringify(HsOfficeRelationshipEntity.class, "rel")
|
||||||
.withProp(Fields.anchor, HsOfficeRelationEntity::getAnchor)
|
.withProp(Fields.relAnchor, HsOfficeRelationshipEntity::getRelAnchor)
|
||||||
.withProp(Fields.type, HsOfficeRelationEntity::getType)
|
.withProp(Fields.relType, HsOfficeRelationshipEntity::getRelType)
|
||||||
.withProp(Fields.mark, HsOfficeRelationEntity::getMark)
|
.withProp(Fields.relMark, HsOfficeRelationshipEntity::getRelMark)
|
||||||
.withProp(Fields.holder, HsOfficeRelationEntity::getHolder)
|
.withProp(Fields.relHolder, HsOfficeRelationshipEntity::getRelHolder)
|
||||||
.withProp(Fields.contact, HsOfficeRelationEntity::getContact);
|
.withProp(Fields.contact, HsOfficeRelationshipEntity::getContact);
|
||||||
|
|
||||||
private static Stringify<HsOfficeRelationEntity> toShortString = stringify(HsOfficeRelationEntity.class, "rel")
|
private static Stringify<HsOfficeRelationshipEntity> toShortString = stringify(HsOfficeRelationshipEntity.class, "rel")
|
||||||
.withProp(Fields.anchor, HsOfficeRelationEntity::getAnchor)
|
.withProp(Fields.relAnchor, HsOfficeRelationshipEntity::getRelAnchor)
|
||||||
.withProp(Fields.type, HsOfficeRelationEntity::getType)
|
.withProp(Fields.relType, HsOfficeRelationshipEntity::getRelType)
|
||||||
.withProp(Fields.holder, HsOfficeRelationEntity::getHolder);
|
.withProp(Fields.relHolder, HsOfficeRelationshipEntity::getRelHolder);
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "anchoruuid")
|
@JoinColumn(name = "relanchoruuid")
|
||||||
private HsOfficePersonEntity anchor;
|
private HsOfficePersonEntity relAnchor;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "holderuuid")
|
@JoinColumn(name = "relholderuuid")
|
||||||
private HsOfficePersonEntity holder;
|
private HsOfficePersonEntity relHolder;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "contactuuid")
|
@JoinColumn(name = "contactuuid")
|
||||||
private HsOfficeContactEntity contact;
|
private HsOfficeContactEntity contact;
|
||||||
|
|
||||||
@Column(name = "type")
|
@Column(name = "reltype")
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private HsOfficeRelationType type;
|
private HsOfficeRelationshipType relType;
|
||||||
|
|
||||||
@Column(name = "mark")
|
@Column(name = "relmark")
|
||||||
private String mark;
|
private String relMark;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -79,22 +79,22 @@ public class HsOfficeRelationEntity implements HasUuid, Stringifyable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static RbacView rbac() {
|
public static RbacView rbac() {
|
||||||
return rbacViewFor("relation", HsOfficeRelationEntity.class)
|
return rbacViewFor("relationship", HsOfficeRelationshipEntity.class)
|
||||||
.withIdentityView(SQL.projection("""
|
.withIdentityView(SQL.projection("""
|
||||||
(select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|
(select idName from hs_office_person_iv p where p.uuid = relAnchorUuid)
|
||||||
|| '-with-' || target.type || '-'
|
|| '-with-' || target.relType || '-'
|
||||||
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid)
|
|| (select idName from hs_office_person_iv p where p.uuid = relHolderUuid)
|
||||||
"""))
|
"""))
|
||||||
.withRestrictedViewOrderBy(SQL.expression(
|
.withRestrictedViewOrderBy(SQL.expression(
|
||||||
"(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)"))
|
"(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)"))
|
||||||
.withUpdatableColumns("contactUuid")
|
.withUpdatableColumns("contactUuid")
|
||||||
.importEntityAlias("anchorPerson", HsOfficePersonEntity.class,
|
.importEntityAlias("anchorPerson", HsOfficePersonEntity.class,
|
||||||
dependsOnColumn("anchorUuid"),
|
dependsOnColumn("relAnchorUuid"),
|
||||||
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.anchorUuid")
|
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.relAnchorUuid")
|
||||||
)
|
)
|
||||||
.importEntityAlias("holderPerson", HsOfficePersonEntity.class,
|
.importEntityAlias("holderPerson", HsOfficePersonEntity.class,
|
||||||
dependsOnColumn("holderUuid"),
|
dependsOnColumn("relHolderUuid"),
|
||||||
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.holderUuid")
|
fetchedBySql("select * from hs_office_person as p where p.uuid = ${REF}.relHolderUuid")
|
||||||
)
|
)
|
||||||
.importEntityAlias("contact", HsOfficeContactEntity.class,
|
.importEntityAlias("contact", HsOfficeContactEntity.class,
|
||||||
dependsOnColumn("contactUuid"),
|
dependsOnColumn("contactUuid"),
|
||||||
@ -129,6 +129,6 @@ public class HsOfficeRelationEntity implements HasUuid, Stringifyable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
rbac().generateWithBaseFileName("223-hs-office-relation-rbac");
|
rbac().generateWithBaseFileName("223-hs-office-relationship-rbac");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,25 +1,25 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationshipPatchResource;
|
||||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
class HsOfficeRelationEntityPatcher implements EntityPatcher<HsOfficeRelationPatchResource> {
|
class HsOfficeRelationshipEntityPatcher implements EntityPatcher<HsOfficeRelationshipPatchResource> {
|
||||||
|
|
||||||
private final EntityManager em;
|
private final EntityManager em;
|
||||||
private final HsOfficeRelationEntity entity;
|
private final HsOfficeRelationshipEntity entity;
|
||||||
|
|
||||||
HsOfficeRelationEntityPatcher(final EntityManager em, final HsOfficeRelationEntity entity) {
|
HsOfficeRelationshipEntityPatcher(final EntityManager em, final HsOfficeRelationshipEntity entity) {
|
||||||
this.em = em;
|
this.em = em;
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(final HsOfficeRelationPatchResource resource) {
|
public void apply(final HsOfficeRelationshipPatchResource resource) {
|
||||||
OptionalFromJson.of(resource.getContactUuid()).ifPresent(newValue -> {
|
OptionalFromJson.of(resource.getContactUuid()).ifPresent(newValue -> {
|
||||||
verifyNotNull(newValue, "contact");
|
verifyNotNull(newValue, "contact");
|
||||||
entity.setContact(em.getReference(HsOfficeContactEntity.class, newValue));
|
entity.setContact(em.getReference(HsOfficeContactEntity.class, newValue));
|
@ -0,0 +1,37 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface HsOfficeRelationshipRepository extends Repository<HsOfficeRelationshipEntity, UUID> {
|
||||||
|
|
||||||
|
Optional<HsOfficeRelationshipEntity> findByUuid(UUID id);
|
||||||
|
|
||||||
|
default List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuidAndRelationshipType(@NotNull UUID personUuid, HsOfficeRelationshipType relationshipType) {
|
||||||
|
return findRelationshipRelatedToPersonUuidAndRelationshipTypeString(personUuid, relationshipType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query(value = """
|
||||||
|
SELECT p.* FROM hs_office_relationship_rv AS p
|
||||||
|
WHERE p.relAnchorUuid = :personUuid OR p.relHolderUuid = :personUuid
|
||||||
|
""", nativeQuery = true)
|
||||||
|
List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuid(@NotNull UUID personUuid);
|
||||||
|
|
||||||
|
@Query(value = """
|
||||||
|
SELECT p.* FROM hs_office_relationship_rv AS p
|
||||||
|
WHERE (:relationshipType IS NULL OR p.relType = cast(:relationshipType AS HsOfficeRelationshipType))
|
||||||
|
AND ( p.relAnchorUuid = :personUuid OR p.relHolderUuid = :personUuid)
|
||||||
|
""", nativeQuery = true)
|
||||||
|
List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuidAndRelationshipTypeString(@NotNull UUID personUuid, String relationshipType);
|
||||||
|
|
||||||
|
HsOfficeRelationshipEntity save(final HsOfficeRelationshipEntity entity);
|
||||||
|
|
||||||
|
long count();
|
||||||
|
|
||||||
|
int deleteByUuid(UUID uuid);
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
public enum HsOfficeRelationType {
|
public enum HsOfficeRelationshipType {
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
PARTNER,
|
PARTNER,
|
||||||
EX_PARTNER,
|
EX_PARTNER,
|
||||||
REPRESENTATIVE,
|
REPRESENTATIVE,
|
||||||
VIP_CONTACT,
|
VIP_CONTACT,
|
||||||
DEBITOR,
|
ACCOUNTING,
|
||||||
OPERATIONS,
|
OPERATIONS,
|
||||||
SUBSCRIBER
|
SUBSCRIBER
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ import lombok.*;
|
|||||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||||
@ -103,11 +103,11 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid {
|
|||||||
.withRestrictedViewOrderBy(expression("validity"))
|
.withRestrictedViewOrderBy(expression("validity"))
|
||||||
.withUpdatableColumns("reference", "agreement", "validity")
|
.withUpdatableColumns("reference", "agreement", "validity")
|
||||||
|
|
||||||
.importEntityAlias("debitorRel", HsOfficeRelationEntity.class,
|
.importEntityAlias("debitorRel", HsOfficeRelationshipEntity.class,
|
||||||
dependsOnColumn("debitorUuid"),
|
dependsOnColumn("debitorUuid"),
|
||||||
fetchedBySql("""
|
fetchedBySql("""
|
||||||
SELECT debitorRel.*
|
SELECT debitorRel.*
|
||||||
FROM hs_office_relation debitorRel
|
FROM hs_office_relationship debitorRel
|
||||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||||
WHERE debitor.uuid = ${REF}.debitorUuid
|
WHERE debitor.uuid = ${REF}.debitorUuid
|
||||||
""")
|
""")
|
||||||
|
@ -23,7 +23,7 @@ public class InsertTriggerGenerator {
|
|||||||
|
|
||||||
void generateTo(final StringWriter plPgSql) {
|
void generateTo(final StringWriter plPgSql) {
|
||||||
generateLiquibaseChangesetHeader(plPgSql);
|
generateLiquibaseChangesetHeader(plPgSql);
|
||||||
generateGrantInsertRoleToExistingObjects(plPgSql);
|
generateGrantInsertRoleToExistingCustomers(plPgSql);
|
||||||
generateInsertPermissionGrantTrigger(plPgSql);
|
generateInsertPermissionGrantTrigger(plPgSql);
|
||||||
generateInsertCheckTrigger(plPgSql);
|
generateInsertCheckTrigger(plPgSql);
|
||||||
plPgSql.writeLn("--//");
|
plPgSql.writeLn("--//");
|
||||||
@ -38,7 +38,7 @@ public class InsertTriggerGenerator {
|
|||||||
with("liquibaseTagPrefix", liquibaseTagPrefix));
|
with("liquibaseTagPrefix", liquibaseTagPrefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGrantInsertRoleToExistingObjects(final StringWriter plPgSql) {
|
private void generateGrantInsertRoleToExistingCustomers(final StringWriter plPgSql) {
|
||||||
getOptionalInsertSuperRole().ifPresent( superRoleDef -> {
|
getOptionalInsertSuperRole().ifPresent( superRoleDef -> {
|
||||||
plPgSql.writeLn("""
|
plPgSql.writeLn("""
|
||||||
/*
|
/*
|
||||||
@ -100,7 +100,13 @@ public class InsertTriggerGenerator {
|
|||||||
|
|
||||||
private void generateInsertCheckTrigger(final StringWriter plPgSql) {
|
private void generateInsertCheckTrigger(final StringWriter plPgSql) {
|
||||||
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
||||||
if (g.getSuperRoleDef().getEntityAlias().isGlobal()) {
|
if (!g.getSuperRoleDef().getEntityAlias().isGlobal()) {
|
||||||
|
if (rbacDef.isRootEntityAlias(g.getSuperRoleDef().getEntityAlias())) {
|
||||||
|
generateInsertPermissionTriggerAllowByDirectRole(plPgSql, g);
|
||||||
|
} else {
|
||||||
|
generateInsertPermissionTriggerAllowByIndirectRole(plPgSql, g);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
switch (g.getSuperRoleDef().getRole()) {
|
switch (g.getSuperRoleDef().getRole()) {
|
||||||
case ADMIN -> {
|
case ADMIN -> {
|
||||||
generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql);
|
generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql);
|
||||||
@ -113,23 +119,27 @@ public class InsertTriggerGenerator {
|
|||||||
"invalid global role for INSERT permission: " + g.getSuperRoleDef().getRole());
|
"invalid global role for INSERT permission: " + g.getSuperRoleDef().getRole());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(plPgSql, g);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() -> {
|
() -> {
|
||||||
System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global.admin");
|
plPgSql.writeLn("""
|
||||||
generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql);
|
-- FIXME: Where is this case necessary?
|
||||||
|
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||||
|
before insert on ${rawSubTable}
|
||||||
|
for each row
|
||||||
|
-- As there is no explicit INSERT grant specified for this table,
|
||||||
|
-- only global admins are allowed to insert any rows.
|
||||||
|
when ( not isGlobalAdmin() )
|
||||||
|
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||||
|
""",
|
||||||
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) {
|
private void generateInsertPermissionTriggerAllowByDirectRole(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) {
|
||||||
plPgSql.writeLn("""
|
plPgSql.writeLn("""
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
|
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
|
||||||
where the check is performed by a direct role.
|
|
||||||
|
|
||||||
A direct role is a role depending on a foreign key directly available in the NEW row.
|
|
||||||
*/
|
*/
|
||||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
@ -149,11 +159,51 @@ public class InsertTriggerGenerator {
|
|||||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName()));
|
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateInsertPermissionTriggerAllowByIndirectRole(
|
||||||
|
final StringWriter plPgSql,
|
||||||
|
final RbacView.RbacGrantDefinition g) {
|
||||||
|
plPgSql.writeLn("""
|
||||||
|
/**
|
||||||
|
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
|
||||||
|
*/
|
||||||
|
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql as $$
|
||||||
|
begin
|
||||||
|
if ( not hasInsertPermission(
|
||||||
|
( SELECT ${varName}.uuid FROM
|
||||||
|
""",
|
||||||
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||||
|
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()));
|
||||||
|
plPgSql.indented(3, () -> {
|
||||||
|
plPgSql.writeLn(
|
||||||
|
"(" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ") AS ${varName}",
|
||||||
|
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()),
|
||||||
|
with("ref", NEW.name()));
|
||||||
|
});
|
||||||
|
plPgSql.writeLn("""
|
||||||
|
|
||||||
|
), 'INSERT', '${rawSubTable}') ) then
|
||||||
|
raise exception
|
||||||
|
'[403] insert into ${rawSubTable} not allowed for current subjects % (%)',
|
||||||
|
currentSubjects(), currentSubjectsUuids();
|
||||||
|
end if;
|
||||||
|
return NEW;
|
||||||
|
end; $$;
|
||||||
|
|
||||||
|
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||||
|
before insert on ${rawSubTable}
|
||||||
|
for each row
|
||||||
|
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||||
|
|
||||||
|
""",
|
||||||
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||||
|
}
|
||||||
|
|
||||||
private void generateInsertPermissionTriggerAllowOnlyGlobalAdmin(final StringWriter plPgSql) {
|
private void generateInsertPermissionTriggerAllowOnlyGlobalAdmin(final StringWriter plPgSql) {
|
||||||
plPgSql.writeLn("""
|
plPgSql.writeLn("""
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
|
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
|
||||||
where only global-admin has that permission.
|
|
||||||
*/
|
*/
|
||||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
|
@ -8,11 +8,13 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.StringWriter.with;
|
|||||||
public class RbacRestrictedViewGenerator {
|
public class RbacRestrictedViewGenerator {
|
||||||
private final RbacView rbacDef;
|
private final RbacView rbacDef;
|
||||||
private final String liquibaseTagPrefix;
|
private final String liquibaseTagPrefix;
|
||||||
|
private final String simpleEntityVarName;
|
||||||
private final String rawTableName;
|
private final String rawTableName;
|
||||||
|
|
||||||
public RbacRestrictedViewGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
|
public RbacRestrictedViewGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
|
||||||
this.rbacDef = rbacDef;
|
this.rbacDef = rbacDef;
|
||||||
this.liquibaseTagPrefix = liquibaseTagPrefix;
|
this.liquibaseTagPrefix = liquibaseTagPrefix;
|
||||||
|
this.simpleEntityVarName = rbacDef.getRootEntityAlias().simpleName();
|
||||||
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableName();
|
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,16 +25,16 @@ public class RbacRestrictedViewGenerator {
|
|||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('${rawTableName}',
|
call generateRbacRestrictedView('${rawTableName}',
|
||||||
$orderBy$
|
$orderBy$
|
||||||
${orderBy}
|
${orderBy}
|
||||||
$orderBy$,
|
$orderBy$,
|
||||||
$updates$
|
$updates$
|
||||||
${updates}
|
${updates}
|
||||||
$updates$);
|
$updates$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
""",
|
""",
|
||||||
with("liquibaseTagPrefix", liquibaseTagPrefix),
|
with("liquibaseTagPrefix", liquibaseTagPrefix),
|
||||||
with("orderBy", indented(rbacDef.getOrderBySqlExpression().sql, 2)),
|
with("orderBy", rbacDef.getOrderBySqlExpression().sql),
|
||||||
with("updates", indented(rbacDef.getUpdatableColumns().stream()
|
with("updates", indented(rbacDef.getUpdatableColumns().stream()
|
||||||
.map(c -> c + " = new." + c)
|
.map(c -> c + " = new." + c)
|
||||||
.collect(joining(",\n")), 2)),
|
.collect(joining(",\n")), 2)),
|
||||||
|
@ -11,7 +11,7 @@ import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
|||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
|
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
|
||||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
||||||
@ -812,7 +812,7 @@ public class RbacView {
|
|||||||
HsOfficePartnerDetailsEntity.class,
|
HsOfficePartnerDetailsEntity.class,
|
||||||
HsOfficeBankAccountEntity.class,
|
HsOfficeBankAccountEntity.class,
|
||||||
HsOfficeDebitorEntity.class,
|
HsOfficeDebitorEntity.class,
|
||||||
HsOfficeRelationEntity.class,
|
HsOfficeRelationshipEntity.class,
|
||||||
HsOfficeCoopAssetsTransactionEntity.class,
|
HsOfficeCoopAssetsTransactionEntity.class,
|
||||||
HsOfficeContactEntity.class,
|
HsOfficeContactEntity.class,
|
||||||
HsOfficeSepaMandateEntity.class,
|
HsOfficeSepaMandateEntity.class,
|
||||||
@ -831,7 +831,7 @@ public class RbacView {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.err.println("WARNING: no main method in: " + c.getName() + " => no RBAC rules generated");
|
System.err.println("no main method in: " + c.getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ map:
|
|||||||
null: org.openapitools.jackson.nullable.JsonNullable
|
null: org.openapitools.jackson.nullable.JsonNullable
|
||||||
/api/hs/office/persons/{personUUID}:
|
/api/hs/office/persons/{personUUID}:
|
||||||
null: org.openapitools.jackson.nullable.JsonNullable
|
null: org.openapitools.jackson.nullable.JsonNullable
|
||||||
/api/hs/office/relations/{relationUUID}:
|
/api/hs/office/relationships/{relationshipUUID}:
|
||||||
null: org.openapitools.jackson.nullable.JsonNullable
|
null: org.openapitools.jackson.nullable.JsonNullable
|
||||||
/api/hs/office/bankaccounts/{bankAccountUUID}:
|
/api/hs/office/bankaccounts/{bankAccountUUID}:
|
||||||
null: org.openapitools.jackson.nullable.JsonNullable
|
null: org.openapitools.jackson.nullable.JsonNullable
|
||||||
|
@ -10,7 +10,7 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
debitorRel:
|
debitorRel:
|
||||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||||
debitorNumber:
|
debitorNumber:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
@ -76,7 +76,7 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
debitorRel:
|
debitorRel:
|
||||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationInsert'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipInsert'
|
||||||
debitorRelUuid:
|
debitorRelUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
|
@ -14,8 +14,8 @@ components:
|
|||||||
format: int8
|
format: int8
|
||||||
minimum: 10000
|
minimum: 10000
|
||||||
maximum: 99999
|
maximum: 99999
|
||||||
partnerRel:
|
partnerRole:
|
||||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||||
details:
|
details:
|
||||||
$ref: '#/components/schemas/HsOfficePartnerDetails'
|
$ref: '#/components/schemas/HsOfficePartnerDetails'
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ components:
|
|||||||
HsOfficePartnerPatch:
|
HsOfficePartnerPatch:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
partnerRelUuid:
|
partnerRoleUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
nullable: true
|
||||||
@ -90,31 +90,31 @@ components:
|
|||||||
format: int8
|
format: int8
|
||||||
minimum: 10000
|
minimum: 10000
|
||||||
maximum: 99999
|
maximum: 99999
|
||||||
partnerRel:
|
partnerRole:
|
||||||
$ref: '#/components/schemas/HsOfficePartnerRelInsert'
|
$ref: '#/components/schemas/HsOfficePartnerRoleInsert'
|
||||||
details:
|
details:
|
||||||
$ref: '#/components/schemas/HsOfficePartnerDetailsInsert'
|
$ref: '#/components/schemas/HsOfficePartnerDetailsInsert'
|
||||||
required:
|
required:
|
||||||
- partnerNumber
|
- partnerNumber
|
||||||
- partnerRel
|
- partnerRole
|
||||||
- details
|
- details
|
||||||
|
|
||||||
HsOfficePartnerRelInsert:
|
HsOfficePartnerRoleInsert:
|
||||||
type: object
|
type: object
|
||||||
nullable: false
|
nullable: false
|
||||||
properties:
|
properties:
|
||||||
anchorUuid:
|
relAnchorUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
holderUuid:
|
relHolderUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
contactUuid:
|
contactUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
required:
|
required:
|
||||||
- anchorUuid
|
- relAnchorUuid
|
||||||
- holderUuid
|
- relHolderUuid
|
||||||
- relContactUuid
|
- relContactUuid
|
||||||
|
|
||||||
HsOfficePartnerDetailsInsert:
|
HsOfficePartnerDetailsInsert:
|
||||||
|
@ -3,37 +3,37 @@ components:
|
|||||||
|
|
||||||
schemas:
|
schemas:
|
||||||
|
|
||||||
HsOfficeRelationType:
|
HsOfficeRelationshipType:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- UNKNOWN
|
- UNKNOWN
|
||||||
- PARTNER
|
- PARTNER
|
||||||
- EX_PARTNER
|
- EX_PARTNER
|
||||||
- DEBITOR
|
- REPRESENTATIVE,
|
||||||
- REPRESENTATIVE
|
|
||||||
- VIP_CONTACT
|
- VIP_CONTACT
|
||||||
|
- ACCOUNTING,
|
||||||
- OPERATIONS
|
- OPERATIONS
|
||||||
- SUBSCRIBER
|
- SUBSCRIBER
|
||||||
|
|
||||||
HsOfficeRelation:
|
HsOfficeRelationship:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
uuid:
|
uuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
anchor:
|
relAnchor:
|
||||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||||
holder:
|
relHolder:
|
||||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||||
type:
|
relType:
|
||||||
type: string
|
type: string
|
||||||
mark:
|
relMark:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
contact:
|
contact:
|
||||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||||
|
|
||||||
HsOfficeRelationPatch:
|
HsOfficeRelationshipPatch:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
contactUuid:
|
contactUuid:
|
||||||
@ -41,25 +41,25 @@ components:
|
|||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
nullable: true
|
||||||
|
|
||||||
HsOfficeRelationInsert:
|
HsOfficeRelationshipInsert:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
anchorUuid:
|
relAnchorUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
holderUuid:
|
relHolderUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
type:
|
relType:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
mark:
|
relMark:
|
||||||
type: string
|
type: string
|
||||||
contactUuid:
|
contactUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
required:
|
required:
|
||||||
- anchorUuid
|
- relAnchorUuid
|
||||||
- holderUuid
|
- relHolderUuid
|
||||||
- type
|
- relType
|
||||||
- relContactUuid
|
- relContactUuid
|
@ -1,25 +1,25 @@
|
|||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- hs-office-relations
|
- hs-office-relationships
|
||||||
description: 'Fetch a single person relation by its uuid, if visible for the current subject.'
|
description: 'Fetch a single person relationship by its uuid, if visible for the current subject.'
|
||||||
operationId: getRelationByUuid
|
operationId: getRelationshipByUuid
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||||
- name: relationUUID
|
- name: relationshipUUID
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
description: UUID of the relation to fetch.
|
description: UUID of the relationship to fetch.
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
content:
|
content:
|
||||||
'application/json':
|
'application/json':
|
||||||
schema:
|
schema:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||||
|
|
||||||
"401":
|
"401":
|
||||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||||
@ -28,13 +28,13 @@ get:
|
|||||||
|
|
||||||
patch:
|
patch:
|
||||||
tags:
|
tags:
|
||||||
- hs-office-relations
|
- hs-office-relationships
|
||||||
description: 'Updates a single person relation by its uuid, if permitted for the current subject.'
|
description: 'Updates a single person relationship by its uuid, if permitted for the current subject.'
|
||||||
operationId: patchRelation
|
operationId: patchRelationship
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||||
- name: relationUUID
|
- name: relationshipUUID
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
@ -44,14 +44,14 @@ patch:
|
|||||||
content:
|
content:
|
||||||
'application/json':
|
'application/json':
|
||||||
schema:
|
schema:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelationPatch'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipPatch'
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
content:
|
content:
|
||||||
'application/json':
|
'application/json':
|
||||||
schema:
|
schema:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||||
"401":
|
"401":
|
||||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||||
"403":
|
"403":
|
||||||
@ -59,19 +59,19 @@ patch:
|
|||||||
|
|
||||||
delete:
|
delete:
|
||||||
tags:
|
tags:
|
||||||
- hs-office-relations
|
- hs-office-relationships
|
||||||
description: 'Delete a single person relation by its uuid, if permitted for the current subject.'
|
description: 'Delete a single person relationship by its uuid, if permitted for the current subject.'
|
||||||
operationId: deleteRelationByUuid
|
operationId: deleteRelationshipByUuid
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||||
- name: relationUUID
|
- name: relationshipUUID
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
description: UUID of the relation to delete.
|
description: UUID of the relationship to delete.
|
||||||
responses:
|
responses:
|
||||||
"204":
|
"204":
|
||||||
description: No Content
|
description: No Content
|
@ -1,9 +1,9 @@
|
|||||||
get:
|
get:
|
||||||
summary: Returns a list of (optionally filtered) person relations for a given person.
|
summary: Returns a list of (optionally filtered) person relationships for a given person.
|
||||||
description: Returns the list of (optionally filtered) person relations of a given person and which are visible to the current user or any of it's assumed roles.
|
description: Returns the list of (optionally filtered) person relationships of a given person and which are visible to the current user or any of it's assumed roles.
|
||||||
tags:
|
tags:
|
||||||
- hs-office-relations
|
- hs-office-relationships
|
||||||
operationId: listRelations
|
operationId: listRelationships
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||||
@ -13,13 +13,13 @@ get:
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
description: Prefix of name properties from holder or contact to filter the results.
|
description: Prefix of name properties from relHolder or contact to filter the results.
|
||||||
- name: relationType
|
- name: relationshipType
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelationType'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipType'
|
||||||
description: Prefix of name properties from holder or contact to filter the results.
|
description: Prefix of name properties from relHolder or contact to filter the results.
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
@ -28,17 +28,17 @@ get:
|
|||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||||
"401":
|
"401":
|
||||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||||
"403":
|
"403":
|
||||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||||
|
|
||||||
post:
|
post:
|
||||||
summary: Adds a new person relation.
|
summary: Adds a new person relationship.
|
||||||
tags:
|
tags:
|
||||||
- hs-office-relations
|
- hs-office-relationships
|
||||||
operationId: addRelation
|
operationId: addRelationship
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||||
@ -46,7 +46,7 @@ post:
|
|||||||
content:
|
content:
|
||||||
'application/json':
|
'application/json':
|
||||||
schema:
|
schema:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelationInsert'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipInsert'
|
||||||
required: true
|
required: true
|
||||||
responses:
|
responses:
|
||||||
"201":
|
"201":
|
||||||
@ -54,7 +54,7 @@ post:
|
|||||||
content:
|
content:
|
||||||
'application/json':
|
'application/json':
|
||||||
schema:
|
schema:
|
||||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||||
"401":
|
"401":
|
||||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||||
"403":
|
"403":
|
@ -35,13 +35,13 @@ paths:
|
|||||||
$ref: "./hs-office-persons-with-uuid.yaml"
|
$ref: "./hs-office-persons-with-uuid.yaml"
|
||||||
|
|
||||||
|
|
||||||
# Relations
|
# Relationships
|
||||||
|
|
||||||
/api/hs/office/relations:
|
/api/hs/office/relationships:
|
||||||
$ref: "./hs-office-relations.yaml"
|
$ref: "./hs-office-relationships.yaml"
|
||||||
|
|
||||||
/api/hs/office/relations/{relationUUID}:
|
/api/hs/office/relationships/{relationshipUUID}:
|
||||||
$ref: "./hs-office-relations-with-uuid.yaml"
|
$ref: "./hs-office-relationships-with-uuid.yaml"
|
||||||
|
|
||||||
|
|
||||||
# BankAccounts
|
# BankAccounts
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
### rbac customer
|
### rbac customer
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.425403022.
|
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.571772062.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
--liquibase formatted sql
|
--liquibase formatted sql
|
||||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-22T14:44:19.441879428.
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.584886824.
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
|
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
|
||||||
@ -37,8 +36,8 @@ begin
|
|||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
testCustomerOwner(NEW),
|
testCustomerOwner(NEW),
|
||||||
permissions => array['DELETE'],
|
permissions => array['DELETE'],
|
||||||
incomingSuperRoles => array[globalAdmin(unassumed())],
|
userUuids => array[currentUserUuid()],
|
||||||
userUuids => array[currentUserUuid()]
|
incomingSuperRoles => array[globalAdmin(unassumed())]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
@ -73,16 +72,15 @@ create trigger insertTriggerForTestCustomer_tg
|
|||||||
after insert on test_customer
|
after insert on test_customer
|
||||||
for each row
|
for each row
|
||||||
execute procedure insertTriggerForTestCustomer_tf();
|
execute procedure insertTriggerForTestCustomer_tf();
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to test_customer,
|
Checks if the user or assumed roles are allowed to insert a row to test_customer.
|
||||||
where only global-admin has that permission.
|
|
||||||
*/
|
*/
|
||||||
create or replace function test_customer_insert_permission_missing_tf()
|
create or replace function test_customer_insert_permission_missing_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
@ -95,10 +93,12 @@ end; $$;
|
|||||||
create trigger test_customer_insert_permission_check_tg
|
create trigger test_customer_insert_permission_check_tg
|
||||||
before insert on test_customer
|
before insert on test_customer
|
||||||
for each row
|
for each row
|
||||||
|
-- As there is no explicit INSERT grant specified for this table,
|
||||||
|
-- only global admins are allowed to insert any rows.
|
||||||
when ( not isGlobalAdmin() )
|
when ( not isGlobalAdmin() )
|
||||||
execute procedure test_customer_insert_permission_missing_tf();
|
execute procedure test_customer_insert_permission_missing_tf();
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
@ -106,15 +106,13 @@ create trigger test_customer_insert_permission_check_tg
|
|||||||
call generateRbacIdentityViewFromProjection('test_customer', $idName$
|
call generateRbacIdentityViewFromProjection('test_customer', $idName$
|
||||||
prefix
|
prefix
|
||||||
$idName$);
|
$idName$);
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('test_customer',
|
call generateRbacRestrictedView('test_customer',
|
||||||
$orderBy$
|
'reference',
|
||||||
reference
|
|
||||||
$orderBy$,
|
|
||||||
$updates$
|
$updates$
|
||||||
reference = new.reference,
|
reference = new.reference,
|
||||||
prefix = new.prefix,
|
prefix = new.prefix,
|
||||||
@ -122,3 +120,4 @@ call generateRbacRestrictedView('test_customer',
|
|||||||
$updates$);
|
$updates$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
### rbac package
|
### rbac package
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.484173294.
|
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.624847792.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
--liquibase formatted sql
|
--liquibase formatted sql
|
||||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-22T12:01:44.554331877.
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.625353859.
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-package-rbac-OBJECT:1 endDelimiter:--//
|
--changeset test-package-rbac-OBJECT:1 endDelimiter:--//
|
||||||
@ -34,12 +33,9 @@ declare
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
SELECT * FROM test_customer c
|
SELECT * FROM test_customer c
|
||||||
WHERE c.uuid= NEW.customerUuid
|
WHERE c.uuid= NEW.customerUuid
|
||||||
INTO newCustomer;
|
into newCustomer;
|
||||||
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s', NEW.customerUuid);
|
|
||||||
|
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
testPackageOwner(NEW),
|
testPackageOwner(NEW),
|
||||||
@ -79,8 +75,8 @@ create trigger insertTriggerForTestPackage_tg
|
|||||||
after insert on test_package
|
after insert on test_package
|
||||||
for each row
|
for each row
|
||||||
execute procedure insertTriggerForTestPackage_tf();
|
execute procedure insertTriggerForTestPackage_tf();
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-package-rbac-update-trigger:1 endDelimiter:--//
|
--changeset test-package-rbac-update-trigger:1 endDelimiter:--//
|
||||||
@ -105,18 +101,14 @@ begin
|
|||||||
|
|
||||||
SELECT * FROM test_customer c
|
SELECT * FROM test_customer c
|
||||||
WHERE c.uuid= OLD.customerUuid
|
WHERE c.uuid= OLD.customerUuid
|
||||||
INTO oldCustomer;
|
into oldCustomer;
|
||||||
assert oldCustomer.uuid is not null, format('oldCustomer must not be null for OLD.customerUuid = %s', OLD.customerUuid);
|
|
||||||
|
|
||||||
SELECT * FROM test_customer c
|
SELECT * FROM test_customer c
|
||||||
WHERE c.uuid= NEW.customerUuid
|
WHERE c.uuid= NEW.customerUuid
|
||||||
INTO newCustomer;
|
into newCustomer;
|
||||||
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s', NEW.customerUuid);
|
|
||||||
|
|
||||||
|
|
||||||
if NEW.customerUuid <> OLD.customerUuid then
|
if NEW.customerUuid <> OLD.customerUuid then
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'INSERT'), testCustomerAdmin(oldCustomer));
|
call revokePermissionFromRole(findPermissionId(OLD.uuid, 'INSERT'), testCustomerAdmin(oldCustomer));
|
||||||
|
|
||||||
call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer));
|
call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer));
|
||||||
call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer));
|
call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer));
|
||||||
@ -146,8 +138,8 @@ create trigger updateTriggerForTestPackage_tg
|
|||||||
after update on test_package
|
after update on test_package
|
||||||
for each row
|
for each row
|
||||||
execute procedure updateTriggerForTestPackage_tf();
|
execute procedure updateTriggerForTestPackage_tf();
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-package-rbac-INSERT:1 endDelimiter:--//
|
--changeset test-package-rbac-INSERT:1 endDelimiter:--//
|
||||||
@ -187,43 +179,29 @@ begin
|
|||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
|
||||||
create trigger z_test_package_test_customer_insert_tg
|
create trigger z_test_package_test_customer_insert_tg
|
||||||
after insert on test_customer
|
after insert on test_customer
|
||||||
for each row
|
for each row
|
||||||
execute procedure test_package_test_customer_insert_tf();
|
execute procedure test_package_test_customer_insert_tf();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to test_package,
|
Checks if the user or assumed roles are allowed to insert a row to test_package.
|
||||||
where the check is performed by an indirect role.
|
|
||||||
|
|
||||||
An indirect role is a role FIXME.
|
|
||||||
*/
|
*/
|
||||||
create or replace function test_package_insert_permission_missing_tf()
|
create or replace function test_package_insert_permission_missing_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
begin
|
begin
|
||||||
if ( not hasInsertPermission(
|
raise exception '[403] insert into test_package not allowed for current subjects % (%)',
|
||||||
( SELECT customer.uuid FROM
|
currentSubjects(), currentSubjectsUuids();
|
||||||
|
|
||||||
(SELECT * FROM test_customer c
|
|
||||||
WHERE c.uuid= NEW.customerUuid
|
|
||||||
) AS customer
|
|
||||||
|
|
||||||
), 'INSERT', 'test_package') ) then
|
|
||||||
raise exception
|
|
||||||
'[403] insert into test_package not allowed for current subjects % (%)',
|
|
||||||
currentSubjects(), currentSubjectsUuids();
|
|
||||||
end if;
|
|
||||||
return NEW;
|
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
create trigger test_package_insert_permission_check_tg
|
create trigger test_package_insert_permission_check_tg
|
||||||
before insert on test_package
|
before insert on test_package
|
||||||
for each row
|
for each row
|
||||||
|
when ( not hasInsertPermission(NEW.customerUuid, 'INSERT', 'test_package') )
|
||||||
execute procedure test_package_insert_permission_missing_tf();
|
execute procedure test_package_insert_permission_missing_tf();
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
@ -231,15 +209,13 @@ create trigger test_package_insert_permission_check_tg
|
|||||||
call generateRbacIdentityViewFromProjection('test_package', $idName$
|
call generateRbacIdentityViewFromProjection('test_package', $idName$
|
||||||
name
|
name
|
||||||
$idName$);
|
$idName$);
|
||||||
--//
|
|
||||||
|
|
||||||
|
--//
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('test_package',
|
call generateRbacRestrictedView('test_package',
|
||||||
$orderBy$
|
'name',
|
||||||
name
|
|
||||||
$orderBy$,
|
|
||||||
$updates$
|
$updates$
|
||||||
version = new.version,
|
version = new.version,
|
||||||
customerUuid = new.customerUuid,
|
customerUuid = new.customerUuid,
|
||||||
@ -247,3 +223,4 @@ call generateRbacRestrictedView('test_package',
|
|||||||
$updates$);
|
$updates$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
### rbac domain
|
### rbac domain
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.510830235.
|
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.644658132.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
--liquibase formatted sql
|
|
||||||
|
|
||||||
-- ============================================================================
|
|
||||||
--changeset hs-office-relation-MAIN-TABLE:1 endDelimiter:--//
|
|
||||||
-- ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TYPE HsOfficeRelationType AS ENUM (
|
|
||||||
'UNKNOWN',
|
|
||||||
'PARTNER',
|
|
||||||
'EX_PARTNER',
|
|
||||||
'REPRESENTATIVE',
|
|
||||||
'DEBITOR',
|
|
||||||
'VIP_CONTACT',
|
|
||||||
'OPERATIONS',
|
|
||||||
'SUBSCRIBER');
|
|
||||||
|
|
||||||
CREATE CAST (character varying as HsOfficeRelationType) WITH INOUT AS IMPLICIT;
|
|
||||||
|
|
||||||
create table if not exists hs_office_relation
|
|
||||||
(
|
|
||||||
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
|
|
||||||
anchorUuid uuid not null references hs_office_person(uuid),
|
|
||||||
holderUuid uuid not null references hs_office_person(uuid),
|
|
||||||
contactUuid uuid references hs_office_contact(uuid),
|
|
||||||
type HsOfficeRelationType not null,
|
|
||||||
mark varchar(24)
|
|
||||||
);
|
|
||||||
--//
|
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
|
||||||
--changeset hs-office-relation-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
|
||||||
-- ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
call create_journal('hs_office_relation');
|
|
||||||
--//
|
|
@ -0,0 +1,36 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE TYPE HsOfficeRelationshipType AS ENUM (
|
||||||
|
'UNKNOWN',
|
||||||
|
'PARTNER',
|
||||||
|
'EX_PARTNER',
|
||||||
|
'REPRESENTATIVE',
|
||||||
|
'VIP_CONTACT',
|
||||||
|
'ACCOUNTING',
|
||||||
|
'OPERATIONS',
|
||||||
|
'SUBSCRIBER');
|
||||||
|
|
||||||
|
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT;
|
||||||
|
|
||||||
|
create table if not exists hs_office_relationship
|
||||||
|
(
|
||||||
|
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
|
||||||
|
relAnchorUuid uuid not null references hs_office_person(uuid),
|
||||||
|
relHolderUuid uuid not null references hs_office_person(uuid),
|
||||||
|
contactUuid uuid references hs_office_contact(uuid),
|
||||||
|
relType HsOfficeRelationshipType not null,
|
||||||
|
relMark varchar(24)
|
||||||
|
);
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs-office-relationship-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
call create_journal('hs_office_relationship');
|
||||||
|
--//
|
@ -1,4 +1,4 @@
|
|||||||
### rbac relation
|
### rbac relationship
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-15T17:17:00.854621634.
|
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-15T17:17:00.854621634.
|
||||||
|
|
||||||
@ -45,31 +45,31 @@ subgraph contact["`**contact**`"]
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph relation["`**relation**`"]
|
subgraph relationship["`**relationship**`"]
|
||||||
direction TB
|
direction TB
|
||||||
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
style relationship fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
subgraph relation:roles[ ]
|
subgraph relationship:roles[ ]
|
||||||
style relation:roles fill:#dd4901,stroke:white
|
style relationship:roles fill:#dd4901,stroke:white
|
||||||
|
|
||||||
role:relation:owner[[relation:owner]]
|
role:relationship:owner[[relationship:owner]]
|
||||||
role:relation:admin[[relation:admin]]
|
role:relationship:admin[[relationship:admin]]
|
||||||
role:relation:agent[[relation:agent]]
|
role:relationship:agent[[relationship:agent]]
|
||||||
role:relation:tenant[[relation:tenant]]
|
role:relationship:tenant[[relationship:tenant]]
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph relation:permissions[ ]
|
subgraph relationship:permissions[ ]
|
||||||
style relation:permissions fill:#dd4901,stroke:white
|
style relationship:permissions fill:#dd4901,stroke:white
|
||||||
|
|
||||||
perm:relation:DELETE{{relation:DELETE}}
|
perm:relationship:DELETE{{relationship:DELETE}}
|
||||||
perm:relation:UPDATE{{relation:UPDATE}}
|
perm:relationship:UPDATE{{relationship:UPDATE}}
|
||||||
perm:relation:SELECT{{relation:SELECT}}
|
perm:relationship:SELECT{{relationship:SELECT}}
|
||||||
perm:relation:INSERT{{relation:INSERT}}
|
perm:relationship:INSERT{{relationship:INSERT}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%% granting roles to users
|
%% granting roles to users
|
||||||
user:creator ==> role:relation:owner
|
user:creator ==> role:relationship:owner
|
||||||
|
|
||||||
%% granting roles to roles
|
%% granting roles to roles
|
||||||
role:global:admin -.-> role:anchorPerson:owner
|
role:global:admin -.-> role:anchorPerson:owner
|
||||||
@ -81,22 +81,22 @@ role:holderPerson:admin -.-> role:holderPerson:referrer
|
|||||||
role:global:admin -.-> role:contact:owner
|
role:global:admin -.-> role:contact:owner
|
||||||
role:contact:owner -.-> role:contact:admin
|
role:contact:owner -.-> role:contact:admin
|
||||||
role:contact:admin -.-> role:contact:referrer
|
role:contact:admin -.-> role:contact:referrer
|
||||||
role:global:admin ==> role:relation:owner
|
role:global:admin ==> role:relationship:owner
|
||||||
role:relation:owner ==> role:relation:admin
|
role:relationship:owner ==> role:relationship:admin
|
||||||
role:anchorPerson:admin ==> role:relation:admin
|
role:anchorPerson:admin ==> role:relationship:admin
|
||||||
role:relation:admin ==> role:relation:agent
|
role:relationship:admin ==> role:relationship:agent
|
||||||
role:holderPerson:admin ==> role:relation:agent
|
role:holderPerson:admin ==> role:relationship:agent
|
||||||
role:relation:agent ==> role:relation:tenant
|
role:relationship:agent ==> role:relationship:tenant
|
||||||
role:holderPerson:admin ==> role:relation:tenant
|
role:holderPerson:admin ==> role:relationship:tenant
|
||||||
role:contact:admin ==> role:relation:tenant
|
role:contact:admin ==> role:relationship:tenant
|
||||||
role:relation:tenant ==> role:anchorPerson:referrer
|
role:relationship:tenant ==> role:anchorPerson:referrer
|
||||||
role:relation:tenant ==> role:holderPerson:referrer
|
role:relationship:tenant ==> role:holderPerson:referrer
|
||||||
role:relation:tenant ==> role:contact:referrer
|
role:relationship:tenant ==> role:contact:referrer
|
||||||
|
|
||||||
%% granting permissions to roles
|
%% granting permissions to roles
|
||||||
role:relation:owner ==> perm:relation:DELETE
|
role:relationship:owner ==> perm:relationship:DELETE
|
||||||
role:relation:admin ==> perm:relation:UPDATE
|
role:relationship:admin ==> perm:relationship:UPDATE
|
||||||
role:relation:tenant ==> perm:relation:SELECT
|
role:relationship:tenant ==> perm:relationship:SELECT
|
||||||
role:anchorPerson:admin ==> perm:relation:INSERT
|
role:anchorPerson:admin ==> perm:relationship:INSERT
|
||||||
|
|
||||||
```
|
```
|
@ -3,29 +3,29 @@
|
|||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-OBJECT:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-OBJECT:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRelatedRbacObject('hs_office_relation');
|
call generateRelatedRbacObject('hs_office_relationship');
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRoleDescriptors('hsOfficeRelation', 'hs_office_relation');
|
call generateRbacRoleDescriptors('hsOfficeRelationship', 'hs_office_relationship');
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-insert-trigger:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-insert-trigger:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create or replace procedure buildRbacSystemForHsOfficeRelation(
|
create or replace procedure buildRbacSystemForHsOfficeRelationship(
|
||||||
NEW hs_office_relation
|
NEW hs_office_relationship
|
||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
@ -37,43 +37,43 @@ declare
|
|||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_person as p where p.uuid = NEW.holderUuid INTO newHolderPerson;
|
select * from hs_office_person as p where p.uuid = NEW.relHolderUuid INTO newHolderPerson;
|
||||||
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
|
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.relHolderUuid = %s', NEW.relHolderUuid);
|
||||||
|
|
||||||
select * from hs_office_person as p where p.uuid = NEW.anchorUuid INTO newAnchorPerson;
|
select * from hs_office_person as p where p.uuid = NEW.relAnchorUuid INTO newAnchorPerson;
|
||||||
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
|
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.relAnchorUuid = %s', NEW.relAnchorUuid);
|
||||||
|
|
||||||
select * from hs_office_contact as c where c.uuid = NEW.contactUuid INTO newContact;
|
select * from hs_office_contact as c where c.uuid = NEW.contactUuid INTO newContact;
|
||||||
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
|
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
|
||||||
|
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationOwner(NEW),
|
hsOfficeRelationshipOwner(NEW),
|
||||||
permissions => array['DELETE'],
|
permissions => array['DELETE'],
|
||||||
incomingSuperRoles => array[globalAdmin()],
|
incomingSuperRoles => array[globalAdmin()],
|
||||||
userUuids => array[currentUserUuid()]
|
userUuids => array[currentUserUuid()]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationAdmin(NEW),
|
hsOfficeRelationshipAdmin(NEW),
|
||||||
permissions => array['UPDATE'],
|
permissions => array['UPDATE'],
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficeRelationOwner(NEW),
|
hsOfficeRelationshipOwner(NEW),
|
||||||
hsOfficePersonAdmin(newAnchorPerson)]
|
hsOfficePersonAdmin(newAnchorPerson)]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationAgent(NEW),
|
hsOfficeRelationshipAgent(NEW),
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficePersonAdmin(newHolderPerson),
|
hsOfficePersonAdmin(newHolderPerson),
|
||||||
hsOfficeRelationAdmin(NEW)]
|
hsOfficeRelationshipAdmin(NEW)]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationTenant(NEW),
|
hsOfficeRelationshipTenant(NEW),
|
||||||
permissions => array['SELECT'],
|
permissions => array['SELECT'],
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficeRelationAgent(NEW),
|
hsOfficeRelationshipAgent(NEW),
|
||||||
hsOfficeContactAdmin(newContact),
|
hsOfficeContactAdmin(newContact),
|
||||||
hsOfficePersonAdmin(newHolderPerson)],
|
hsOfficePersonAdmin(newHolderPerson)],
|
||||||
outgoingSubRoles => array[
|
outgoingSubRoles => array[
|
||||||
@ -86,36 +86,36 @@ begin
|
|||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_relation row.
|
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_relationship row.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create or replace function insertTriggerForHsOfficeRelation_tf()
|
create or replace function insertTriggerForHsOfficeRelationship_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
call buildRbacSystemForHsOfficeRelation(NEW);
|
call buildRbacSystemForHsOfficeRelationship(NEW);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
create trigger insertTriggerForHsOfficeRelation_tg
|
create trigger insertTriggerForHsOfficeRelationship_tg
|
||||||
after insert on hs_office_relation
|
after insert on hs_office_relationship
|
||||||
for each row
|
for each row
|
||||||
execute procedure insertTriggerForHsOfficeRelation_tf();
|
execute procedure insertTriggerForHsOfficeRelationship_tf();
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-update-trigger:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-update-trigger:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create or replace procedure updateRbacRulesForHsOfficeRelation(
|
create or replace procedure updateRbacRulesForHsOfficeRelationship(
|
||||||
OLD hs_office_relation,
|
OLD hs_office_relationship,
|
||||||
NEW hs_office_relation
|
NEW hs_office_relationship
|
||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
@ -130,17 +130,17 @@ declare
|
|||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_person as p where p.uuid = OLD.holderUuid INTO oldHolderPerson;
|
select * from hs_office_person as p where p.uuid = OLD.relHolderUuid INTO oldHolderPerson;
|
||||||
assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid);
|
assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.relHolderUuid = %s', OLD.relHolderUuid);
|
||||||
|
|
||||||
select * from hs_office_person as p where p.uuid = NEW.holderUuid INTO newHolderPerson;
|
select * from hs_office_person as p where p.uuid = NEW.relHolderUuid INTO newHolderPerson;
|
||||||
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
|
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.relHolderUuid = %s', NEW.relHolderUuid);
|
||||||
|
|
||||||
select * from hs_office_person as p where p.uuid = OLD.anchorUuid INTO oldAnchorPerson;
|
select * from hs_office_person as p where p.uuid = OLD.relAnchorUuid INTO oldAnchorPerson;
|
||||||
assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid);
|
assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.relAnchorUuid = %s', OLD.relAnchorUuid);
|
||||||
|
|
||||||
select * from hs_office_person as p where p.uuid = NEW.anchorUuid INTO newAnchorPerson;
|
select * from hs_office_person as p where p.uuid = NEW.relAnchorUuid INTO newAnchorPerson;
|
||||||
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
|
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.relAnchorUuid = %s', NEW.relAnchorUuid);
|
||||||
|
|
||||||
select * from hs_office_contact as c where c.uuid = OLD.contactUuid INTO oldContact;
|
select * from hs_office_contact as c where c.uuid = OLD.contactUuid INTO oldContact;
|
||||||
assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid);
|
assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid);
|
||||||
@ -151,11 +151,11 @@ begin
|
|||||||
|
|
||||||
if NEW.contactUuid <> OLD.contactUuid then
|
if NEW.contactUuid <> OLD.contactUuid then
|
||||||
|
|
||||||
call revokeRoleFromRole(hsOfficeRelationTenant(OLD), hsOfficeContactAdmin(oldContact));
|
call revokeRoleFromRole(hsOfficeRelationshipTenant(OLD), hsOfficeContactAdmin(oldContact));
|
||||||
call grantRoleToRole(hsOfficeRelationTenant(NEW), hsOfficeContactAdmin(newContact));
|
call grantRoleToRole(hsOfficeRelationshipTenant(NEW), hsOfficeContactAdmin(newContact));
|
||||||
|
|
||||||
call revokeRoleFromRole(hsOfficeContactReferrer(oldContact), hsOfficeRelationTenant(OLD));
|
call revokeRoleFromRole(hsOfficeContactReferrer(oldContact), hsOfficeRelationshipTenant(OLD));
|
||||||
call grantRoleToRole(hsOfficeContactReferrer(newContact), hsOfficeRelationTenant(NEW));
|
call grantRoleToRole(hsOfficeContactReferrer(newContact), hsOfficeRelationshipTenant(NEW));
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
@ -163,31 +163,31 @@ begin
|
|||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_relation row.
|
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_relationship row.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create or replace function updateTriggerForHsOfficeRelation_tf()
|
create or replace function updateTriggerForHsOfficeRelationship_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
call updateRbacRulesForHsOfficeRelation(OLD, NEW);
|
call updateRbacRulesForHsOfficeRelationship(OLD, NEW);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
create trigger updateTriggerForHsOfficeRelation_tg
|
create trigger updateTriggerForHsOfficeRelationship_tg
|
||||||
after update on hs_office_relation
|
after update on hs_office_relationship
|
||||||
for each row
|
for each row
|
||||||
execute procedure updateTriggerForHsOfficeRelation_tf();
|
execute procedure updateTriggerForHsOfficeRelationship_tf();
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-INSERT:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-INSERT:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates INSERT INTO hs_office_relation permissions for the related hs_office_person rows.
|
Creates INSERT INTO hs_office_relationship permissions for the related hs_office_person rows.
|
||||||
*/
|
*/
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
declare
|
declare
|
||||||
@ -195,80 +195,80 @@ do language plpgsql $$
|
|||||||
permissionUuid uuid;
|
permissionUuid uuid;
|
||||||
roleUuid uuid;
|
roleUuid uuid;
|
||||||
begin
|
begin
|
||||||
call defineContext('create INSERT INTO hs_office_relation permissions for the related hs_office_person rows');
|
call defineContext('create INSERT INTO hs_office_relationship permissions for the related hs_office_person rows');
|
||||||
|
|
||||||
FOR row IN SELECT * FROM hs_office_person
|
FOR row IN SELECT * FROM hs_office_person
|
||||||
LOOP
|
LOOP
|
||||||
roleUuid := findRoleId(hsOfficePersonAdmin(row));
|
roleUuid := findRoleId(hsOfficePersonAdmin(row));
|
||||||
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_relation');
|
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_relationship');
|
||||||
call grantPermissionToRole(permissionUuid, roleUuid);
|
call grantPermissionToRole(permissionUuid, roleUuid);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adds hs_office_relation INSERT permission to specified role of new hs_office_person rows.
|
Adds hs_office_relationship INSERT permission to specified role of new hs_office_person rows.
|
||||||
*/
|
*/
|
||||||
create or replace function hs_office_relation_hs_office_person_insert_tf()
|
create or replace function hs_office_relationship_hs_office_person_insert_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
call grantPermissionToRole(
|
call grantPermissionToRole(
|
||||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'),
|
createPermission(NEW.uuid, 'INSERT', 'hs_office_relationship'),
|
||||||
hsOfficePersonAdmin(NEW));
|
hsOfficePersonAdmin(NEW));
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
create trigger z_hs_office_relation_hs_office_person_insert_tg
|
create trigger z_hs_office_relationship_hs_office_person_insert_tg
|
||||||
after insert on hs_office_person
|
after insert on hs_office_person
|
||||||
for each row
|
for each row
|
||||||
execute procedure hs_office_relation_hs_office_person_insert_tf();
|
execute procedure hs_office_relationship_hs_office_person_insert_tf();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_relation.
|
Checks if the user or assumed roles are allowed to insert a row to hs_office_relationship.
|
||||||
*/
|
*/
|
||||||
create or replace function hs_office_relation_insert_permission_missing_tf()
|
create or replace function hs_office_relationship_insert_permission_missing_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
begin
|
begin
|
||||||
if ( not hasInsertPermission(
|
if ( not hasInsertPermission(
|
||||||
( SELECT anchorPerson.uuid FROM
|
( SELECT anchorPerson.uuid FROM
|
||||||
|
|
||||||
(select * from hs_office_person as p where p.uuid = NEW.anchorUuid) AS anchorPerson
|
(select * from hs_office_person as p where p.uuid = NEW.relAnchorUuid) AS anchorPerson
|
||||||
|
|
||||||
), 'INSERT', 'hs_office_relation') ) then
|
), 'INSERT', 'hs_office_relationship') ) then
|
||||||
raise exception
|
raise exception
|
||||||
'[403] insert into hs_office_relation not allowed for current subjects % (%)',
|
'[403] insert into hs_office_relationship not allowed for current subjects % (%)',
|
||||||
currentSubjects(), currentSubjectsUuids();
|
currentSubjects(), currentSubjectsUuids();
|
||||||
end if;
|
end if;
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
create trigger hs_office_relation_insert_permission_check_tg
|
create trigger hs_office_relationship_insert_permission_check_tg
|
||||||
before insert on hs_office_relation
|
before insert on hs_office_relationship
|
||||||
for each row
|
for each row
|
||||||
execute procedure hs_office_relation_insert_permission_missing_tf();
|
execute procedure hs_office_relationship_insert_permission_missing_tf();
|
||||||
--//
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
call generateRbacIdentityViewFromProjection('hs_office_relation', $idName$
|
call generateRbacIdentityViewFromProjection('hs_office_relationship', $idName$
|
||||||
(select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|
(select idName from hs_office_person_iv p where p.uuid = relAnchorUuid)
|
||||||
|| '-with-' || target.type || '-'
|
|| '-with-' || target.relType || '-'
|
||||||
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid)
|
|| (select idName from hs_office_person_iv p where p.uuid = relHolderUuid)
|
||||||
|
|
||||||
$idName$);
|
$idName$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
--changeset hs-office-relationship-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('hs_office_relation',
|
call generateRbacRestrictedView('hs_office_relationship',
|
||||||
$orderBy$
|
$orderBy$
|
||||||
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
|
(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)
|
||||||
$orderBy$,
|
$orderBy$,
|
||||||
$updates$
|
$updates$
|
||||||
contactUuid = new.contactUuid
|
contactUuid = new.contactUuid
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
--changeset hs-office-relationship-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates a single relation test record.
|
Creates a single relationship test record.
|
||||||
*/
|
*/
|
||||||
create or replace procedure createHsOfficeRelationTestData(
|
create or replace procedure createHsOfficeRelationshipTestData(
|
||||||
holderPersonName varchar,
|
holderPersonName varchar,
|
||||||
relationType HsOfficeRelationType,
|
relationshipType HsOfficeRelationshipType,
|
||||||
anchorPersonName varchar,
|
anchorPersonName varchar,
|
||||||
contactLabel varchar,
|
contactLabel varchar,
|
||||||
mark varchar default null)
|
mark varchar default null)
|
||||||
@ -24,7 +24,7 @@ declare
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName);
|
idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName);
|
||||||
currentTask := 'creating relation test-data ' || idName;
|
currentTask := 'creating relationship test-data ' || idName;
|
||||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
||||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||||
|
|
||||||
@ -49,20 +49,20 @@ begin
|
|||||||
raise exception 'contact "%" not found', contactLabel;
|
raise exception 'contact "%" not found', contactLabel;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
raise notice 'creating test relation: %', idName;
|
raise notice 'creating test relationship: %', idName;
|
||||||
raise notice '- using anchor person (%): %', anchorPerson.uuid, anchorPerson;
|
raise notice '- using anchor person (%): %', anchorPerson.uuid, anchorPerson;
|
||||||
raise notice '- using holder person (%): %', holderPerson.uuid, holderPerson;
|
raise notice '- using holder person (%): %', holderPerson.uuid, holderPerson;
|
||||||
raise notice '- using contact (%): %', contact.uuid, contact;
|
raise notice '- using contact (%): %', contact.uuid, contact;
|
||||||
insert
|
insert
|
||||||
into hs_office_relation (uuid, anchoruuid, holderuuid, type, mark, contactUuid)
|
into hs_office_relationship (uuid, relanchoruuid, relholderuuid, reltype, relmark, contactUuid)
|
||||||
values (uuid_generate_v4(), anchorPerson.uuid, holderPerson.uuid, relationType, mark, contact.uuid);
|
values (uuid_generate_v4(), anchorPerson.uuid, holderPerson.uuid, relationshipType, mark, contact.uuid);
|
||||||
end; $$;
|
end; $$;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates a range of test relation for mass data generation.
|
Creates a range of test relationship for mass data generation.
|
||||||
*/
|
*/
|
||||||
create or replace procedure createHsOfficeRelationTestData(
|
create or replace procedure createHsOfficeRelationshipTestData(
|
||||||
startCount integer, -- count of auto generated rows before the run
|
startCount integer, -- count of auto generated rows before the run
|
||||||
endCount integer -- count of auto generated rows after the run
|
endCount integer -- count of auto generated rows after the run
|
||||||
)
|
)
|
||||||
@ -76,7 +76,7 @@ begin
|
|||||||
select p.* from hs_office_person p where tradeName = intToVarChar(t, 4) into person;
|
select p.* from hs_office_person p where tradeName = intToVarChar(t, 4) into person;
|
||||||
select c.* from hs_office_contact c where c.label = intToVarChar(t, 4) || '#' || t into contact;
|
select c.* from hs_office_contact c where c.label = intToVarChar(t, 4) || '#' || t into contact;
|
||||||
|
|
||||||
call createHsOfficeRelationTestData(person.uuid, contact.uuid, 'REPRESENTATIVE');
|
call createHsOfficeRelationshipTestData(person.uuid, contact.uuid, 'REPRESENTATIVE');
|
||||||
commit;
|
commit;
|
||||||
end loop;
|
end loop;
|
||||||
end; $$;
|
end; $$;
|
||||||
@ -84,30 +84,30 @@ end; $$;
|
|||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-relation-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
--changeset hs-office-relationship-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
call createHsOfficeRelationTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
|
call createHsOfficeRelationshipTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
|
||||||
call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
call createHsOfficeRelationshipTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
||||||
call createHsOfficeRelationTestData('First GmbH', 'DEBITOR', 'First GmbH', 'first contact');
|
call createHsOfficeRelationshipTestData('First GmbH', 'ACCOUNTING', 'First GmbH', 'first contact');
|
||||||
|
|
||||||
call createHsOfficeRelationTestData('Second e.K.', 'PARTNER', 'Hostsharing eG', 'second contact');
|
call createHsOfficeRelationshipTestData('Second e.K.', 'PARTNER', 'Hostsharing eG', 'second contact');
|
||||||
call createHsOfficeRelationTestData('Smith', 'REPRESENTATIVE', 'Second e.K.', 'second contact');
|
call createHsOfficeRelationshipTestData('Smith', 'REPRESENTATIVE', 'Second e.K.', 'second contact');
|
||||||
call createHsOfficeRelationTestData('Second e.K.', 'DEBITOR', 'Second e.K.', 'second contact');
|
call createHsOfficeRelationshipTestData('Second e.K.', 'ACCOUNTING', 'Second e.K.', 'second contact');
|
||||||
|
|
||||||
call createHsOfficeRelationTestData('Third OHG', 'PARTNER', 'Hostsharing eG', 'third contact');
|
call createHsOfficeRelationshipTestData('Third OHG', 'PARTNER', 'Hostsharing eG', 'third contact');
|
||||||
call createHsOfficeRelationTestData('Tucker', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
call createHsOfficeRelationshipTestData('Tucker', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
||||||
call createHsOfficeRelationTestData('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
|
call createHsOfficeRelationshipTestData('Third OHG', 'ACCOUNTING', 'Third OHG', 'third contact');
|
||||||
|
|
||||||
call createHsOfficeRelationTestData('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact');
|
call createHsOfficeRelationshipTestData('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact');
|
||||||
call createHsOfficeRelationTestData('Fouler', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
call createHsOfficeRelationshipTestData('Fouler', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
||||||
call createHsOfficeRelationTestData('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
|
call createHsOfficeRelationshipTestData('Third OHG', 'ACCOUNTING', 'Third OHG', 'third contact');
|
||||||
|
|
||||||
call createHsOfficeRelationTestData('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact');
|
call createHsOfficeRelationshipTestData('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact');
|
||||||
call createHsOfficeRelationTestData('Smith', 'DEBITOR', 'Smith', 'third contact');
|
call createHsOfficeRelationshipTestData('Smith', 'ACCOUNTING', 'Smith', 'third contact');
|
||||||
call createHsOfficeRelationTestData('Smith', 'SUBSCRIBER', 'Third OHG', 'third contact', 'members-announce');
|
call createHsOfficeRelationshipTestData('Smith', 'SUBSCRIBER', 'Third OHG', 'third contact', 'members-announce');
|
||||||
end;
|
end;
|
||||||
$$;
|
$$;
|
||||||
--//
|
--//
|
@ -33,7 +33,7 @@ create table hs_office_partner
|
|||||||
(
|
(
|
||||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||||
partnerNumber numeric(5) unique not null,
|
partnerNumber numeric(5) unique not null,
|
||||||
partnerRelUuid uuid not null references hs_office_relation(uuid), -- TODO: delete in after delete trigger
|
partnerRoleUuid uuid not null references hs_office_relationship(uuid), -- TODO: delete in after delete trigger
|
||||||
detailsUuid uuid not null references hs_office_partner_details(uuid) -- deleted in after delete trigger
|
detailsUuid uuid not null references hs_office_partner_details(uuid) -- deleted in after delete trigger
|
||||||
);
|
);
|
||||||
--//
|
--//
|
||||||
|
@ -30,24 +30,24 @@ create or replace procedure buildRbacSystemForHsOfficePartner(
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
declare
|
||||||
newPartnerRel hs_office_relation;
|
newPartnerRel hs_office_relationship;
|
||||||
newPartnerDetails hs_office_partner_details;
|
newPartnerDetails hs_office_partner_details;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
SELECT * FROM hs_office_relation AS r WHERE r.uuid = NEW.partnerRelUuid INTO newPartnerRel;
|
SELECT * FROM hs_office_relationship AS r WHERE r.uuid = NEW.partnerRoleUuid INTO newPartnerRel;
|
||||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
|
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRoleUuid = %s', NEW.partnerRoleUuid);
|
||||||
|
|
||||||
SELECT * FROM hs_office_partner_details AS d WHERE d.uuid = NEW.detailsUuid INTO newPartnerDetails;
|
SELECT * FROM hs_office_partner_details AS d WHERE d.uuid = NEW.detailsUuid INTO newPartnerDetails;
|
||||||
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
|
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
|
||||||
|
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationshipAdmin(newPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationshipTenant(newPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
|
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationshipAdmin(newPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel));
|
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
|
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
end; $$;
|
end; $$;
|
||||||
@ -87,19 +87,19 @@ create or replace procedure updateRbacRulesForHsOfficePartner(
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
declare
|
||||||
oldPartnerRel hs_office_relation;
|
oldPartnerRel hs_office_relationship;
|
||||||
newPartnerRel hs_office_relation;
|
newPartnerRel hs_office_relationship;
|
||||||
oldPartnerDetails hs_office_partner_details;
|
oldPartnerDetails hs_office_partner_details;
|
||||||
newPartnerDetails hs_office_partner_details;
|
newPartnerDetails hs_office_partner_details;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
SELECT * FROM hs_office_relation AS r WHERE r.uuid = OLD.partnerRelUuid INTO oldPartnerRel;
|
SELECT * FROM hs_office_relationship AS r WHERE r.uuid = OLD.partnerRoleUuid INTO oldPartnerRel;
|
||||||
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRelUuid = %s', OLD.partnerRelUuid);
|
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRoleUuid = %s', OLD.partnerRoleUuid);
|
||||||
|
|
||||||
SELECT * FROM hs_office_relation AS r WHERE r.uuid = NEW.partnerRelUuid INTO newPartnerRel;
|
SELECT * FROM hs_office_relationship AS r WHERE r.uuid = NEW.partnerRoleUuid INTO newPartnerRel;
|
||||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
|
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRoleUuid = %s', NEW.partnerRoleUuid);
|
||||||
|
|
||||||
SELECT * FROM hs_office_partner_details AS d WHERE d.uuid = OLD.detailsUuid INTO oldPartnerDetails;
|
SELECT * FROM hs_office_partner_details AS d WHERE d.uuid = OLD.detailsUuid INTO oldPartnerDetails;
|
||||||
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s', OLD.detailsUuid);
|
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s', OLD.detailsUuid);
|
||||||
@ -108,31 +108,31 @@ begin
|
|||||||
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
|
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
|
||||||
|
|
||||||
|
|
||||||
if NEW.partnerRelUuid <> OLD.partnerRelUuid then
|
if NEW.partnerRoleUuid <> OLD.partnerRoleUuid then
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel));
|
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationshipAdmin(oldPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationshipAdmin(newPartnerRel));
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel));
|
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationshipAgent(oldPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTenant(oldPartnerRel));
|
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationshipTenant(oldPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationshipTenant(newPartnerRel));
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel));
|
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationshipAdmin(oldPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
|
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationshipAdmin(newPartnerRel));
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel));
|
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationshipAgent(oldPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
|
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
|
|
||||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(oldPartnerRel));
|
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationshipAgent(oldPartnerRel));
|
||||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel));
|
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
-- raise exception 'RBAC updated from rel % to %', OLD.partnerReluuid, NEW.partnerReluuid;
|
-- raise exception 'RBAC updated from rel % to %', OLD.partnerroleuuid, NEW.partnerroleuuid;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
|
||||||
@ -143,20 +143,20 @@ create or replace procedure updateRbacRulesForHsOfficePartnerX(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
partnerRel hs_office_relation;
|
partnerRel hs_office_relationship;
|
||||||
grantCount int;
|
grantCount int;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
assert OLD.uuid = NEW.uuid, 'uuid did change, but should not';
|
assert OLD.uuid = NEW.uuid, 'uuid did change, but should not';
|
||||||
assert OLD.partnerReluuid <> NEW.partnerReluuid, 'partnerReluuid did not change, but should have';
|
assert OLD.partnerroleuuid <> NEW.partnerroleuuid, 'partnerroleuuid did not change, but should have';
|
||||||
|
|
||||||
delete from rbacgrants where grantedbytriggerof = OLD.uuid;
|
delete from rbacgrants where grantedbytriggerof = OLD.uuid;
|
||||||
select count(*) from rbacgrants where grantedbytriggerof=NEW.uuid into grantCount;
|
select count(*) from rbacgrants where grantedbytriggerof=NEW.uuid into grantCount;
|
||||||
assert grantCount=0, format('unexpected grantCount>0: %d', grantCount);
|
assert grantCount=0, format('unexpected grantCount>0: %d', grantCount);
|
||||||
|
|
||||||
call buildRbacSystemForHsOfficePartner(NEW);
|
call buildRbacSystemForHsOfficePartner(NEW);
|
||||||
select * from hs_office_relation where uuid=NEW.partnerReluuid into partnerRel;
|
select * from hs_office_relationship where uuid=NEW.partnerroleuuid into partnerRel;
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(partnerRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationshipTenant(partnerRel));
|
||||||
select count(*) from rbacgrants where grantedbytriggerof=NEW.uuid into grantCount;
|
select count(*) from rbacgrants where grantedbytriggerof=NEW.uuid into grantCount;
|
||||||
assert grantCount>0, format('unexpected grantCount=0: %d', grantCount);
|
assert grantCount>0, format('unexpected grantCount=0: %d', grantCount);
|
||||||
raise warning 'WARNING grantCount=%', grantCount;
|
raise warning 'WARNING grantCount=%', grantCount;
|
||||||
@ -262,7 +262,7 @@ call generateRbacRestrictedView('hs_office_partner',
|
|||||||
'P-' || partnerNumber
|
'P-' || partnerNumber
|
||||||
$orderBy$,
|
$orderBy$,
|
||||||
$updates$
|
$updates$
|
||||||
partnerRelUuid = new.partnerRelUuid
|
partnerRoleUuid = new.partnerRoleUuid
|
||||||
$updates$);
|
$updates$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ declare
|
|||||||
currentTask varchar;
|
currentTask varchar;
|
||||||
idName varchar;
|
idName varchar;
|
||||||
mandantPerson hs_office_person;
|
mandantPerson hs_office_person;
|
||||||
partnerRel hs_office_relation;
|
partnerRole hs_office_relationship;
|
||||||
relatedPerson hs_office_person;
|
relatedPerson hs_office_person;
|
||||||
relatedDetailsUuid uuid;
|
relatedDetailsUuid uuid;
|
||||||
begin
|
begin
|
||||||
@ -38,16 +38,16 @@ begin
|
|||||||
where p.tradeName = partnerPersonName or p.familyName = partnerPersonName
|
where p.tradeName = partnerPersonName or p.familyName = partnerPersonName
|
||||||
into relatedPerson;
|
into relatedPerson;
|
||||||
|
|
||||||
select r.* from hs_office_relation r
|
select r.* from hs_office_relationship r
|
||||||
where r.type = 'PARTNER'
|
where r.reltype = 'PARTNER'
|
||||||
and r.anchoruuid = mandantPerson.uuid and r.holderuuid = relatedPerson.uuid
|
and r.relanchoruuid = mandantPerson.uuid and r.relholderuuid = relatedPerson.uuid
|
||||||
into partnerRel;
|
into partnerRole;
|
||||||
if partnerRel is null then
|
if partnerRole is null then
|
||||||
raise exception 'partnerRel "%"-"%" not found', mandantPerson.tradename, partnerPersonName;
|
raise exception 'partnerRole "%"-"%" not found', mandantPerson.tradename, partnerPersonName;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
raise notice 'creating test partner: %', idName;
|
raise notice 'creating test partner: %', idName;
|
||||||
raise notice '- using partnerRel (%): %', partnerRel.uuid, partnerRel;
|
raise notice '- using partnerRole (%): %', partnerRole.uuid, partnerRole;
|
||||||
raise notice '- using person (%): %', relatedPerson.uuid, relatedPerson;
|
raise notice '- using person (%): %', relatedPerson.uuid, relatedPerson;
|
||||||
|
|
||||||
if relatedPerson.persontype = 'NP' then
|
if relatedPerson.persontype = 'NP' then
|
||||||
@ -63,8 +63,8 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into hs_office_partner (uuid, partnerNumber, partnerRelUuid, detailsUuid)
|
into hs_office_partner (uuid, partnerNumber, partnerRoleUuid, detailsUuid)
|
||||||
values (uuid_generate_v4(), newPartnerNumber, partnerRel.uuid, relatedDetailsUuid);
|
values (uuid_generate_v4(), newPartnerNumber, partnerRole.uuid, relatedDetailsUuid);
|
||||||
end; $$;
|
end; $$;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ create or replace procedure buildRbacSystemForHsOfficeSepaMandate(
|
|||||||
|
|
||||||
declare
|
declare
|
||||||
newBankAccount hs_office_bankaccount;
|
newBankAccount hs_office_bankaccount;
|
||||||
newDebitorRel hs_office_relation;
|
newDebitorRel hs_office_relationship;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
@ -40,7 +40,7 @@ begin
|
|||||||
assert newBankAccount.uuid is not null, format('newBankAccount must not be null for NEW.bankAccountUuid = %s', NEW.bankAccountUuid);
|
assert newBankAccount.uuid is not null, format('newBankAccount must not be null for NEW.bankAccountUuid = %s', NEW.bankAccountUuid);
|
||||||
|
|
||||||
SELECT debitorRel.*
|
SELECT debitorRel.*
|
||||||
FROM hs_office_relation debitorRel
|
FROM hs_office_relationship debitorRel
|
||||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||||
WHERE debitor.uuid = NEW.debitorUuid
|
WHERE debitor.uuid = NEW.debitorUuid
|
||||||
INTO newDebitorRel;
|
INTO newDebitorRel;
|
||||||
@ -64,7 +64,7 @@ begin
|
|||||||
hsOfficeSepaMandateAgent(NEW),
|
hsOfficeSepaMandateAgent(NEW),
|
||||||
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
|
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
|
||||||
outgoingSubRoles => array[
|
outgoingSubRoles => array[
|
||||||
hsOfficeRelationAgent(newDebitorRel),
|
hsOfficeRelationshipAgent(newDebitorRel),
|
||||||
hsOfficeBankAccountReferrer(newBankAccount)]
|
hsOfficeBankAccountReferrer(newBankAccount)]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -74,8 +74,8 @@ begin
|
|||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficeSepaMandateAgent(NEW),
|
hsOfficeSepaMandateAgent(NEW),
|
||||||
hsOfficeBankAccountAdmin(newBankAccount),
|
hsOfficeBankAccountAdmin(newBankAccount),
|
||||||
hsOfficeRelationAgent(newDebitorRel)],
|
hsOfficeRelationshipAgent(newDebitorRel)],
|
||||||
outgoingSubRoles => array[hsOfficeRelationTenant(newDebitorRel)]
|
outgoingSubRoles => array[hsOfficeRelationshipTenant(newDebitorRel)]
|
||||||
);
|
);
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
@ -106,19 +106,19 @@ execute procedure insertTriggerForHsOfficeSepaMandate_tf();
|
|||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows.
|
Creates INSERT INTO hs_office_sepamandate permissions for the related hs_office_relationship rows.
|
||||||
*/
|
*/
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
declare
|
declare
|
||||||
row hs_office_relation;
|
row hs_office_relationship;
|
||||||
permissionUuid uuid;
|
permissionUuid uuid;
|
||||||
roleUuid uuid;
|
roleUuid uuid;
|
||||||
begin
|
begin
|
||||||
call defineContext('create INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows');
|
call defineContext('create INSERT INTO hs_office_sepamandate permissions for the related hs_office_relationship rows');
|
||||||
|
|
||||||
FOR row IN SELECT * FROM hs_office_relation
|
FOR row IN SELECT * FROM hs_office_relationship
|
||||||
LOOP
|
LOOP
|
||||||
roleUuid := findRoleId(hsOfficeRelationAdmin(row));
|
roleUuid := findRoleId(hsOfficeRelationshipAdmin(row));
|
||||||
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate');
|
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate');
|
||||||
call grantPermissionToRole(permissionUuid, roleUuid);
|
call grantPermissionToRole(permissionUuid, roleUuid);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
@ -126,24 +126,24 @@ do language plpgsql $$
|
|||||||
$$;
|
$$;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adds hs_office_sepamandate INSERT permission to specified role of new hs_office_relation rows.
|
Adds hs_office_sepamandate INSERT permission to specified role of new hs_office_relationship rows.
|
||||||
*/
|
*/
|
||||||
create or replace function hs_office_sepamandate_hs_office_relation_insert_tf()
|
create or replace function hs_office_sepamandate_hs_office_relationship_insert_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
call grantPermissionToRole(
|
call grantPermissionToRole(
|
||||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_sepamandate'),
|
createPermission(NEW.uuid, 'INSERT', 'hs_office_sepamandate'),
|
||||||
hsOfficeRelationAdmin(NEW));
|
hsOfficeRelationshipAdmin(NEW));
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||||
create trigger z_hs_office_sepamandate_hs_office_relation_insert_tg
|
create trigger z_hs_office_sepamandate_hs_office_relationship_insert_tg
|
||||||
after insert on hs_office_relation
|
after insert on hs_office_relationship
|
||||||
for each row
|
for each row
|
||||||
execute procedure hs_office_sepamandate_hs_office_relation_insert_tf();
|
execute procedure hs_office_sepamandate_hs_office_relationship_insert_tf();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate.
|
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate.
|
||||||
@ -156,7 +156,7 @@ begin
|
|||||||
( SELECT debitorRel.uuid FROM
|
( SELECT debitorRel.uuid FROM
|
||||||
|
|
||||||
(SELECT debitorRel.*
|
(SELECT debitorRel.*
|
||||||
FROM hs_office_relation debitorRel
|
FROM hs_office_relationship debitorRel
|
||||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||||
WHERE debitor.uuid = NEW.debitorUuid
|
WHERE debitor.uuid = NEW.debitorUuid
|
||||||
) AS debitorRel
|
) AS debitorRel
|
||||||
|
@ -25,9 +25,9 @@ begin
|
|||||||
|
|
||||||
select debitor.* into relatedDebitor
|
select debitor.* into relatedDebitor
|
||||||
from hs_office_debitor debitor
|
from hs_office_debitor debitor
|
||||||
join hs_office_relation debitorRel on debitorRel.uuid = debitor.debitorRelUuid
|
join hs_office_relationship debitorRel on debitorRel.uuid = debitor.debitorRelUuid
|
||||||
join hs_office_relation partnerRel on partnerRel.holderUuid = debitorRel.anchorUuid
|
join hs_office_relationship partnerRel on partnerRel.relHolderUuid = debitorRel.relAnchorUuid
|
||||||
join hs_office_partner partner on partner.partnerRelUuid = partnerRel.uuid
|
join hs_office_partner partner on partner.partnerRoleUuid = partnerRel.uuid
|
||||||
where partner.partnerNumber = forPartnerNumber and debitor.debitorNumberSuffix = forDebitorSuffix;
|
where partner.partnerNumber = forPartnerNumber and debitor.debitorNumberSuffix = forDebitorSuffix;
|
||||||
select b.* into relatedBankAccount
|
select b.* into relatedBankAccount
|
||||||
from hs_office_bankAccount b where b.iban = forIban;
|
from hs_office_bankAccount b where b.iban = forIban;
|
||||||
|
@ -8,7 +8,7 @@ create table hs_office_debitor
|
|||||||
(
|
(
|
||||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||||
debitorNumberSuffix numeric(2) not null,
|
debitorNumberSuffix numeric(2) not null,
|
||||||
debitorRelUuid uuid not null references hs_office_relation(uuid),
|
debitorRelUuid uuid not null references hs_office_relationship(uuid),
|
||||||
billable boolean not null default true,
|
billable boolean not null default true,
|
||||||
vatId varchar(24), -- TODO.spec: here or in person?
|
vatId varchar(24), -- TODO.spec: here or in person?
|
||||||
vatCountryCode varchar(2),
|
vatCountryCode varchar(2),
|
||||||
|
@ -30,25 +30,25 @@ create or replace procedure buildRbacSystemForHsOfficeDebitor(
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
declare
|
||||||
newPartnerRel hs_office_relation;
|
newPartnerRel hs_office_relationship;
|
||||||
newDebitorRel hs_office_relation;
|
newDebitorRel hs_office_relationship;
|
||||||
newRefundBankAccount hs_office_bankaccount;
|
newRefundBankAccount hs_office_bankaccount;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
SELECT partnerRel.*
|
SELECT partnerRel.*
|
||||||
FROM hs_office_relation AS partnerRel
|
FROM hs_office_relationship AS partnerRel
|
||||||
JOIN hs_office_relation AS debitorRel
|
JOIN hs_office_relationship AS debitorRel
|
||||||
ON debitorRel.type = 'DEBITOR' AND debitorRel.anchorUuid = partnerRel.holderUuid
|
ON debitorRel.relType = 'ACCOUNTING' AND debitorRel.relAnchorUuid = partnerRel.relHolderUuid
|
||||||
WHERE partnerRel.type = 'PARTNER'
|
WHERE partnerRel.relType = 'PARTNER'
|
||||||
AND NEW.debitorRelUuid = debitorRel.uuid
|
AND NEW.debitorRelUuid = debitorRel.uuid
|
||||||
INTO newPartnerRel;
|
INTO newPartnerRel;
|
||||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
|
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
|
||||||
|
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM hs_office_relation AS r
|
FROM hs_office_relationship AS r
|
||||||
WHERE r.type = 'DEBITOR' AND r.uuid = NEW.debitorRelUuid
|
WHERE r.relType = 'ACCOUNTING' AND r.uuid = NEW.debitorRelUuid
|
||||||
INTO newDebitorRel;
|
INTO newDebitorRel;
|
||||||
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
|
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
|
||||||
|
|
||||||
@ -57,15 +57,15 @@ begin
|
|||||||
WHERE b.uuid = NEW.refundBankAccountUuid
|
WHERE b.uuid = NEW.refundBankAccountUuid
|
||||||
INTO newRefundBankAccount;
|
INTO newRefundBankAccount;
|
||||||
|
|
||||||
call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel));
|
call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationshipAgent(newDebitorRel));
|
||||||
call grantRoleToRole(hsOfficeRelationAdmin(newDebitorRel), hsOfficeRelationAdmin(newPartnerRel));
|
call grantRoleToRole(hsOfficeRelationshipAdmin(newDebitorRel), hsOfficeRelationshipAdmin(newPartnerRel));
|
||||||
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountAdmin(newRefundBankAccount));
|
call grantRoleToRole(hsOfficeRelationshipAgent(newDebitorRel), hsOfficeBankAccountAdmin(newRefundBankAccount));
|
||||||
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeRelationAgent(newPartnerRel));
|
call grantRoleToRole(hsOfficeRelationshipAgent(newDebitorRel), hsOfficeRelationshipAgent(newPartnerRel));
|
||||||
call grantRoleToRole(hsOfficeRelationTenant(newPartnerRel), hsOfficeRelationAgent(newDebitorRel));
|
call grantRoleToRole(hsOfficeRelationshipTenant(newPartnerRel), hsOfficeRelationshipAgent(newDebitorRel));
|
||||||
|
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOwner(newDebitorRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationshipOwner(newDebitorRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newDebitorRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationshipTenant(newDebitorRel));
|
||||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAdmin(newDebitorRel));
|
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationshipAdmin(newDebitorRel));
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
end; $$;
|
end; $$;
|
||||||
@ -202,10 +202,10 @@ create trigger hs_office_debitor_insert_permission_check_tg
|
|||||||
SELECT debitor.uuid AS uuid,
|
SELECT debitor.uuid AS uuid,
|
||||||
'D-' || (SELECT partner.partnerNumber
|
'D-' || (SELECT partner.partnerNumber
|
||||||
FROM hs_office_partner partner
|
FROM hs_office_partner partner
|
||||||
JOIN hs_office_relation partnerRel
|
JOIN hs_office_relationship partnerRel
|
||||||
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
|
ON partnerRel.uuid = partner.partnerRoleUUid AND partnerRel.relType = 'PARTNER'
|
||||||
JOIN hs_office_relation debitorRel
|
JOIN hs_office_relationship debitorRel
|
||||||
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
ON debitorRel.relAnchorUuid = partnerRel.relHolderUuid AND debitorRel.relType = 'ACCOUNTING'
|
||||||
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
||||||
|| to_char(debitorNumberSuffix, 'fm00') as idName
|
|| to_char(debitorNumberSuffix, 'fm00') as idName
|
||||||
FROM hs_office_debitor AS debitor
|
FROM hs_office_debitor AS debitor
|
||||||
|
@ -28,10 +28,10 @@ begin
|
|||||||
|
|
||||||
select debitorRel.uuid
|
select debitorRel.uuid
|
||||||
into relatedDebitorRelUuid
|
into relatedDebitorRelUuid
|
||||||
from hs_office_relation debitorRel
|
from hs_office_relationship debitorRel
|
||||||
join hs_office_person person on person.uuid = debitorRel.holderUuid
|
join hs_office_person person on person.uuid = debitorRel.relHolderUuid
|
||||||
and (person.tradeName = forPartnerPersonName or person.familyName = forPartnerPersonName)
|
and (person.tradeName = forPartnerPersonName or person.familyName = forPartnerPersonName)
|
||||||
where debitorRel.type = 'DEBITOR';
|
where debitorRel.relType = 'ACCOUNTING';
|
||||||
|
|
||||||
select b.uuid
|
select b.uuid
|
||||||
into relatedBankAccountUuid
|
into relatedBankAccountUuid
|
||||||
|
@ -30,14 +30,14 @@ create or replace procedure buildRbacSystemForHsOfficeMembership(
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
declare
|
||||||
newPartnerRel hs_office_relation;
|
newPartnerRel hs_office_relationship;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
SELECT r.*
|
SELECT r.*
|
||||||
FROM hs_office_partner AS p
|
FROM hs_office_partner AS p
|
||||||
JOIN hs_office_relation AS r ON r.uuid = p.partnerRelUuid
|
JOIN hs_office_relationship AS r ON r.uuid = p.partnerRoleUuid
|
||||||
WHERE p.uuid = NEW.partnerUuid
|
WHERE p.uuid = NEW.partnerUuid
|
||||||
INTO newPartnerRel;
|
INTO newPartnerRel;
|
||||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerUuid = %s', NEW.partnerUuid);
|
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerUuid = %s', NEW.partnerUuid);
|
||||||
@ -46,7 +46,7 @@ begin
|
|||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeMembershipOwner(NEW),
|
hsOfficeMembershipOwner(NEW),
|
||||||
permissions => array['DELETE'],
|
permissions => array['DELETE'],
|
||||||
incomingSuperRoles => array[hsOfficeRelationAdmin(newPartnerRel)],
|
incomingSuperRoles => array[hsOfficeRelationshipAdmin(newPartnerRel)],
|
||||||
userUuids => array[currentUserUuid()]
|
userUuids => array[currentUserUuid()]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -55,14 +55,14 @@ begin
|
|||||||
permissions => array['UPDATE'],
|
permissions => array['UPDATE'],
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficeMembershipOwner(NEW),
|
hsOfficeMembershipOwner(NEW),
|
||||||
hsOfficeRelationAgent(newPartnerRel)]
|
hsOfficeRelationshipAgent(newPartnerRel)]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeMembershipReferrer(NEW),
|
hsOfficeMembershipReferrer(NEW),
|
||||||
permissions => array['SELECT'],
|
permissions => array['SELECT'],
|
||||||
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW)],
|
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW)],
|
||||||
outgoingSubRoles => array[hsOfficeRelationTenant(newPartnerRel)]
|
outgoingSubRoles => array[hsOfficeRelationshipTenant(newPartnerRel)]
|
||||||
);
|
);
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
@ -93,19 +93,19 @@ execute procedure insertTriggerForHsOfficeMembership_tf();
|
|||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates INSERT INTO hs_office_membership permissions for the related hs_office_relation rows.
|
Creates INSERT INTO hs_office_membership permissions for the related hs_office_relationship rows.
|
||||||
*/
|
*/
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
declare
|
declare
|
||||||
row hs_office_relation;
|
row hs_office_relationship;
|
||||||
permissionUuid uuid;
|
permissionUuid uuid;
|
||||||
roleUuid uuid;
|
roleUuid uuid;
|
||||||
begin
|
begin
|
||||||
call defineContext('create INSERT INTO hs_office_membership permissions for the related hs_office_relation rows');
|
call defineContext('create INSERT INTO hs_office_membership permissions for the related hs_office_relationship rows');
|
||||||
|
|
||||||
FOR row IN SELECT * FROM hs_office_relation
|
FOR row IN SELECT * FROM hs_office_relationship
|
||||||
LOOP
|
LOOP
|
||||||
roleUuid := findRoleId(hsOfficeRelationAdmin(row));
|
roleUuid := findRoleId(hsOfficeRelationshipAdmin(row));
|
||||||
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_membership');
|
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_membership');
|
||||||
call grantPermissionToRole(permissionUuid, roleUuid);
|
call grantPermissionToRole(permissionUuid, roleUuid);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
@ -113,24 +113,24 @@ do language plpgsql $$
|
|||||||
$$;
|
$$;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adds hs_office_membership INSERT permission to specified role of new hs_office_relation rows.
|
Adds hs_office_membership INSERT permission to specified role of new hs_office_relationship rows.
|
||||||
*/
|
*/
|
||||||
create or replace function hs_office_membership_hs_office_relation_insert_tf()
|
create or replace function hs_office_membership_hs_office_relationship_insert_tf()
|
||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
call grantPermissionToRole(
|
call grantPermissionToRole(
|
||||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'),
|
createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'),
|
||||||
hsOfficeRelationAdmin(NEW));
|
hsOfficeRelationshipAdmin(NEW));
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||||
create trigger z_hs_office_membership_hs_office_relation_insert_tg
|
create trigger z_hs_office_membership_hs_office_relationship_insert_tg
|
||||||
after insert on hs_office_relation
|
after insert on hs_office_relationship
|
||||||
for each row
|
for each row
|
||||||
execute procedure hs_office_membership_hs_office_relation_insert_tf();
|
execute procedure hs_office_membership_hs_office_relationship_insert_tf();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_membership.
|
Checks if the user or assumed roles are allowed to insert a row to hs_office_membership.
|
||||||
@ -144,7 +144,7 @@ begin
|
|||||||
|
|
||||||
(SELECT r.*
|
(SELECT r.*
|
||||||
FROM hs_office_partner AS p
|
FROM hs_office_partner AS p
|
||||||
JOIN hs_office_relation AS r ON r.uuid = p.partnerRelUuid
|
JOIN hs_office_relationship AS r ON r.uuid = p.partnerRoleUuid
|
||||||
WHERE p.uuid = NEW.partnerUuid
|
WHERE p.uuid = NEW.partnerUuid
|
||||||
) AS partnerRel
|
) AS partnerRel
|
||||||
|
|
||||||
|
@ -70,11 +70,11 @@ databaseChangeLog:
|
|||||||
- include:
|
- include:
|
||||||
file: db/changelog/218-hs-office-person-test-data.sql
|
file: db/changelog/218-hs-office-person-test-data.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/220-hs-office-relation.sql
|
file: db/changelog/220-hs-office-relationship.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/223-hs-office-relation-rbac.sql
|
file: db/changelog/223-hs-office-relationship-rbac.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/228-hs-office-relation-test-data.sql
|
file: db/changelog/228-hs-office-relationship-test-data.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/230-hs-office-partner.sql
|
file: db/changelog/230-hs-office-partner.sql
|
||||||
- include:
|
- include:
|
||||||
|
@ -41,7 +41,7 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.migration",
|
"..hs.office.migration",
|
||||||
"..hs.office.partner",
|
"..hs.office.partner",
|
||||||
"..hs.office.person",
|
"..hs.office.person",
|
||||||
"..hs.office.relation",
|
"..hs.office.relationship",
|
||||||
"..hs.office.sepamandate",
|
"..hs.office.sepamandate",
|
||||||
"..errors",
|
"..errors",
|
||||||
"..mapper",
|
"..mapper",
|
||||||
@ -148,7 +148,7 @@ public class ArchitectureTest {
|
|||||||
public static final ArchRule hsOfficeContactPackageRule = classes()
|
public static final ArchRule hsOfficeContactPackageRule = classes()
|
||||||
.that().resideInAPackage("..hs.office.contact..")
|
.that().resideInAPackage("..hs.office.contact..")
|
||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage("..hs.office.contact..", "..hs.office.relation..",
|
.resideInAnyPackage("..hs.office.contact..", "..hs.office.relationship..",
|
||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
@ -159,7 +159,7 @@ public class ArchitectureTest {
|
|||||||
public static final ArchRule hsOfficePersonPackageRule = classes()
|
public static final ArchRule hsOfficePersonPackageRule = classes()
|
||||||
.that().resideInAPackage("..hs.office.person..")
|
.that().resideInAPackage("..hs.office.person..")
|
||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage("..hs.office.person..", "..hs.office.relation..",
|
.resideInAnyPackage("..hs.office.person..", "..hs.office.relationship..",
|
||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
@ -167,10 +167,10 @@ public class ArchitectureTest {
|
|||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static final ArchRule hsOfficeRelationPackageRule = classes()
|
public static final ArchRule hsOfficeRelationshipPackageRule = classes()
|
||||||
.that().resideInAPackage("..hs.office.relation..")
|
.that().resideInAPackage("..hs.office.relationship..")
|
||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage("..hs.office.relation..",
|
.resideInAnyPackage("..hs.office.relationship..",
|
||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.migration..");
|
"..hs.office.migration..");
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountReposi
|
|||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRepository;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.test.Accepts;
|
import net.hostsharing.test.Accepts;
|
||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
@ -27,7 +27,7 @@ import jakarta.persistence.EntityManager;
|
|||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR;
|
import static net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType.ACCOUNTING;
|
||||||
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
|
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
|
||||||
import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
|
import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -65,7 +65,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
HsOfficePersonRepository personRepo;
|
HsOfficePersonRepository personRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeRelationRepository relRepo;
|
HsOfficeRelationshipRepository relRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
JpaAttempt jpaAttempt;
|
JpaAttempt jpaAttempt;
|
||||||
@ -93,20 +93,20 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"debitorRel": {
|
"debitorRel": {
|
||||||
"anchor": {
|
"relAnchor": {
|
||||||
"personType": "LEGAL_PERSON",
|
"personType": "LEGAL_PERSON",
|
||||||
"tradeName": "First GmbH",
|
"tradeName": "First GmbH",
|
||||||
"givenName": null,
|
"givenName": null,
|
||||||
"familyName": null
|
"familyName": null
|
||||||
},
|
},
|
||||||
"holder": {
|
"relHolder": {
|
||||||
"personType": "LEGAL_PERSON",
|
"personType": "LEGAL_PERSON",
|
||||||
"tradeName": "First GmbH",
|
"tradeName": "First GmbH",
|
||||||
"givenName": null,
|
"givenName": null,
|
||||||
"familyName": null
|
"familyName": null
|
||||||
},
|
},
|
||||||
"type": "DEBITOR",
|
"relType": "ACCOUNTING",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": {
|
"contact": {
|
||||||
"label": "first contact",
|
"label": "first contact",
|
||||||
"emailAddresses": "contact-admin@firstcontact.example.com",
|
"emailAddresses": "contact-admin@firstcontact.example.com",
|
||||||
@ -117,21 +117,21 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
"debitorNumberSuffix": 11,
|
"debitorNumberSuffix": 11,
|
||||||
"partner": {
|
"partner": {
|
||||||
"partnerNumber": 10001,
|
"partnerNumber": 10001,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": {
|
"relAnchor": {
|
||||||
"personType": "LEGAL_PERSON",
|
"personType": "LEGAL_PERSON",
|
||||||
"tradeName": "Hostsharing eG",
|
"tradeName": "Hostsharing eG",
|
||||||
"givenName": null,
|
"givenName": null,
|
||||||
"familyName": null
|
"familyName": null
|
||||||
},
|
},
|
||||||
"holder": {
|
"relHolder": {
|
||||||
"personType": "LEGAL_PERSON",
|
"personType": "LEGAL_PERSON",
|
||||||
"tradeName": "First GmbH",
|
"tradeName": "First GmbH",
|
||||||
"givenName": null,
|
"givenName": null,
|
||||||
"familyName": null
|
"familyName": null
|
||||||
},
|
},
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": {
|
"contact": {
|
||||||
"label": "first contact",
|
"label": "first contact",
|
||||||
"emailAddresses": "contact-admin@firstcontact.example.com",
|
"emailAddresses": "contact-admin@firstcontact.example.com",
|
||||||
@ -161,19 +161,19 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"debitorRel": {
|
"debitorRel": {
|
||||||
"anchor": {"tradeName": "Second e.K."},
|
"relAnchor": {"tradeName": "Second e.K."},
|
||||||
"holder": {"tradeName": "Second e.K."},
|
"relHolder": {"tradeName": "Second e.K."},
|
||||||
"type": "DEBITOR",
|
"relType": "ACCOUNTING",
|
||||||
"contact": {"emailAddresses": "contact-admin@secondcontact.example.com"}
|
"contact": {"emailAddresses": "contact-admin@secondcontact.example.com"}
|
||||||
},
|
},
|
||||||
"debitorNumber": 1000212,
|
"debitorNumber": 1000212,
|
||||||
"debitorNumberSuffix": 12,
|
"debitorNumberSuffix": 12,
|
||||||
"partner": {
|
"partner": {
|
||||||
"partnerNumber": 10002,
|
"partnerNumber": 10002,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": {"tradeName": "Hostsharing eG"},
|
"relAnchor": {"tradeName": "Hostsharing eG"},
|
||||||
"holder": {"tradeName": "Second e.K."},
|
"relHolder": {"tradeName": "Second e.K."},
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"contact": {"emailAddresses": "contact-admin@secondcontact.example.com"}
|
"contact": {"emailAddresses": "contact-admin@secondcontact.example.com"}
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
@ -191,19 +191,19 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"debitorRel": {
|
"debitorRel": {
|
||||||
"anchor": {"tradeName": "Third OHG"},
|
"relAnchor": {"tradeName": "Third OHG"},
|
||||||
"holder": {"tradeName": "Third OHG"},
|
"relHolder": {"tradeName": "Third OHG"},
|
||||||
"type": "DEBITOR",
|
"relType": "ACCOUNTING",
|
||||||
"contact": {"emailAddresses": "contact-admin@thirdcontact.example.com"}
|
"contact": {"emailAddresses": "contact-admin@thirdcontact.example.com"}
|
||||||
},
|
},
|
||||||
"debitorNumber": 1000313,
|
"debitorNumber": 1000313,
|
||||||
"debitorNumberSuffix": 13,
|
"debitorNumberSuffix": 13,
|
||||||
"partner": {
|
"partner": {
|
||||||
"partnerNumber": 10003,
|
"partnerNumber": 10003,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": {"tradeName": "Hostsharing eG"},
|
"relAnchor": {"tradeName": "Hostsharing eG"},
|
||||||
"holder": {"tradeName": "Third OHG"},
|
"relHolder": {"tradeName": "Third OHG"},
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"contact": {"emailAddresses": "contact-admin@thirdcontact.example.com"}
|
"contact": {"emailAddresses": "contact-admin@thirdcontact.example.com"}
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
@ -268,10 +268,10 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
|
|
||||||
final var givenDebitorRelUUid = jpaAttempt.transacted(() -> {
|
final var givenDebitorRelUUid = jpaAttempt.transacted(() -> {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
return relRepo.save(HsOfficeRelationEntity.builder()
|
return relRepo.save(HsOfficeRelationshipEntity.builder()
|
||||||
.type(DEBITOR)
|
.relType(ACCOUNTING)
|
||||||
.anchor(givenPartner.getPartnerRel().getHolder())
|
.relAnchor(givenPartner.getPartnerRole().getRelHolder())
|
||||||
.holder(givenBillingPerson)
|
.relHolder(givenBillingPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build()).getUuid();
|
.build()).getUuid();
|
||||||
}).assertSuccessful().returnedValue();
|
}).assertSuccessful().returnedValue();
|
||||||
@ -303,7 +303,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("vatId", is("VAT123456"))
|
.body("vatId", is("VAT123456"))
|
||||||
.body("defaultPrefix", is("for"))
|
.body("defaultPrefix", is("for"))
|
||||||
.body("debitorRel.contact.label", is(givenContact.getLabel()))
|
.body("debitorRel.contact.label", is(givenContact.getLabel()))
|
||||||
.body("debitorRel.holder.tradeName", is(givenBillingPerson.getTradeName()))
|
.body("debitorRel.relHolder.tradeName", is(givenBillingPerson.getTradeName()))
|
||||||
.body("refundBankAccount.holder", is(givenBankAccount.getHolder()))
|
.body("refundBankAccount.holder", is(givenBankAccount.getHolder()))
|
||||||
.header("Location", startsWith("http://localhost"))
|
.header("Location", startsWith("http://localhost"))
|
||||||
.extract().header("Location"); // @formatter:on
|
.extract().header("Location"); // @formatter:on
|
||||||
@ -328,9 +328,9 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"debitorRel": {
|
"debitorRel": {
|
||||||
"type": "DEBITOR",
|
"relType": "ACCOUNTING",
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"debitorNumberSuffix": "%s",
|
"debitorNumberSuffix": "%s",
|
||||||
@ -339,8 +339,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
"vatReverseCharge": "false"
|
"vatReverseCharge": "false"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
givenPartner.getPartnerRel().getHolder().getUuid(),
|
givenPartner.getPartnerRole().getRelHolder().getUuid(),
|
||||||
givenPartner.getPartnerRel().getHolder().getUuid(),
|
givenPartner.getPartnerRole().getRelHolder().getUuid(),
|
||||||
givenContact.getUuid(),
|
givenContact.getUuid(),
|
||||||
++nextDebitorSuffix))
|
++nextDebitorSuffix))
|
||||||
.port(port)
|
.port(port)
|
||||||
@ -351,7 +351,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("uuid", isUuidValid())
|
.body("uuid", isUuidValid())
|
||||||
.body("debitorRel.contact.label", is(givenContact.getLabel()))
|
.body("debitorRel.contact.label", is(givenContact.getLabel()))
|
||||||
.body("partner.partnerRel.holder.tradeName", is(givenPartner.getPartnerRel().getHolder().getTradeName()))
|
.body("partner.partnerRole.relHolder.tradeName", is(givenPartner.getPartnerRole().getRelHolder().getTradeName()))
|
||||||
.body("vatId", equalTo(null))
|
.body("vatId", equalTo(null))
|
||||||
.body("vatCountryCode", equalTo(null))
|
.body("vatCountryCode", equalTo(null))
|
||||||
.body("vatBusiness", equalTo(false))
|
.body("vatBusiness", equalTo(false))
|
||||||
@ -380,9 +380,9 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"debitorRel": {
|
"debitorRel": {
|
||||||
"type": "DEBITOR",
|
"relType": "ACCOUNTING",
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"debitorNumberSuffix": "%s",
|
"debitorNumberSuffix": "%s",
|
||||||
@ -391,8 +391,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
"vatReverseCharge": "false"
|
"vatReverseCharge": "false"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
givenPartner.getPartnerRel().getAnchor().getUuid(),
|
givenPartner.getPartnerRole().getRelAnchor().getUuid(),
|
||||||
givenPartner.getPartnerRel().getAnchor().getUuid(),
|
givenPartner.getPartnerRole().getRelAnchor().getUuid(),
|
||||||
givenContactUuid, ++nextDebitorSuffix))
|
givenContactUuid, ++nextDebitorSuffix))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
@ -428,7 +428,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.post("http://localhost/api/hs/office/debitors")
|
.post("http://localhost/api/hs/office/debitors")
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(400)
|
.statusCode(400)
|
||||||
.body("message", is("Unable to find HsOfficeRelationEntity with uuid 00000000-0000-0000-0000-000000000000"));
|
.body("message", is("Unable to find HsOfficeRelationshipEntity with uuid 00000000-0000-0000-0000-000000000000"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,9 +454,9 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"debitorRel": {
|
"debitorRel": {
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH"},
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH"},
|
||||||
"holder": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH"},
|
"relHolder": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH"},
|
||||||
"type": "DEBITOR",
|
"relType": "ACCOUNTING",
|
||||||
"contact": {
|
"contact": {
|
||||||
"label": "first contact",
|
"label": "first contact",
|
||||||
"postalAddress": "\\nVorname Nachname\\nStraße Hnr\\nPLZ Stadt\\n",
|
"postalAddress": "\\nVorname Nachname\\nStraße Hnr\\nPLZ Stadt\\n",
|
||||||
@ -468,11 +468,11 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
"debitorNumberSuffix": 11,
|
"debitorNumberSuffix": 11,
|
||||||
"partner": {
|
"partner": {
|
||||||
"partnerNumber": 10001,
|
"partnerNumber": 10001,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG"},
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG"},
|
||||||
"holder": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH"},
|
"relHolder": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH"},
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": {
|
"contact": {
|
||||||
"label": "first contact",
|
"label": "first contact",
|
||||||
"postalAddress": "\\nVorname Nachname\\nStraße Hnr\\nPLZ Stadt\\n",
|
"postalAddress": "\\nVorname Nachname\\nStraße Hnr\\nPLZ Stadt\\n",
|
||||||
@ -576,7 +576,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("vatBusiness", is(true))
|
.body("vatBusiness", is(true))
|
||||||
.body("defaultPrefix", is("for"))
|
.body("defaultPrefix", is("for"))
|
||||||
// FIXME .body("billingContact.label", is(givenContact.getLabel()))
|
// FIXME .body("billingContact.label", is(givenContact.getLabel()))
|
||||||
// FIXME .body("partner.partnerRel.holder.tradeName", is(givenDebitor.getPartner().getPartnerRel().getHolder().getTradeName()))
|
// FIXME .body("partner.partnerRole.relHolder.tradeName", is(givenDebitor.getPartner().getPartnerRole().getRelHolder().getTradeName()))
|
||||||
;
|
;
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
@ -584,8 +584,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent().get()
|
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent().get()
|
||||||
.matches(debitor -> {
|
.matches(debitor -> {
|
||||||
assertThat(debitor.getDebitorRel().getHolder().getTradeName())
|
assertThat(debitor.getDebitorRel().getRelHolder().getTradeName())
|
||||||
.isEqualTo(givenDebitor.getDebitorRel().getHolder().getTradeName());
|
.isEqualTo(givenDebitor.getDebitorRel().getRelHolder().getTradeName());
|
||||||
assertThat(debitor.getDebitorRel().getContact().getLabel()).isEqualTo("fourth contact");
|
assertThat(debitor.getDebitorRel().getContact().getLabel()).isEqualTo("fourth contact");
|
||||||
assertThat(debitor.getVatId()).isEqualTo("VAT222222");
|
assertThat(debitor.getVatId()).isEqualTo("VAT222222");
|
||||||
assertThat(debitor.getVatCountryCode()).isEqualTo("AA");
|
assertThat(debitor.getVatCountryCode()).isEqualTo("AA");
|
||||||
@ -627,8 +627,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
// finally, the debitor is actually updated
|
// finally, the debitor is actually updated
|
||||||
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent().get()
|
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent().get()
|
||||||
.matches(partner -> {
|
.matches(partner -> {
|
||||||
assertThat(partner.getDebitorRel().getHolder().getTradeName())
|
assertThat(partner.getDebitorRel().getRelHolder().getTradeName())
|
||||||
.isEqualTo(givenDebitor.getDebitorRel().getHolder().getTradeName());
|
.isEqualTo(givenDebitor.getDebitorRel().getRelHolder().getTradeName());
|
||||||
// FIXME assertThat(partner.getDebitorRel().getContact().getLabel()).isEqualTo("sixth contact");
|
// FIXME assertThat(partner.getDebitorRel().getContact().getLabel()).isEqualTo("sixth contact");
|
||||||
assertThat(partner.getVatId()).isEqualTo("VAT999999");
|
assertThat(partner.getVatId()).isEqualTo("VAT999999");
|
||||||
assertThat(partner.getVatCountryCode()).isEqualTo(givenDebitor.getVatCountryCode());
|
assertThat(partner.getVatCountryCode()).isEqualTo(givenDebitor.getVatCountryCode());
|
||||||
@ -711,10 +711,10 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.debitorNumberSuffix(++nextDebitorSuffix)
|
.debitorNumberSuffix(++nextDebitorSuffix)
|
||||||
.billable(true)
|
.billable(true)
|
||||||
.debitorRel(
|
.debitorRel(
|
||||||
HsOfficeRelationEntity.builder()
|
HsOfficeRelationshipEntity.builder()
|
||||||
.type(DEBITOR)
|
.relType(ACCOUNTING)
|
||||||
.anchor(givenPartner.getPartnerRel().getHolder())
|
.relAnchor(givenPartner.getPartnerRole().getRelHolder())
|
||||||
.holder(givenPartner.getPartnerRel().getHolder())
|
.relHolder(givenPartner.getPartnerRole().getRelHolder())
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.office.debitor;
|
|||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.test.PatchUnitTestBase;
|
import net.hostsharing.test.PatchUnitTestBase;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.TestInstance;
|
import org.junit.jupiter.api.TestInstance;
|
||||||
@ -44,7 +44,7 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
private static final UUID INITIAL_REFUND_BANK_ACCOUNT_UUID = UUID.randomUUID();
|
private static final UUID INITIAL_REFUND_BANK_ACCOUNT_UUID = UUID.randomUUID();
|
||||||
private static final UUID PATCHED_REFUND_BANK_ACCOUNT_UUID = UUID.randomUUID();
|
private static final UUID PATCHED_REFUND_BANK_ACCOUNT_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
private final HsOfficeRelationEntity givenInitialDebitorRel = HsOfficeRelationEntity.builder()
|
private final HsOfficeRelationshipEntity givenInitialDebitorRel = HsOfficeRelationshipEntity.builder()
|
||||||
.uuid(INITIAL_DEBITOR_REL_UUID)
|
.uuid(INITIAL_DEBITOR_REL_UUID)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void initMocks() {
|
void initMocks() {
|
||||||
lenient().when(em.getReference(eq(HsOfficeRelationEntity.class), any())).thenAnswer(invocation ->
|
lenient().when(em.getReference(eq(HsOfficeRelationshipEntity.class), any())).thenAnswer(invocation ->
|
||||||
HsOfficeRelationEntity.builder().uuid(invocation.getArgument(1)).build());
|
HsOfficeRelationshipEntity.builder().uuid(invocation.getArgument(1)).build());
|
||||||
lenient().when(em.getReference(eq(HsOfficeBankAccountEntity.class), any())).thenAnswer(invocation ->
|
lenient().when(em.getReference(eq(HsOfficeBankAccountEntity.class), any())).thenAnswer(invocation ->
|
||||||
HsOfficeBankAccountEntity.builder().uuid(invocation.getArgument(1)).build());
|
HsOfficeBankAccountEntity.builder().uuid(invocation.getArgument(1)).build());
|
||||||
}
|
}
|
||||||
@ -141,8 +141,8 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity newDebitorRel(final UUID uuid) {
|
private HsOfficeRelationshipEntity newDebitorRel(final UUID uuid) {
|
||||||
return HsOfficeRelationEntity.builder()
|
return HsOfficeRelationshipEntity.builder()
|
||||||
.uuid(uuid)
|
.uuid(uuid)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -4,19 +4,19 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
|||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
class HsOfficeDebitorEntityUnitTest {
|
class HsOfficeDebitorEntityUnitTest {
|
||||||
|
|
||||||
private HsOfficeRelationEntity givenDebitorRel = HsOfficeRelationEntity.builder()
|
private HsOfficeRelationshipEntity givenDebitorRel = HsOfficeRelationshipEntity.builder()
|
||||||
.anchor(HsOfficePersonEntity.builder()
|
.relAnchor(HsOfficePersonEntity.builder()
|
||||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||||
.tradeName("some partner trade name")
|
.tradeName("some partner trade name")
|
||||||
.build())
|
.build())
|
||||||
.holder(HsOfficePersonEntity.builder()
|
.relHolder(HsOfficePersonEntity.builder()
|
||||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||||
.tradeName("some billing trade name")
|
.tradeName("some billing trade name")
|
||||||
.build())
|
.build())
|
||||||
@ -36,7 +36,7 @@ class HsOfficeDebitorEntityUnitTest {
|
|||||||
|
|
||||||
final var result = given.toString();
|
final var result = given.toString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("debitor(D-1234567: rel(anchor='LP some partner trade name', holder='LP some billing trade name'), som)");
|
assertThat(result).isEqualTo("debitor(D-1234567: rel(relAnchor='LP some partner trade name', relHolder='LP some billing trade name'), som)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -5,8 +5,8 @@ import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountReposi
|
|||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
|
||||||
@ -89,10 +89,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)21)
|
.debitorNumberSuffix((byte)21)
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||||
.anchor(givenPartnerPerson)
|
.relAnchor(givenPartnerPerson)
|
||||||
.holder(givenPartnerPerson)
|
.relHolder(givenPartnerPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build())
|
.build())
|
||||||
.defaultPrefix("abc")
|
.defaultPrefix("abc")
|
||||||
@ -121,10 +121,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)21)
|
.debitorNumberSuffix((byte)21)
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||||
.anchor(givenPartnerPerson)
|
.relAnchor(givenPartnerPerson)
|
||||||
.holder(givenPartnerPerson)
|
.relHolder(givenPartnerPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build())
|
.build())
|
||||||
.billable(true)
|
.billable(true)
|
||||||
@ -156,10 +156,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenContact = one(contactRepo.findContactByOptionalLabelLike("fourth contact"));
|
final var givenContact = one(contactRepo.findContactByOptionalLabelLike("fourth contact"));
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)22)
|
.debitorNumberSuffix((byte)22)
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||||
.anchor(givenPartnerPerson)
|
.relAnchor(givenPartnerPerson)
|
||||||
.holder(givenDebitorPerson)
|
.relHolder(givenDebitorPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build())
|
.build())
|
||||||
.defaultPrefix("abc")
|
.defaultPrefix("abc")
|
||||||
@ -171,45 +171,45 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// then
|
// then
|
||||||
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
||||||
initialRoleNames,
|
initialRoleNames,
|
||||||
"hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.owner",
|
"hs_office_relationship#FirstGmbH-with-ACCOUNTING-FourtheG.owner",
|
||||||
"hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.admin",
|
"hs_office_relationship#FirstGmbH-with-ACCOUNTING-FourtheG.admin",
|
||||||
"hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.agent",
|
"hs_office_relationship#FirstGmbH-with-ACCOUNTING-FourtheG.agent",
|
||||||
"hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.tenant"));
|
"hs_office_relationship#FirstGmbH-with-ACCOUNTING-FourtheG.tenant"));
|
||||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
||||||
.map(s -> s.replace("hs_office_", ""))
|
.map(s -> s.replace("hs_office_", ""))
|
||||||
.containsExactlyInAnyOrder(Array.fromFormatted(
|
.containsExactlyInAnyOrder(Array.fromFormatted(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
// FIXME: the next line is completely wrong, the format as well that it exists
|
// FIXME: the next line is completely wrong, the format as well that it exists
|
||||||
"{ grant perm INSERT on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }",
|
"{ grant perm INSERT on relationship#FirstGmbH-with-ACCOUNTING-FourtheG to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.admin by system and assume }",
|
||||||
|
|
||||||
// owner
|
// owner
|
||||||
"{ grant perm DELETE on debitor#D-1000122 to role relation#FirstGmbH-with-DEBITOR-FourtheG.owner by system and assume }",
|
"{ grant perm DELETE on debitor#D-1000122 to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.owner by system and assume }",
|
||||||
"{ grant perm DELETE on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.owner by system and assume }",
|
"{ grant perm DELETE on relationship#FirstGmbH-with-ACCOUNTING-FourtheG to role relationship#FirstGmbH-with-ACCOUNTING-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 relationship#FirstGmbH-with-ACCOUNTING-FourtheG.owner to role global#global.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 }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.owner to user superuser-alex@hostsharing.net by relationship#FirstGmbH-with-ACCOUNTING-FourtheG.owner and assume }",
|
||||||
|
|
||||||
// admin
|
// admin
|
||||||
"{ grant perm UPDATE on debitor#D-1000122 to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }",
|
"{ grant perm UPDATE on debitor#D-1000122 to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.admin by system and assume }",
|
||||||
"{ grant perm UPDATE on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }",
|
"{ grant perm UPDATE on relationship#FirstGmbH-with-ACCOUNTING-FourtheG to role relationship#FirstGmbH-with-ACCOUNTING-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 relationship#FirstGmbH-with-ACCOUNTING-FourtheG.admin to role relationship#FirstGmbH-with-ACCOUNTING-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 relationship#FirstGmbH-with-ACCOUNTING-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 }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.admin to role relationship#HostsharingeG-with-PARTNER-FirstGmbH.admin by system and assume }",
|
||||||
|
|
||||||
// agent
|
// agent
|
||||||
"{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.agent to role person#FourtheG.admin by system and assume }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.agent to role person#FourtheG.admin by system and assume }",
|
||||||
"{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.agent to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.agent to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.admin by system and assume }",
|
||||||
"{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.agent to role relation#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.agent to role relationship#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }",
|
||||||
|
|
||||||
// tenant
|
// tenant
|
||||||
"{ grant perm SELECT on debitor#D-1000122 to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }",
|
"{ grant perm SELECT on debitor#D-1000122 to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.tenant by system and assume }",
|
||||||
"{ grant perm SELECT on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }",
|
"{ grant perm SELECT on relationship#FirstGmbH-with-ACCOUNTING-FourtheG to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.tenant by system and assume }",
|
||||||
"{ grant role relation#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role relation#FirstGmbH-with-DEBITOR-FourtheG.agent by system and assume }",
|
"{ grant role relationship#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.agent by system and assume }",
|
||||||
"{ grant role contact#fourthcontact.referrer to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }",
|
"{ grant role contact#fourthcontact.referrer to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.tenant by system and assume }",
|
||||||
"{ grant role person#FirstGmbH.referrer to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }",
|
"{ grant role person#FirstGmbH.referrer to role relationship#FirstGmbH-with-ACCOUNTING-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 person#FourtheG.referrer to role relationship#FirstGmbH-with-ACCOUNTING-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 relationship#FirstGmbH-with-ACCOUNTING-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 relationship#FirstGmbH-with-ACCOUNTING-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 }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.tenant to role relationship#FirstGmbH-with-ACCOUNTING-FourtheG.agent by system and assume }",
|
||||||
|
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
@ -235,9 +235,9 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// then
|
// then
|
||||||
allTheseDebitorsAreReturned(
|
allTheseDebitorsAreReturned(
|
||||||
result,
|
result,
|
||||||
"debitor(D-1000111: rel(anchor='LP First GmbH', type='DEBITOR', holder='LP First GmbH'), fir)",
|
"debitor(D-1000111: rel(relAnchor='LP First GmbH', relType='ACCOUNTING', relHolder='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(relAnchor='LP Second e.K.', relType='ACCOUNTING', relHolder='LP Second e.K.'), sec)",
|
||||||
"debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
|
"debitor(D-1000313: rel(relAnchor='IF Third OHG', relType='ACCOUNTING', relHolder='IF Third OHG'), thi)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ -286,7 +286,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
exactlyTheseDebitorsAreReturned(result,
|
exactlyTheseDebitorsAreReturned(result,
|
||||||
"debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
|
"debitor(D-1000313: rel(relAnchor='IF Third OHG', relType='ACCOUNTING', relHolder='IF Third OHG'), thi)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var result = debitorRepo.findDebitorByOptionalNameLike("third contact");
|
final var result = debitorRepo.findDebitorByOptionalNameLike("third contact");
|
||||||
|
|
||||||
// then
|
// then
|
||||||
exactlyTheseDebitorsAreReturned(result, "debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
|
exactlyTheseDebitorsAreReturned(result, "debitor(D-1000313: rel(relAnchor='IF Third OHG', relType='ACCOUNTING', relHolder='IF Third OHG'), thi)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
|
|
||||||
assertThatDebitorIsVisibleForUserWithRole(
|
assertThatDebitorIsVisibleForUserWithRole(
|
||||||
givenDebitor,
|
givenDebitor,
|
||||||
"hs_office_relation#FourtheG-with-DEBITOR-FourtheG.admin");
|
"hs_office_relationship#FourtheG-with-ACCOUNTING-FourtheG.admin");
|
||||||
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(contactRepo.findContactByOptionalLabelLike("sixth contact"));
|
final var givenNewContact = one(contactRepo.findContactByOptionalLabelLike("sixth contact"));
|
||||||
@ -329,10 +329,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
givenDebitor.setDebitorRel(HsOfficeRelationEntity.builder()
|
givenDebitor.setDebitorRel(HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||||
.anchor(givenNewPartnerPerson)
|
.relAnchor(givenNewPartnerPerson)
|
||||||
.holder(givenNewBillingPerson)
|
.relHolder(givenNewBillingPerson)
|
||||||
.contact(givenNewContact)
|
.contact(givenNewContact)
|
||||||
.build());
|
.build());
|
||||||
givenDebitor.setRefundBankAccount(givenNewBankAccount);
|
givenDebitor.setRefundBankAccount(givenNewBankAccount);
|
||||||
@ -351,10 +351,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");
|
"hs_office_relationship#FourtheG-with-ACCOUNTING-FourtheG.admin");
|
||||||
assertThatDebitorIsVisibleForUserWithRole(
|
assertThatDebitorIsVisibleForUserWithRole(
|
||||||
result.returnedValue(),
|
result.returnedValue(),
|
||||||
"hs_office_relation#FirstGmbH-with-DEBITOR-FirbySusan.agent");
|
"hs_office_relationship#FirstGmbH-with-ACCOUNTING-FirbySusan.agent");
|
||||||
|
|
||||||
// ... contact role was reassigned:
|
// ... contact role was reassigned:
|
||||||
assertThatDebitorIsNotVisibleForUserWithRole(
|
assertThatDebitorIsNotVisibleForUserWithRole(
|
||||||
@ -380,7 +380,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", null, "fig");
|
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", null, "fig");
|
||||||
assertThatDebitorIsVisibleForUserWithRole(
|
assertThatDebitorIsVisibleForUserWithRole(
|
||||||
givenDebitor,
|
givenDebitor,
|
||||||
"hs_office_relation#FourtheG-with-DEBITOR-FourtheG.admin");
|
"hs_office_relationship#FourtheG-with-ACCOUNTING-FourtheG.admin");
|
||||||
assertThatDebitorActuallyInDatabase(givenDebitor);
|
assertThatDebitorActuallyInDatabase(givenDebitor);
|
||||||
final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first"));
|
final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first"));
|
||||||
|
|
||||||
@ -410,7 +410,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fih");
|
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fih");
|
||||||
assertThatDebitorIsVisibleForUserWithRole(
|
assertThatDebitorIsVisibleForUserWithRole(
|
||||||
givenDebitor,
|
givenDebitor,
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-FourtheG.agent");
|
"hs_office_relationship#HostsharingeG-with-PARTNER-FourtheG.agent");
|
||||||
assertThatDebitorActuallyInDatabase(givenDebitor);
|
assertThatDebitorActuallyInDatabase(givenDebitor);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -439,12 +439,12 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "eighth", "Fourth", "eig");
|
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "eighth", "Fourth", "eig");
|
||||||
assertThatDebitorIsVisibleForUserWithRole(
|
assertThatDebitorIsVisibleForUserWithRole(
|
||||||
givenDebitor,
|
givenDebitor,
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-FourtheG.agent");
|
"hs_office_relationship#HostsharingeG-with-PARTNER-FourtheG.agent");
|
||||||
assertThatDebitorActuallyInDatabase(givenDebitor);
|
assertThatDebitorActuallyInDatabase(givenDebitor);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net", "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG.agent");
|
context("superuser-alex@hostsharing.net", "hs_office_relationship#HostsharingeG-with-PARTNER-FourtheG.agent");
|
||||||
givenDebitor.setVatId("NEW-VAT-ID");
|
givenDebitor.setVatId("NEW-VAT-ID");
|
||||||
return toCleanup(debitorRepo.save(givenDebitor));
|
return toCleanup(debitorRepo.save(givenDebitor));
|
||||||
});
|
});
|
||||||
@ -489,7 +489,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
if ( saved.getPartner() != null) { // FIXME: check, why there is no partner for the updated contact
|
if ( saved.getPartner() != null) { // FIXME: check, why there is no partner for the updated contact
|
||||||
assertThat(foundEntity.getPartner()).isNotNull();
|
assertThat(foundEntity.getPartner()).isNotNull();
|
||||||
}
|
}
|
||||||
assertThat(foundEntity.getDebitorRel()).extracting(HsOfficeRelationEntity::toString)
|
assertThat(foundEntity.getDebitorRel()).extracting(HsOfficeRelationshipEntity::toString)
|
||||||
.isEqualTo(saved.getDebitorRel().toString());
|
.isEqualTo(saved.getDebitorRel().toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -545,7 +545,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", "hs_office_relationship#FourtheG-with-ACCOUNTING-FourtheG.admin");
|
||||||
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent();
|
assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent();
|
||||||
|
|
||||||
debitorRepo.deleteByUuid(givenDebitor.getUuid());
|
debitorRepo.deleteByUuid(givenDebitor.getUuid());
|
||||||
@ -614,10 +614,10 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null;
|
bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null;
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)20)
|
.debitorNumberSuffix((byte)20)
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||||
.anchor(givenPartnerPerson)
|
.relAnchor(givenPartnerPerson)
|
||||||
.holder(givenPartnerPerson)
|
.relHolder(givenPartnerPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build())
|
.build())
|
||||||
.refundBankAccount(givenBankAccount)
|
.refundBankAccount(givenBankAccount)
|
||||||
|
@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.office.debitor;
|
|||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT;
|
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT;
|
||||||
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;
|
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;
|
||||||
@ -14,9 +14,9 @@ public class TestHsOfficeDebitor {
|
|||||||
|
|
||||||
public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder()
|
public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX)
|
.debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX)
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationshipEntity.builder()
|
||||||
.holder(HsOfficePersonEntity.builder().build())
|
.relHolder(HsOfficePersonEntity.builder().build())
|
||||||
.anchor(HsOfficePersonEntity.builder().build())
|
.relAnchor(HsOfficePersonEntity.builder().build())
|
||||||
.contact(TEST_CONTACT)
|
.contact(TEST_CONTACT)
|
||||||
.build())
|
.build())
|
||||||
.partner(TEST_PARTNER)
|
.partner(TEST_PARTNER)
|
||||||
|
@ -269,7 +269,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle
|
|||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.header("assumed-roles", "hs_office_relation#HostsharingeG-with-PARTNER-ThirdOHG.agent")
|
.header("assumed-roles", "hs_office_relationship#HostsharingeG-with-PARTNER-ThirdOHG.agent")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/office/memberships/" + givenMembershipUuid)
|
.get("http://localhost/api/hs/office/memberships/" + givenMembershipUuid)
|
||||||
@ -338,7 +338,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle
|
|||||||
void partnerRelAgent_canPatchValidityOfRelatedMembership() {
|
void partnerRelAgent_canPatchValidityOfRelatedMembership() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent";
|
final var givenPartnerAgent = "hs_office_relationship#HostsharingeG-with-PARTNER-FirstGmbH.agent";
|
||||||
context.define("superuser-alex@hostsharing.net", givenPartnerAgent);
|
context.define("superuser-alex@hostsharing.net", givenPartnerAgent);
|
||||||
final var givenMembership = givenSomeTemporaryMembershipBessler("First");
|
final var givenMembership = givenSomeTemporaryMembershipBessler("First");
|
||||||
|
|
||||||
@ -401,7 +401,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle
|
|||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.header("assumed-roles", "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent")
|
.header("assumed-roles", "hs_office_relationship#HostsharingeG-with-PARTNER-FirstGmbH.agent")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.delete("http://localhost/api/hs/office/memberships/" + givenMembership.getUuid())
|
.delete("http://localhost/api/hs/office/memberships/" + givenMembership.getUuid())
|
||||||
|
@ -126,16 +126,16 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
|||||||
// admin
|
// admin
|
||||||
"{ grant perm UPDATE on membership#M-1000117 to role membership#M-1000117.admin by system and assume }",
|
"{ grant perm UPDATE on membership#M-1000117 to role membership#M-1000117.admin by system and assume }",
|
||||||
"{ grant role membership#M-1000117.admin to role membership#M-1000117.owner by system and assume }",
|
"{ grant role membership#M-1000117.admin to role membership#M-1000117.owner by system and assume }",
|
||||||
"{ grant role membership#M-1000117.owner to role relation#HostsharingeG-with-PARTNER-FirstGmbH.admin by system and assume }",
|
"{ grant role membership#M-1000117.owner to role relationship#HostsharingeG-with-PARTNER-FirstGmbH.admin by system and assume }",
|
||||||
"{ grant role membership#M-1000117.owner to user superuser-alex@hostsharing.net by membership#M-1000117.owner and assume }",
|
"{ grant role membership#M-1000117.owner to user superuser-alex@hostsharing.net by membership#M-1000117.owner and assume }",
|
||||||
|
|
||||||
// agent
|
// agent
|
||||||
"{ grant role membership#M-1000117.admin to role relation#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }",
|
"{ grant role membership#M-1000117.admin to role relationship#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }",
|
||||||
|
|
||||||
// referrer
|
// referrer
|
||||||
"{ grant perm SELECT on membership#M-1000117 to role membership#M-1000117.referrer by system and assume }",
|
"{ grant perm SELECT on membership#M-1000117 to role membership#M-1000117.referrer by system and assume }",
|
||||||
"{ grant role membership#M-1000117.referrer to role membership#M-1000117.admin by system and assume }",
|
"{ grant role membership#M-1000117.referrer to role membership#M-1000117.admin by system and assume }",
|
||||||
"{ grant role relation#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role membership#M-1000117.referrer by system and assume }",
|
"{ grant role relationship#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role membership#M-1000117.referrer by system and assume }",
|
||||||
|
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net", "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent");
|
context("superuser-alex@hostsharing.net", "hs_office_relationship#HostsharingeG-with-PARTNER-FirstGmbH.agent");
|
||||||
assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent();
|
assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent();
|
||||||
|
|
||||||
membershipRepo.deleteByUuid(givenMembership.getUuid());
|
membershipRepo.deleteByUuid(givenMembership.getUuid());
|
||||||
|
@ -18,8 +18,8 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
|
|||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
|
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
@ -127,7 +127,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
new String[]{"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"},
|
new String[]{"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"},
|
||||||
SUBSCRIBER_ROLES);
|
SUBSCRIBER_ROLES);
|
||||||
|
|
||||||
static int relationId = 2000000;
|
static int relationshipId = 2000000;
|
||||||
|
|
||||||
@Value("${spring.datasource.url}")
|
@Value("${spring.datasource.url}")
|
||||||
private String jdbcUrl;
|
private String jdbcUrl;
|
||||||
@ -144,7 +144,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
private static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>();
|
private static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>();
|
||||||
private static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>();
|
private static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>();
|
||||||
|
|
||||||
private static Map<Integer, HsOfficeRelationEntity> relations = new WriteOnceMap<>();
|
private static Map<Integer, HsOfficeRelationshipEntity> relationships = new WriteOnceMap<>();
|
||||||
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>();
|
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>();
|
||||||
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>();
|
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>();
|
||||||
private static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>();
|
private static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>();
|
||||||
@ -161,7 +161,6 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
HttpServletRequest request;
|
HttpServletRequest request;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1010)
|
@Order(1010)
|
||||||
void importBusinessPartners() {
|
void importBusinessPartners() {
|
||||||
@ -175,7 +174,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1019)
|
@Order(1011)
|
||||||
void verifyBusinessPartners() {
|
void verifyBusinessPartners() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
@ -191,17 +190,17 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
assertThat(toFormattedString(contacts)).isEqualTo("{}");
|
assertThat(toFormattedString(contacts)).isEqualTo("{}");
|
||||||
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=debitor(D-1001700: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), mih),
|
17=debitor(D-1001700: P-10017, mih),
|
||||||
20=debitor(D-1002000: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), xyz),
|
20=debitor(D-1002000: P-10020, xyz),
|
||||||
22=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), xxx),
|
22=debitor(D-1102200: P-11022, xxx),
|
||||||
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), zzz)
|
99=debitor(D-1999900: P-19999, zzz)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=Membership(M-1001700, P-10017, [2000-12-06,), NONE),
|
17=Membership(M-1001700, P-10017, D-1001700, [2000-12-06,), NONE),
|
||||||
20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
20=Membership(M-1002000, P-10020, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
|
||||||
22=Membership(M-1102200, P-11022, [2021-04-01,), NONE)
|
22=Membership(M-1102200, P-11022, D-1102200, [2021-04-01,), NONE)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -220,23 +219,6 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1021)
|
@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() {
|
void verifyContacts() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
@ -275,42 +257,38 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=debitor(D-1001700: rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael'), mih),
|
17=debitor(D-1001700: P-10017, mih),
|
||||||
20=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz),
|
20=debitor(D-1002000: P-10020, xyz),
|
||||||
22=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx),
|
22=debitor(D-1102200: P-11022, xxx),
|
||||||
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), zzz)
|
99=debitor(D-1999900: P-19999, zzz)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
17=Membership(M-1001700, P-10017, [2000-12-06,), NONE),
|
17=Membership(M-1001700, P-10017, D-1001700, [2000-12-06,), NONE),
|
||||||
20=Membership(M-1002000, P-10020, [2000-12-06,2016-01-01), UNKNOWN),
|
20=Membership(M-1002000, P-10020, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
|
||||||
22=Membership(M-1102200, P-11022, [2021-04-01,), NONE)
|
22=Membership(M-1102200, P-11022, D-1102200, [2021-04-01,), NONE)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(toFormattedString(relations)).isEqualToIgnoringWhitespace("""
|
assertThat(toFormattedString(relationships)).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000000=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||||
2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000001=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000002=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000003=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
|
2000003=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='null null, null'),
|
||||||
2000004=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000004=rel(relAnchor='NP Mellies, Michael', relType='OPERATIONS', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||||
2000005=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000005=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||||
2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
|
2000006=rel(relAnchor='LP JM GmbH', relType='EX_PARTNER', relHolder='LP JM e.K.', contact='JM e.K.'),
|
||||||
2000007=rel(anchor='null null, null', type='DEBITOR', holder='null null, null'),
|
2000007=rel(relAnchor='LP JM GmbH', relType='OPERATIONS', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
2000008=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000008=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
2000009=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000009=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='operations-announce', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
2000010=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
|
2000010=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000011=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000011=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='members-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000012=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000012=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='customers-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000013=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000013=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
||||||
2000014=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000014=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000015=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000015=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000016=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000016=rel(relAnchor='NP Mellies, Michael', relType='SUBSCRIBER', relMark='operations-announce', relHolder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
|
||||||
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 ')
|
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -328,7 +306,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1039)
|
@Order(1031)
|
||||||
void verifySepaMandates() {
|
void verifySepaMandates() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
@ -387,7 +365,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1059)
|
@Order(1051)
|
||||||
void verifyCoopAssets() {
|
void verifyCoopAssets() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
@ -407,35 +385,35 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(2000)
|
@Order(2000)
|
||||||
void verifyAllPartnersHavePersons() {
|
void verifyAllPartnersHaveProperPartnerRoles() {
|
||||||
partners.forEach((id, p) -> {
|
partners.forEach((id, p) -> {
|
||||||
final var partnerRel = p.getPartnerRel();
|
final var partnerRole = p.getPartnerRole();
|
||||||
assertThat(partnerRel).describedAs("partner " + id + " without partnerRel").isNotNull();
|
assertThat(partnerRole).describedAs("partner " + id + " without partnerRole").isNotNull();
|
||||||
if ( id != 99 ) {
|
if ( id != 99 ) {
|
||||||
assertThat(partnerRel.getContact()).describedAs("partner " + id + " without partnerRel.contact").isNotNull();
|
assertThat(partnerRole.getContact()).describedAs("partner " + id + " without partnerRole.contact").isNotNull();
|
||||||
assertThat(partnerRel.getContact().getLabel()).describedAs("partner " + id + " without valid partnerRel.contact").isNotNull();
|
assertThat(partnerRole.getContact().getLabel()).describedAs("partner " + id + " without valid partnerRole.contact").isNotNull();
|
||||||
assertThat(partnerRel.getHolder()).describedAs("partner " + id + " without partnerRel.relHolder").isNotNull();
|
assertThat(partnerRole.getRelHolder()).describedAs("partner " + id + " without partnerRole.relHolder").isNotNull();
|
||||||
assertThat(partnerRel.getHolder().getPersonType()).describedAs("partner " + id + " without valid partnerRel.relHolder").isNotNull();
|
assertThat(partnerRole.getRelHolder().getPersonType()).describedAs("partner " + id + " without valid partnerRole.relHolder").isNotNull();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(2009)
|
@Order(2001)
|
||||||
void removeEmptyRelations() {
|
void removeEmptyRelationships() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
// avoid a error when persisting the deliberetely invalid partner entry #99
|
// avoid a error when persisting the deliberetely invalid partner entry #99
|
||||||
final var idsToRemove = new HashSet<Integer>();
|
final var idsToRemove = new HashSet<Integer>();
|
||||||
relations.forEach( (id, r) -> {
|
relationships.forEach( (id, r) -> {
|
||||||
// such a record
|
// such a record
|
||||||
if (r.getContact() == null || r.getContact().getLabel() == null ||
|
if (r.getContact() == null || r.getContact().getLabel() == null ||
|
||||||
r.getHolder() == null || r.getHolder().getPersonType() == null ) {
|
r.getRelHolder() == null | r.getRelHolder().getPersonType() == null ) {
|
||||||
idsToRemove.add(id);
|
idsToRemove.add(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assertThat(idsToRemove.size()).isEqualTo(2); // partner #99 + Hostsharing eG itself
|
assertThat(idsToRemove.size()).isEqualTo(1); // only from partner #99 (partner+contractual roles)
|
||||||
idsToRemove.forEach(id -> relations.remove(id));
|
idsToRemove.forEach(id -> relationships.remove(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -446,11 +424,11 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
// avoid a error when persisting the deliberately invalid partner entry #99
|
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||||
final var idsToRemove = new HashSet<Integer>();
|
final var idsToRemove = new HashSet<Integer>();
|
||||||
partners.forEach( (id, r) -> {
|
partners.forEach( (id, r) -> {
|
||||||
final var partnerRole = r.getPartnerRel();
|
final var partnerRole = r.getPartnerRole();
|
||||||
|
|
||||||
// such a record is in test data to test error messages
|
// such a record is in test data to test error messages
|
||||||
if (partnerRole.getContact() == null || partnerRole.getContact().getLabel() == null ||
|
if (partnerRole.getContact() == null || partnerRole.getContact().getLabel() == null ||
|
||||||
partnerRole.getHolder() == null | partnerRole.getHolder().getPersonType() == null ) {
|
partnerRole.getRelHolder() == null | partnerRole.getRelHolder().getPersonType() == null ) {
|
||||||
idsToRemove.add(id);
|
idsToRemove.add(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -466,10 +444,8 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
// avoid a error when persisting the deliberately invalid partner entry #99
|
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||||
final var idsToRemove = new HashSet<Integer>();
|
final var idsToRemove = new HashSet<Integer>();
|
||||||
debitors.forEach( (id, d) -> {
|
debitors.forEach( (id, d) -> {
|
||||||
final var debitorRel = d.getDebitorRel();
|
// such a record is in test data to test error messages
|
||||||
if (debitorRel.getContact() == null || debitorRel.getContact().getLabel() == null ||
|
if (false) { // TODO: how can I now empty debitors?
|
||||||
debitorRel.getAnchor() == null || debitorRel.getAnchor().getPersonType() == null ||
|
|
||||||
debitorRel.getHolder() == null || debitorRel.getHolder().getPersonType() == null ) {
|
|
||||||
idsToRemove.add(id);
|
idsToRemove.add(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -478,6 +454,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled
|
||||||
@Order(3000)
|
@Order(3000)
|
||||||
@Commit
|
@Commit
|
||||||
void persistEntities() {
|
void persistEntities() {
|
||||||
@ -501,7 +478,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
|
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context(rbacSuperuser);
|
context(rbacSuperuser);
|
||||||
relations.forEach(this::persist);
|
relationships.forEach(this::persist);
|
||||||
}).assertSuccessful();
|
}).assertSuccessful();
|
||||||
|
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
@ -578,7 +555,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
em.createNativeQuery("delete from hs_office_bankaccount where true").executeUpdate();
|
em.createNativeQuery("delete from hs_office_bankaccount where true").executeUpdate();
|
||||||
em.createNativeQuery("delete from hs_office_partner where true").executeUpdate();
|
em.createNativeQuery("delete from hs_office_partner where true").executeUpdate();
|
||||||
em.createNativeQuery("delete from hs_office_partner_details where true").executeUpdate();
|
em.createNativeQuery("delete from hs_office_partner_details where true").executeUpdate();
|
||||||
em.createNativeQuery("delete from hs_office_relation where true").executeUpdate();
|
em.createNativeQuery("delete from hs_office_relationship where true").executeUpdate();
|
||||||
em.createNativeQuery("delete from hs_office_contact where true").executeUpdate();
|
em.createNativeQuery("delete from hs_office_contact where true").executeUpdate();
|
||||||
em.createNativeQuery("delete from hs_office_person where true").executeUpdate();
|
em.createNativeQuery("delete from hs_office_person where true").executeUpdate();
|
||||||
}).assertSuccessful();
|
}).assertSuccessful();
|
||||||
@ -682,32 +659,30 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
.forEach(rec -> {
|
.forEach(rec -> {
|
||||||
final var person = HsOfficePersonEntity.builder().build();
|
final var person = HsOfficePersonEntity.builder().build();
|
||||||
|
|
||||||
final var partnerRel = HsOfficeRelationEntity.builder()
|
final var partnerRelationship = HsOfficeRelationshipEntity.builder()
|
||||||
.holder(person)
|
.relHolder(person)
|
||||||
.type(HsOfficeRelationType.PARTNER)
|
.relType(HsOfficeRelationshipType.PARTNER)
|
||||||
.anchor(mandant)
|
.relAnchor(mandant)
|
||||||
.contact(null) // is set during contacts import depending on assigned roles
|
.contact(null) // is set during contacts import depending on assigned roles
|
||||||
.build();
|
.build();
|
||||||
relations.put(relationId++, partnerRel);
|
relationships.put(relationshipId++, partnerRelationship);
|
||||||
|
|
||||||
final var partner = HsOfficePartnerEntity.builder()
|
final var partner = HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(rec.getInteger("member_id"))
|
.partnerNumber(rec.getInteger("member_id"))
|
||||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||||
.partnerRel(partnerRel)
|
.partnerRole(partnerRelationship)
|
||||||
.build();
|
.build();
|
||||||
partners.put(rec.getInteger("bp_id"), partner);
|
partners.put(rec.getInteger("bp_id"), partner);
|
||||||
|
|
||||||
final var debitorRel = HsOfficeRelationEntity.builder()
|
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
|
||||||
.anchor(partnerRel.getHolder())
|
|
||||||
.holder(partnerRel.getHolder()) // currently debitor = partner
|
|
||||||
.build();
|
|
||||||
relations.put(relationId++, debitorRel);
|
|
||||||
|
|
||||||
final var debitor = HsOfficeDebitorEntity.builder()
|
final var debitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte) 0)
|
.debitorNumberSuffix((byte) 0)
|
||||||
.partner(partner)
|
.debitorRel(
|
||||||
.debitorRel(debitorRel)
|
HsOfficeRelationshipEntity.builder()
|
||||||
|
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||||
|
.relAnchor(partnerRelationship.getRelHolder())
|
||||||
|
.relHolder(null) // gets set later
|
||||||
|
.build()
|
||||||
|
)
|
||||||
.defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
|
.defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
|
||||||
.billable(rec.isEmpty("free") || rec.getString("free").equals("f"))
|
.billable(rec.isEmpty("free") || rec.getString("free").equals("f"))
|
||||||
.vatReverseCharge(rec.getBoolean("exempt_vat"))
|
.vatReverseCharge(rec.getBoolean("exempt_vat"))
|
||||||
@ -854,8 +829,8 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
final var partner = partners.get(bpId);
|
final var partner = partners.get(bpId);
|
||||||
final var debitor = debitors.get(bpId);
|
final var debitor = debitors.get(bpId);
|
||||||
|
|
||||||
final var partnerPerson = partner.getPartnerRel().getHolder();
|
final var partnerPerson = partner.getPartnerRole().getRelHolder();
|
||||||
if (containsPartnerRel(rec)) {
|
if (containsPartnerRole(rec)) {
|
||||||
initPerson(partnerPerson, rec);
|
initPerson(partnerPerson, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,45 +844,45 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
final var contact = HsOfficeContactEntity.builder().build();
|
final var contact = HsOfficeContactEntity.builder().build();
|
||||||
initContact(contact, rec);
|
initContact(contact, rec);
|
||||||
|
|
||||||
if (containsPartnerRel(rec)) {
|
if (containsPartnerRole(rec)) {
|
||||||
assertThat(partner.getPartnerRel().getContact()).isNull();
|
assertThat(partner.getPartnerRole().getContact()).isNull();
|
||||||
partner.getPartnerRel().setContact(contact);
|
partner.getPartnerRole().setContact(contact);
|
||||||
}
|
}
|
||||||
if (containsRole(rec, "billing")) {
|
if (containsRole(rec, "billing")) {
|
||||||
assertThat(debitor.getDebitorRel().getContact()).isNull();
|
assertThat(debitor.getDebitorRel().getContact()).isNull();
|
||||||
debitor.getDebitorRel().setContact(contact);
|
debitor.getDebitorRel().setContact(contact);
|
||||||
}
|
}
|
||||||
if (containsRole(rec, "operation")) {
|
if (containsRole(rec, "operation")) {
|
||||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.OPERATIONS);
|
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.OPERATIONS);
|
||||||
}
|
}
|
||||||
if (containsRole(rec, "contractual")) {
|
if (containsRole(rec, "contractual")) {
|
||||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.REPRESENTATIVE);
|
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.REPRESENTATIVE);
|
||||||
}
|
}
|
||||||
if (containsRole(rec, "ex-partner")) {
|
if (containsRole(rec, "ex-partner")) {
|
||||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.EX_PARTNER);
|
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.EX_PARTNER);
|
||||||
}
|
}
|
||||||
if (containsRole(rec, "vip-contact")) {
|
if (containsRole(rec, "vip-contact")) {
|
||||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.VIP_CONTACT);
|
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.VIP_CONTACT);
|
||||||
}
|
}
|
||||||
for (String subscriberRole: SUBSCRIBER_ROLES) {
|
for (String subscriberRole: SUBSCRIBER_ROLES) {
|
||||||
if (containsRole(rec, subscriberRole)) {
|
if (containsRole(rec, subscriberRole)) {
|
||||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.SUBSCRIBER)
|
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.SUBSCRIBER)
|
||||||
.setMark(subscriberRole.split(":")[1])
|
.setRelMark(subscriberRole.split(":")[1])
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verifyContainsOnlyKnownRoles(rec.getString("roles"));
|
verifyContainsOnlyKnownRoles(rec.getString("roles"));
|
||||||
});
|
});
|
||||||
|
|
||||||
optionallyAddMissingContractualRelations();
|
optionallyAddMissingContractualRelationships();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void optionallyAddMissingContractualRelations() {
|
private static void optionallyAddMissingContractualRelationships() {
|
||||||
final var contractualMissing = new HashSet<Integer>();
|
final var contractualMissing = new HashSet<Integer>();
|
||||||
partners.forEach( (id, partner) -> {
|
partners.forEach( (id, partner) -> {
|
||||||
final var partnerPerson = partner.getPartnerRel().getHolder();
|
final var partnerPerson = partner.getPartnerRole().getRelHolder();
|
||||||
if (relations.values().stream()
|
if (relationships.values().stream()
|
||||||
.filter(rel -> rel.getAnchor() == partnerPerson && rel.getType() == HsOfficeRelationType.REPRESENTATIVE)
|
.filter(rel -> rel.getRelAnchor() == partnerPerson && rel.getRelType() == HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
.findFirst().isEmpty()) {
|
.findFirst().isEmpty()) {
|
||||||
contractualMissing.add(partner.getPartnerNumber());
|
contractualMissing.add(partner.getPartnerNumber());
|
||||||
}
|
}
|
||||||
@ -918,23 +893,22 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
final var roles = rec.getString("roles");
|
final var roles = rec.getString("roles");
|
||||||
return ("," + roles + ",").contains("," + role + ",");
|
return ("," + roles + ",").contains("," + role + ",");
|
||||||
}
|
}
|
||||||
|
private static boolean containsPartnerRole(final Record rec) {
|
||||||
private static boolean containsPartnerRel(final Record rec) {
|
|
||||||
return containsRole(rec, "partner");
|
return containsRole(rec, "partner");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HsOfficeRelationEntity addRelation(
|
private static HsOfficeRelationshipEntity addRelationship(
|
||||||
final HsOfficePersonEntity partnerPerson,
|
final HsOfficePersonEntity partnerPerson,
|
||||||
final HsOfficePersonEntity contactPerson,
|
final HsOfficePersonEntity contactPerson,
|
||||||
final HsOfficeContactEntity contact,
|
final HsOfficeContactEntity contact,
|
||||||
final HsOfficeRelationType representative) {
|
final HsOfficeRelationshipType representative) {
|
||||||
final var rel = HsOfficeRelationEntity.builder()
|
final var rel = HsOfficeRelationshipEntity.builder()
|
||||||
.anchor(partnerPerson)
|
.relAnchor(partnerPerson)
|
||||||
.holder(contactPerson)
|
.relHolder(contactPerson)
|
||||||
.contact(contact)
|
.contact(contact)
|
||||||
.type(representative)
|
.relType(representative)
|
||||||
.build();
|
.build();
|
||||||
relations.put(relationId++, rel);
|
relationships.put(relationshipId++, rel);
|
||||||
return rel;
|
return rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
|||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRepository;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.test.Accepts;
|
import net.hostsharing.test.Accepts;
|
||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
@ -41,7 +41,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
HsOfficePartnerRepository partnerRepo;
|
HsOfficePartnerRepository partnerRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeRelationRepository relationRepository;
|
HsOfficeRelationshipRepository relationshipRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficePersonRepository personRepo;
|
HsOfficePersonRepository personRepo;
|
||||||
@ -102,9 +102,9 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"partnerNumber": "20002",
|
"partnerNumber": "20002",
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
@ -125,11 +125,11 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"partnerNumber": 20002,
|
"partnerNumber": 20002,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": { "tradeName": "Hostsharing eG" },
|
"relAnchor": { "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "tradeName": "Third OHG" },
|
"relHolder": { "tradeName": "Third OHG" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": { "label": "fourth contact" }
|
"contact": { "label": "fourth contact" }
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
@ -161,9 +161,9 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"partnerNumber": "20003",
|
"partnerNumber": "20003",
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"personUuid": "%s",
|
"personUuid": "%s",
|
||||||
@ -199,9 +199,9 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"partnerNumber": "20004",
|
"partnerNumber": "20004",
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"personUuid": "%s",
|
"personUuid": "%s",
|
||||||
@ -247,10 +247,10 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"partnerNumber": 10001,
|
"partnerNumber": 10001,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": { "tradeName": "Hostsharing eG" },
|
"relAnchor": { "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "tradeName": "First GmbH" },
|
"relHolder": { "tradeName": "First GmbH" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"contact": { "label": "first contact" }
|
"contact": { "label": "first contact" }
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
@ -295,8 +295,8 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"holder": { "tradeName": "First GmbH" },
|
"relHolder": { "tradeName": "First GmbH" },
|
||||||
"contact": { "label": "first contact" }
|
"contact": { "label": "first contact" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"partnerNumber": "20011",
|
"partnerNumber": "20011",
|
||||||
"partnerRelUuid": "%s",
|
"partnerRoleUuid": "%s",
|
||||||
"details": {
|
"details": {
|
||||||
"registrationOffice": "Temp Registergericht Aurich",
|
"registrationOffice": "Temp Registergericht Aurich",
|
||||||
"registrationNumber": "222222",
|
"registrationNumber": "222222",
|
||||||
@ -342,10 +342,10 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"partnerNumber": 20011,
|
"partnerNumber": 20011,
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchor": { "tradeName": "Hostsharing eG" },
|
"relAnchor": { "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "tradeName": "Third OHG" },
|
"relHolder": { "tradeName": "Third OHG" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"contact": { "label": "third contact" }
|
"contact": { "label": "third contact" }
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
@ -365,8 +365,8 @@ 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.getPartnerRole().getRelHolder().getTradeName()).isEqualTo("Third OHG");
|
||||||
assertThat(partner.getPartnerRel().getContact().getLabel()).isEqualTo("third contact");
|
assertThat(partner.getPartnerRole().getContact().getLabel()).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");
|
||||||
assertThat(partner.getDetails().getBirthName()).isEqualTo("Maja Schmidt");
|
assertThat(partner.getDetails().getBirthName()).isEqualTo("Maja Schmidt");
|
||||||
@ -403,7 +403,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("uuid", isUuidValid())
|
.body("uuid", isUuidValid())
|
||||||
.body("details.birthName", is("Maja Schmidt"));
|
.body("details.birthName", is("Maja Schmidt"));
|
||||||
// TODO: assert partnerRel
|
// TODO: assert partnerRole
|
||||||
// .body("contact.label", is(givenPartner.getContact().getLabel()))
|
// .body("contact.label", is(givenPartner.getContact().getLabel()))
|
||||||
// .body("person.tradeName", is(givenPartner.getPerson().getTradeName()));
|
// .body("person.tradeName", is(givenPartner.getPerson().getTradeName()));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
@ -411,7 +411,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
// finally, the partner is actually updated
|
// finally, the partner is actually updated
|
||||||
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get()
|
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get()
|
||||||
.matches(person -> {
|
.matches(person -> {
|
||||||
// TODO: assert partnerRel
|
// TODO: assert partnerRole
|
||||||
// assertThat(person.getPerson().getTradeName()).isEqualTo(givenPartner.getPerson().getTradeName());
|
// assertThat(person.getPerson().getTradeName()).isEqualTo(givenPartner.getPerson().getTradeName());
|
||||||
// assertThat(person.getContact().getLabel()).isEqualTo(givenPartner.getContact().getLabel());
|
// assertThat(person.getContact().getLabel()).isEqualTo(givenPartner.getContact().getLabel());
|
||||||
assertThat(person.getDetails().getRegistrationOffice()).isEqualTo("Temp Registergericht Leer");
|
assertThat(person.getDetails().getRegistrationOffice()).isEqualTo("Temp Registergericht Leer");
|
||||||
@ -446,7 +446,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
|
|
||||||
// then the given partner is gone
|
// then the given partner is gone
|
||||||
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isEmpty();
|
assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isEmpty();
|
||||||
assertThat(relationRepository.findByUuid(givenPartner.getPartnerRel().getUuid())).isEmpty();
|
assertThat(relationshipRepository.findByUuid(givenPartner.getPartnerRole().getUuid())).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -454,7 +454,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
void contactAdminUser_canNotDeleteRelatedPartner() {
|
void contactAdminUser_canNotDeleteRelatedPartner() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenPartner = givenSomeTemporaryPartnerBessler(20014);
|
final var givenPartner = givenSomeTemporaryPartnerBessler(20014);
|
||||||
assertThat(givenPartner.getPartnerRel().getContact().getLabel()).isEqualTo("fourth contact");
|
assertThat(givenPartner.getPartnerRole().getContact().getLabel()).isEqualTo("fourth contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -474,7 +474,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
void normalUser_canNotDeleteUnrelatedPartner() {
|
void normalUser_canNotDeleteUnrelatedPartner() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenPartner = givenSomeTemporaryPartnerBessler(20015);
|
final var givenPartner = givenSomeTemporaryPartnerBessler(20015);
|
||||||
assertThat(givenPartner.getPartnerRel().getContact().getLabel()).isEqualTo("fourth contact");
|
assertThat(givenPartner.getPartnerRole().getContact().getLabel()).isEqualTo("fourth contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -490,7 +490,7 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity givenSomeTemporaryPartnerRel(
|
private HsOfficeRelationshipEntity givenSomeTemporaryPartnerRel(
|
||||||
final String partnerHolderName,
|
final String partnerHolderName,
|
||||||
final String contactName) {
|
final String contactName) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
@ -499,22 +499,22 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
final var givenPerson = personRepo.findPersonByOptionalNameLike(partnerHolderName).stream().findFirst().orElseThrow();
|
final var givenPerson = personRepo.findPersonByOptionalNameLike(partnerHolderName).stream().findFirst().orElseThrow();
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike(contactName).stream().findFirst().orElseThrow();
|
final var givenContact = contactRepo.findContactByOptionalLabelLike(contactName).stream().findFirst().orElseThrow();
|
||||||
|
|
||||||
final var partnerRel = new HsOfficeRelationEntity();
|
final var partnerRole = new HsOfficeRelationshipEntity();
|
||||||
partnerRel.setType(HsOfficeRelationType.PARTNER);
|
partnerRole.setRelType(HsOfficeRelationshipType.PARTNER);
|
||||||
partnerRel.setAnchor(givenMandantPerson);
|
partnerRole.setRelAnchor(givenMandantPerson);
|
||||||
partnerRel.setHolder(givenPerson);
|
partnerRole.setRelHolder(givenPerson);
|
||||||
partnerRel.setContact(givenContact);
|
partnerRole.setContact(givenContact);
|
||||||
em.persist(partnerRel);
|
em.persist(partnerRole);
|
||||||
return partnerRel;
|
return partnerRole;
|
||||||
}).assertSuccessful().returnedValue();
|
}).assertSuccessful().returnedValue();
|
||||||
}
|
}
|
||||||
private HsOfficePartnerEntity givenSomeTemporaryPartnerBessler(final Integer partnerNumber) {
|
private HsOfficePartnerEntity givenSomeTemporaryPartnerBessler(final Integer partnerNumber) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var partnerRel = em.merge(givenSomeTemporaryPartnerRel("Erben Bessler", "fourth contact"));
|
final var partnerRole = em.merge(givenSomeTemporaryPartnerRel("Erben Bessler", "fourth contact"));
|
||||||
|
|
||||||
final var newPartner = HsOfficePartnerEntity.builder()
|
final var newPartner = HsOfficePartnerEntity.builder()
|
||||||
.partnerRel(partnerRel)
|
.partnerRole(partnerRole)
|
||||||
.partnerNumber(partnerNumber)
|
.partnerNumber(partnerNumber)
|
||||||
.details(HsOfficePartnerDetailsEntity.builder()
|
.details(HsOfficePartnerDetailsEntity.builder()
|
||||||
.registrationOffice("Temp Registergericht Leer")
|
.registrationOffice("Temp Registergericht Leer")
|
||||||
@ -531,6 +531,6 @@ class HsOfficePartnerControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
cleanupAllNew(HsOfficePartnerEntity.class);
|
cleanupAllNew(HsOfficePartnerEntity.class);
|
||||||
|
|
||||||
// TODO: should not be necessary anymore, once it's deleted via after delete trigger
|
// TODO: should not be necessary anymore, once it's deleted via after delete trigger
|
||||||
cleanupAllNew(HsOfficeRelationEntity.class);
|
cleanupAllNew(HsOfficeRelationshipEntity.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package net.hostsharing.hsadminng.hs.office.partner;
|
|||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRepository;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipRepository;
|
||||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Nested;
|
import org.junit.jupiter.api.Nested;
|
||||||
@ -54,7 +54,7 @@ class HsOfficePartnerControllerRestTest {
|
|||||||
HsOfficePartnerRepository partnerRepo;
|
HsOfficePartnerRepository partnerRepo;
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
HsOfficeRelationRepository relationRepo;
|
HsOfficeRelationshipRepository relationshipRepo;
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
EntityManager em;
|
EntityManager em;
|
||||||
@ -100,9 +100,9 @@ class HsOfficePartnerControllerRestTest {
|
|||||||
.content("""
|
.content("""
|
||||||
{
|
{
|
||||||
"partnerNumber": "20002",
|
"partnerNumber": "20002",
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"personUuid": "%s",
|
"personUuid": "%s",
|
||||||
@ -137,9 +137,9 @@ class HsOfficePartnerControllerRestTest {
|
|||||||
.content("""
|
.content("""
|
||||||
{
|
{
|
||||||
"partnerNumber": "20002",
|
"partnerNumber": "20002",
|
||||||
"partnerRel": {
|
"partnerRole": {
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
},
|
},
|
||||||
"personUuid": "%s",
|
"personUuid": "%s",
|
||||||
@ -175,11 +175,11 @@ class HsOfficePartnerControllerRestTest {
|
|||||||
when(partnerRepo.findByUuid(givenPartnerUuid)).thenReturn(Optional.of(partnerMock));
|
when(partnerRepo.findByUuid(givenPartnerUuid)).thenReturn(Optional.of(partnerMock));
|
||||||
when(partnerRepo.deleteByUuid(givenPartnerUuid)).thenReturn(0);
|
when(partnerRepo.deleteByUuid(givenPartnerUuid)).thenReturn(0);
|
||||||
|
|
||||||
final UUID givenRelationUuid = UUID.randomUUID();
|
final UUID givenRelationshipUuid = UUID.randomUUID();
|
||||||
when(partnerMock.getPartnerRel()).thenReturn(HsOfficeRelationEntity.builder()
|
when(partnerMock.getPartnerRole()).thenReturn(HsOfficeRelationshipEntity.builder()
|
||||||
.uuid(givenRelationUuid)
|
.uuid(givenRelationshipUuid)
|
||||||
.build());
|
.build());
|
||||||
when(relationRepo.deleteByUuid(givenRelationUuid)).thenReturn(0);
|
when(relationshipRepo.deleteByUuid(givenRelationshipUuid)).thenReturn(0);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
mockMvc.perform(MockMvcRequestBuilders
|
mockMvc.perform(MockMvcRequestBuilders
|
||||||
|
@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.partner;
|
|||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.test.PatchUnitTestBase;
|
import net.hostsharing.test.PatchUnitTestBase;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.TestInstance;
|
import org.junit.jupiter.api.TestInstance;
|
||||||
@ -48,8 +48,8 @@ class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void initMocks() {
|
void initMocks() {
|
||||||
lenient().when(em.getReference(eq(HsOfficeRelationEntity.class), any())).thenAnswer(invocation ->
|
lenient().when(em.getReference(eq(HsOfficeRelationshipEntity.class), any())).thenAnswer(invocation ->
|
||||||
HsOfficeRelationEntity.builder().uuid(invocation.getArgument(1)).build());
|
HsOfficeRelationshipEntity.builder().uuid(invocation.getArgument(1)).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -57,8 +57,8 @@ class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
final var entity = HsOfficePartnerEntity.builder()
|
final var entity = HsOfficePartnerEntity.builder()
|
||||||
.uuid(INITIAL_PARTNER_UUID)
|
.uuid(INITIAL_PARTNER_UUID)
|
||||||
.partnerNumber(12345)
|
.partnerNumber(12345)
|
||||||
.partnerRel(HsOfficeRelationEntity.builder()
|
.partnerRole(HsOfficeRelationshipEntity.builder()
|
||||||
.holder(givenInitialPerson)
|
.relHolder(givenInitialPerson)
|
||||||
.contact(givenInitialContact)
|
.contact(givenInitialContact)
|
||||||
.build())
|
.build())
|
||||||
.details(givenInitialDetails)
|
.details(givenInitialDetails)
|
||||||
@ -80,19 +80,19 @@ class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
protected Stream<Property> propertyTestDescriptors() {
|
protected Stream<Property> propertyTestDescriptors() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
new JsonNullableProperty<>(
|
new JsonNullableProperty<>(
|
||||||
"partnerRel",
|
"partnerRole",
|
||||||
HsOfficePartnerPatchResource::setPartnerRelUuid,
|
HsOfficePartnerPatchResource::setPartnerRoleUuid,
|
||||||
PATCHED_PARTNER_ROLE_UUID,
|
PATCHED_PARTNER_ROLE_UUID,
|
||||||
HsOfficePartnerEntity::setPartnerRel,
|
HsOfficePartnerEntity::setPartnerRole,
|
||||||
newPartnerRel(PATCHED_PARTNER_ROLE_UUID))
|
newPartnerRole(PATCHED_PARTNER_ROLE_UUID))
|
||||||
.notNullable()
|
.notNullable()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HsOfficeRelationEntity newPartnerRel(final UUID uuid) {
|
private static HsOfficeRelationshipEntity newPartnerRole(final UUID uuid) {
|
||||||
final var newPartnerRel = HsOfficeRelationEntity.builder()
|
final var newPartnerRole = HsOfficeRelationshipEntity.builder()
|
||||||
.uuid(uuid)
|
.uuid(uuid)
|
||||||
.build();
|
.build();
|
||||||
return newPartnerRel;
|
return newPartnerRole;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package net.hostsharing.hsadminng.hs.office.partner;
|
|||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -13,13 +13,13 @@ class HsOfficePartnerEntityUnitTest {
|
|||||||
|
|
||||||
private final HsOfficePartnerEntity givenPartner = HsOfficePartnerEntity.builder()
|
private final HsOfficePartnerEntity givenPartner = HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(12345)
|
.partnerNumber(12345)
|
||||||
.partnerRel(HsOfficeRelationEntity.builder()
|
.partnerRole(HsOfficeRelationshipEntity.builder()
|
||||||
.anchor(HsOfficePersonEntity.builder()
|
.relAnchor(HsOfficePersonEntity.builder()
|
||||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||||
.tradeName("Hostsharing eG")
|
.tradeName("Hostsharing eG")
|
||||||
.build())
|
.build())
|
||||||
.type(HsOfficeRelationType.PARTNER)
|
.relType(HsOfficeRelationshipType.PARTNER)
|
||||||
.holder(HsOfficePersonEntity.builder()
|
.relHolder(HsOfficePersonEntity.builder()
|
||||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||||
.tradeName("some trade name")
|
.tradeName("some trade name")
|
||||||
.build())
|
.build())
|
||||||
|
@ -3,9 +3,9 @@ package net.hostsharing.hsadminng.hs.office.partner;
|
|||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRepository;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectRepository;
|
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectRepository;
|
||||||
@ -43,7 +43,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
HsOfficePartnerRepository partnerRepo;
|
HsOfficePartnerRepository partnerRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeRelationRepository relationRepo;
|
HsOfficeRelationshipRepository relationshipRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficePersonRepository personRepo;
|
HsOfficePersonRepository personRepo;
|
||||||
@ -77,13 +77,13 @@ 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 partnerRole = givenSomeTemporaryHostsharingPartnerRole("First GmbH", "first contact");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newPartner = HsOfficePartnerEntity.builder()
|
final var newPartner = HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(20031)
|
.partnerNumber(20031)
|
||||||
.partnerRel(partnerRel)
|
.partnerRole(partnerRole)
|
||||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||||
.build();
|
.build();
|
||||||
return partnerRepo.save(newPartner);
|
return partnerRepo.save(newPartner);
|
||||||
@ -113,17 +113,17 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0);
|
||||||
final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
||||||
|
|
||||||
final var newRelation = HsOfficeRelationEntity.builder()
|
final var newRelationship = HsOfficeRelationshipEntity.builder()
|
||||||
.holder(givenPartnerPerson)
|
.relHolder(givenPartnerPerson)
|
||||||
.type(HsOfficeRelationType.PARTNER)
|
.relType(HsOfficeRelationshipType.PARTNER)
|
||||||
.anchor(givenMandantPerson)
|
.relAnchor(givenMandantPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
relationRepo.save(newRelation);
|
relationshipRepo.save(newRelationship);
|
||||||
|
|
||||||
final var newPartner = HsOfficePartnerEntity.builder()
|
final var newPartner = HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(20032)
|
.partnerNumber(20032)
|
||||||
.partnerRel(newRelation)
|
.partnerRole(newRelationship)
|
||||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||||
.build();
|
.build();
|
||||||
return partnerRepo.save(newPartner);
|
return partnerRepo.save(newPartner);
|
||||||
@ -132,10 +132,10 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// then
|
// then
|
||||||
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
||||||
initialRoleNames,
|
initialRoleNames,
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.owner",
|
"hs_office_relationship#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.owner",
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.admin",
|
"hs_office_relationship#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.admin",
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.agent",
|
"hs_office_relationship#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.agent",
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant"));
|
"hs_office_relationship#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant"));
|
||||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
||||||
.map(s -> s.replace("ErbenBesslerMelBessler", "EBess"))
|
.map(s -> s.replace("ErbenBesslerMelBessler", "EBess"))
|
||||||
.map(s -> s.replace("fourthcontact", "4th"))
|
.map(s -> s.replace("fourthcontact", "4th"))
|
||||||
@ -143,42 +143,42 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
.containsExactlyInAnyOrder(distinct(fromFormatted(
|
.containsExactlyInAnyOrder(distinct(fromFormatted(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
// FIXME: this entry is wrong in existance and format
|
// FIXME: this entry is wrong in existance and format
|
||||||
"{ grant perm INSERT on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
"{ grant perm INSERT on relationship#HostsharingeG-with-PARTNER-EBess to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||||
|
|
||||||
// permissions on partner
|
// permissions on partner
|
||||||
"{ grant perm DELETE on partner#P-20032 to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
"{ grant perm DELETE on partner#P-20032 to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||||
"{ grant perm UPDATE on partner#P-20032 to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
"{ grant perm UPDATE on partner#P-20032 to role relationship#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
||||||
"{ grant perm SELECT on partner#P-20032 to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }",
|
"{ grant perm SELECT on partner#P-20032 to role relationship#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }",
|
||||||
|
|
||||||
// permissions on partner-details
|
// permissions on partner-details
|
||||||
"{ grant perm DELETE on partner_details#P-20032-details to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
"{ grant perm DELETE on partner_details#P-20032-details to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||||
"{ grant perm UPDATE on partner_details#P-20032-details to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
"{ grant perm UPDATE on partner_details#P-20032-details to role relationship#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
||||||
"{ grant perm SELECT on partner_details#P-20032-details to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
"{ grant perm SELECT on partner_details#P-20032-details to role relationship#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
||||||
|
|
||||||
// permissions on partner-relation
|
// permissions on partner-relationship
|
||||||
"{ grant perm DELETE on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.owner by system and assume }",
|
"{ grant perm DELETE on relationship#HostsharingeG-with-PARTNER-EBess to role relationship#HostsharingeG-with-PARTNER-EBess.owner by system and assume }",
|
||||||
"{ grant perm UPDATE on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
"{ grant perm UPDATE on relationship#HostsharingeG-with-PARTNER-EBess to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||||
"{ grant perm SELECT on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }",
|
"{ grant perm SELECT on relationship#HostsharingeG-with-PARTNER-EBess to role relationship#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }",
|
||||||
|
|
||||||
// relation owner
|
// relationship owner
|
||||||
"{ grant role relation#HostsharingeG-with-PARTNER-EBess.owner to role global#global.admin by system and assume }",
|
"{ grant role relationship#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 relationship#HostsharingeG-with-PARTNER-EBess.owner to user superuser-alex@hostsharing.net by relationship#HostsharingeG-with-PARTNER-EBess.owner and assume }",
|
||||||
|
|
||||||
// relation admin
|
// relationship admin
|
||||||
"{ grant role relation#HostsharingeG-with-PARTNER-EBess.admin to role relation#HostsharingeG-with-PARTNER-EBess.owner by system and assume }",
|
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.admin to role relationship#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 relationship#HostsharingeG-with-PARTNER-EBess.admin to role person#HostsharingeG.admin by system and assume }",
|
||||||
|
|
||||||
// relation agent
|
// relationship agent
|
||||||
"{ grant role relation#HostsharingeG-with-PARTNER-EBess.agent to role person#EBess.admin by system and assume }",
|
"{ grant role relationship#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 relationship#HostsharingeG-with-PARTNER-EBess.agent to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||||
|
|
||||||
// relation tenant
|
// relationship tenant
|
||||||
"{ grant role contact#4th.referrer to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }",
|
"{ grant role contact#4th.referrer to role relationship#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#EBess.referrer to role relationship#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 person#HostsharingeG.referrer to role relationship#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 relationship#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 relationship#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 relationship#HostsharingeG-with-PARTNER-EBess.tenant to role relationship#HostsharingeG-with-PARTNER-EBess.agent by system and assume }",
|
||||||
null)));
|
null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +273,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.setPartnerRole(givenSomeTemporaryHostsharingPartnerRole("Third OHG", "sixth contact"));
|
||||||
return partnerRepo.save(givenPartner);
|
return partnerRepo.save(givenPartner);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -327,7 +327,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",
|
||||||
"hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant");
|
"hs_office_relationship#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant");
|
||||||
givenPartner.getDetails().setBirthName("new birthname");
|
givenPartner.getDetails().setBirthName("new birthname");
|
||||||
return partnerRepo.save(givenPartner);
|
return partnerRepo.save(givenPartner);
|
||||||
});
|
});
|
||||||
@ -335,7 +335,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
||||||
// FIXME: the assumed role should appear, but it does not:
|
// FIXME: the assumed role should appear, but it does not:
|
||||||
//"[403] insert into hs_office_partner_details not allowed for current subjects {hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant}");
|
//"[403] insert into hs_office_partner_details not allowed for current subjects {hs_office_relationship#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant}");
|
||||||
"[403] insert into hs_office_partner_details not allowed for current subjects");
|
"[403] insert into hs_office_partner_details not allowed for current subjects");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,11 +457,11 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final Integer partnerNumber, final String person, final String contact) {
|
final Integer partnerNumber, final String person, final String contact) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var partnerRel = givenSomeTemporaryHostsharingPartnerRel(person, contact);
|
final var partnerRole = givenSomeTemporaryHostsharingPartnerRole(person, contact);
|
||||||
|
|
||||||
final var newPartner = HsOfficePartnerEntity.builder()
|
final var newPartner = HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(partnerNumber)
|
.partnerNumber(partnerNumber)
|
||||||
.partnerRel(partnerRel)
|
.partnerRole(partnerRole)
|
||||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -469,19 +469,19 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
}).assertSuccessful().returnedValue();
|
}).assertSuccessful().returnedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity givenSomeTemporaryHostsharingPartnerRel(final String person, final String contact) {
|
private HsOfficeRelationshipEntity givenSomeTemporaryHostsharingPartnerRole(final String person, final String contact) {
|
||||||
final var givenMandantorPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
final var givenMandantorPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
||||||
final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike(person).get(0);
|
final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike(person).get(0);
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
||||||
|
|
||||||
final var partnerRel = HsOfficeRelationEntity.builder()
|
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
||||||
.holder(givenPartnerPerson)
|
.relHolder(givenPartnerPerson)
|
||||||
.type(HsOfficeRelationType.PARTNER)
|
.relType(HsOfficeRelationshipType.PARTNER)
|
||||||
.anchor(givenMandantorPerson)
|
.relAnchor(givenMandantorPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
relationRepo.save(partnerRel);
|
relationshipRepo.save(partnerRole);
|
||||||
return partnerRel;
|
return partnerRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exactlyThesePartnersAreReturned(final List<HsOfficePartnerEntity> actualResult, final String... partnerNames) {
|
void exactlyThesePartnersAreReturned(final List<HsOfficePartnerEntity> actualResult, final String... partnerNames) {
|
||||||
|
@ -2,8 +2,8 @@ package net.hostsharing.hsadminng.hs.office.partner;
|
|||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL_PERSON;
|
import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.LEGAL_PERSON;
|
||||||
|
|
||||||
@ -14,14 +14,14 @@ public class TestHsOfficePartner {
|
|||||||
static public HsOfficePartnerEntity hsOfficePartnerWithLegalPerson(final String tradeName) {
|
static public HsOfficePartnerEntity hsOfficePartnerWithLegalPerson(final String tradeName) {
|
||||||
return HsOfficePartnerEntity.builder()
|
return HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(10001)
|
.partnerNumber(10001)
|
||||||
.partnerRel(
|
.partnerRole(
|
||||||
HsOfficeRelationEntity.builder()
|
HsOfficeRelationshipEntity.builder()
|
||||||
.holder(HsOfficePersonEntity.builder()
|
.relHolder(HsOfficePersonEntity.builder()
|
||||||
.personType(LEGAL_PERSON)
|
.personType(LEGAL_PERSON)
|
||||||
.tradeName("Hostsharing eG")
|
.tradeName("Hostsharing eG")
|
||||||
.build())
|
.build())
|
||||||
.type(HsOfficeRelationType.PARTNER)
|
.relType(HsOfficeRelationshipType.PARTNER)
|
||||||
.holder(HsOfficePersonEntity.builder()
|
.relHolder(HsOfficePersonEntity.builder()
|
||||||
.personType(LEGAL_PERSON)
|
.personType(LEGAL_PERSON)
|
||||||
.tradeName(tradeName)
|
.tradeName(tradeName)
|
||||||
.build())
|
.build())
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
class HsOfficeRelationEntityUnitTest {
|
|
||||||
|
|
||||||
private HsOfficePersonEntity anchor = HsOfficePersonEntity.builder()
|
|
||||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
|
||||||
.tradeName("some trade name")
|
|
||||||
.build();
|
|
||||||
private HsOfficePersonEntity holder = HsOfficePersonEntity.builder()
|
|
||||||
.personType(HsOfficePersonType.NATURAL_PERSON)
|
|
||||||
.familyName("Meier")
|
|
||||||
.givenName("Mellie")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void toStringReturnsAllProperties() {
|
|
||||||
final var given = HsOfficeRelationEntity.builder()
|
|
||||||
.type(HsOfficeRelationType.SUBSCRIBER)
|
|
||||||
.mark("members-announce")
|
|
||||||
.anchor(anchor)
|
|
||||||
.holder(holder)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
assertThat(given.toString()).isEqualTo("rel(anchor='LP some trade name', type='SUBSCRIBER', mark='members-announce', holder='NP Meier, Mellie')");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void toShortString() {
|
|
||||||
final var given = HsOfficeRelationEntity.builder()
|
|
||||||
.type(HsOfficeRelationType.REPRESENTATIVE)
|
|
||||||
.anchor(anchor)
|
|
||||||
.holder(holder)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
assertThat(given.toShortString()).isEqualTo("rel(anchor='LP some trade name', type='REPRESENTATIVE', holder='NP Meier, Mellie')");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
@ -7,7 +7,7 @@ import net.hostsharing.test.Accepts;
|
|||||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationTypeResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationshipTypeResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@ -31,7 +31,7 @@ import static org.hamcrest.Matchers.startsWith;
|
|||||||
classes = { HsadminNgApplication.class, JpaAttempt.class }
|
classes = { HsadminNgApplication.class, JpaAttempt.class }
|
||||||
)
|
)
|
||||||
@Transactional
|
@Transactional
|
||||||
class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithCleanup {
|
class HsOfficeRelationshipControllerAcceptanceTest extends ContextBasedTestWithCleanup {
|
||||||
|
|
||||||
public static final UUID GIVEN_NON_EXISTING_HOLDER_PERSON_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
|
public static final UUID GIVEN_NON_EXISTING_HOLDER_PERSON_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
|
||||||
@LocalServerPort
|
@LocalServerPort
|
||||||
@ -44,7 +44,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
Context contextMock;
|
Context contextMock;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeRelationRepository relationRepo;
|
HsOfficeRelationshipRepository relationshipRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficePersonRepository personRepo;
|
HsOfficePersonRepository personRepo;
|
||||||
@ -56,11 +56,11 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
JpaAttempt jpaAttempt;
|
JpaAttempt jpaAttempt;
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Accepts({ "Relation:F(Find)" })
|
@Accepts({ "Relationship:F(Find)" })
|
||||||
class ListRelations {
|
class ListRelationships {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRoles_canViewAllRelationsOfGivenPersonAndType_ifNoCriteriaGiven() throws JSONException {
|
void globalAdmin_withoutAssumedRoles_canViewAllRelationshipsOfGivenPersonAndType_ifNoCriteriaGiven() throws JSONException {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
@ -71,45 +71,45 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/office/relations?personUuid=%s&relationType=%s"
|
.get("http://localhost/api/hs/office/relationships?personUuid=%s&relationshipType=%s"
|
||||||
.formatted(givenPerson.getUuid(), HsOfficeRelationTypeResource.PARTNER))
|
.formatted(givenPerson.getUuid(), HsOfficeRelationshipTypeResource.PARTNER))
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH" },
|
"relHolder": { "personType": "LEGAL_PERSON", "tradeName": "First GmbH" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": { "label": "first contact" }
|
"contact": { "label": "first contact" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "personType": "LEGAL_PERSON", "tradeName": "Fourth eG" },
|
"relHolder": { "personType": "LEGAL_PERSON", "tradeName": "Fourth eG" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"contact": { "label": "fourth contact" }
|
"contact": { "label": "fourth contact" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "personType": "LEGAL_PERSON", "tradeName": "Second e.K.", "givenName": "Peter", "familyName": "Smith" },
|
"relHolder": { "personType": "LEGAL_PERSON", "tradeName": "Second e.K.", "givenName": "Peter", "familyName": "Smith" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": { "label": "second contact" }
|
"contact": { "label": "second contact" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "personType": "NATURAL_PERSON", "givenName": "Peter", "familyName": "Smith" },
|
"relHolder": { "personType": "NATURAL_PERSON", "givenName": "Peter", "familyName": "Smith" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": { "label": "sixth contact" }
|
"contact": { "label": "sixth contact" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
"relAnchor": { "personType": "LEGAL_PERSON", "tradeName": "Hostsharing eG" },
|
||||||
"holder": { "personType": "INCORPORATED_FIRM", "tradeName": "Third OHG" },
|
"relHolder": { "personType": "INCORPORATED_FIRM", "tradeName": "Third OHG" },
|
||||||
"type": "PARTNER",
|
"relType": "PARTNER",
|
||||||
"mark": null,
|
"relMark": null,
|
||||||
"contact": { "label": "third contact" }
|
"contact": { "label": "third contact" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -119,11 +119,11 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Accepts({ "Relation:C(Create)" })
|
@Accepts({ "Relationship:C(Create)" })
|
||||||
class AddRelation {
|
class AddRelationship {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRole_canAddRelation() {
|
void globalAdmin_withoutAssumedRole_canAddRelationship() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
||||||
@ -136,38 +136,38 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"type": "%s",
|
"relType": "%s",
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationTypeResource.DEBITOR,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPerson.getUuid(),
|
givenAnchorPerson.getUuid(),
|
||||||
givenHolderPerson.getUuid(),
|
givenHolderPerson.getUuid(),
|
||||||
givenContact.getUuid()))
|
givenContact.getUuid()))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.post("http://localhost/api/hs/office/relations")
|
.post("http://localhost/api/hs/office/relationships")
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(201)
|
.statusCode(201)
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("uuid", isUuidValid())
|
.body("uuid", isUuidValid())
|
||||||
.body("type", is("DEBITOR"))
|
.body("relType", is("ACCOUNTING"))
|
||||||
.body("anchor.tradeName", is("Third OHG"))
|
.body("relAnchor.tradeName", is("Third OHG"))
|
||||||
.body("holder.givenName", is("Paul"))
|
.body("relHolder.givenName", is("Paul"))
|
||||||
.body("contact.label", is("second contact"))
|
.body("contact.label", is("second contact"))
|
||||||
.header("Location", startsWith("http://localhost"))
|
.header("Location", startsWith("http://localhost"))
|
||||||
.extract().header("Location"); // @formatter:on
|
.extract().header("Location"); // @formatter:on
|
||||||
|
|
||||||
// finally, the new relation can be accessed under the generated UUID
|
// finally, the new relationship can be accessed under the generated UUID
|
||||||
final var newUserUuid = toCleanup(HsOfficeRelationEntity.class, UUID.fromString(
|
final var newUserUuid = toCleanup(HsOfficeRelationshipEntity.class, UUID.fromString(
|
||||||
location.substring(location.lastIndexOf('/') + 1)));
|
location.substring(location.lastIndexOf('/') + 1)));
|
||||||
assertThat(newUserUuid).isNotNull();
|
assertThat(newUserUuid).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_canNotAddRelation_ifAnchorPersonDoesNotExist() {
|
void globalAdmin_canNotAddRelationship_ifAnchorPersonDoesNotExist() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenAnchorPersonUuid = GIVEN_NON_EXISTING_HOLDER_PERSON_UUID;
|
final var givenAnchorPersonUuid = GIVEN_NON_EXISTING_HOLDER_PERSON_UUID;
|
||||||
@ -180,27 +180,27 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"type": "%s",
|
"relType": "%s",
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationTypeResource.DEBITOR,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPersonUuid,
|
givenAnchorPersonUuid,
|
||||||
givenHolderPerson.getUuid(),
|
givenHolderPerson.getUuid(),
|
||||||
givenContact.getUuid()))
|
givenContact.getUuid()))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.post("http://localhost/api/hs/office/relations")
|
.post("http://localhost/api/hs/office/relationships")
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(404)
|
.statusCode(404)
|
||||||
.body("message", is("cannot find anchorUuid " + GIVEN_NON_EXISTING_HOLDER_PERSON_UUID));
|
.body("message", is("cannot find relAnchorUuid " + GIVEN_NON_EXISTING_HOLDER_PERSON_UUID));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_canNotAddRelation_ifHolderPersonDoesNotExist() {
|
void globalAdmin_canNotAddRelationship_ifHolderPersonDoesNotExist() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
||||||
@ -212,27 +212,27 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"type": "%s",
|
"relType": "%s",
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationTypeResource.DEBITOR,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPerson.getUuid(),
|
givenAnchorPerson.getUuid(),
|
||||||
GIVEN_NON_EXISTING_HOLDER_PERSON_UUID,
|
GIVEN_NON_EXISTING_HOLDER_PERSON_UUID,
|
||||||
givenContact.getUuid()))
|
givenContact.getUuid()))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.post("http://localhost/api/hs/office/relations")
|
.post("http://localhost/api/hs/office/relationships")
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(404)
|
.statusCode(404)
|
||||||
.body("message", is("cannot find holderUuid " + GIVEN_NON_EXISTING_HOLDER_PERSON_UUID));
|
.body("message", is("cannot find relHolderUuid " + GIVEN_NON_EXISTING_HOLDER_PERSON_UUID));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_canNotAddRelation_ifContactDoesNotExist() {
|
void globalAdmin_canNotAddRelationship_ifContactDoesNotExist() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
||||||
@ -245,19 +245,19 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"type": "%s",
|
"relType": "%s",
|
||||||
"anchorUuid": "%s",
|
"relAnchorUuid": "%s",
|
||||||
"holderUuid": "%s",
|
"relHolderUuid": "%s",
|
||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationTypeResource.DEBITOR,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPerson.getUuid(),
|
givenAnchorPerson.getUuid(),
|
||||||
givenHolderPerson.getUuid(),
|
givenHolderPerson.getUuid(),
|
||||||
givenContactUuid))
|
givenContactUuid))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.post("http://localhost/api/hs/office/relations")
|
.post("http://localhost/api/hs/office/relationships")
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(404)
|
.statusCode(404)
|
||||||
.body("message", is("cannot find contactUuid 00000000-0000-0000-0000-000000000000"));
|
.body("message", is("cannot find contactUuid 00000000-0000-0000-0000-000000000000"));
|
||||||
@ -266,97 +266,97 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Accepts({ "Relation:R(Read)" })
|
@Accepts({ "Relationship:R(Read)" })
|
||||||
class GetRelation {
|
class GetRelationship {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRole_canGetArbitraryRelation() {
|
void globalAdmin_withoutAssumedRole_canGetArbitraryRelationship() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final UUID givenRelationUuid = findRelation("First", "Firby").getUuid();
|
final UUID givenRelationshipUuid = findRelationship("First", "Firby").getUuid();
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/office/relations/" + givenRelationUuid)
|
.get("http://localhost/api/hs/office/relationships/" + givenRelationshipUuid)
|
||||||
.then().log().body().assertThat()
|
.then().log().body().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"anchor": { "tradeName": "First GmbH" },
|
"relAnchor": { "tradeName": "First GmbH" },
|
||||||
"holder": { "familyName": "Firby" },
|
"relHolder": { "familyName": "Firby" },
|
||||||
"contact": { "label": "first contact" }
|
"contact": { "label": "first contact" }
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Accepts({ "Relation:X(Access Control)" })
|
@Accepts({ "Relationship:X(Access Control)" })
|
||||||
void normalUser_canNotGetUnrelatedRelation() {
|
void normalUser_canNotGetUnrelatedRelationship() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final UUID givenRelationUuid = findRelation("First", "Firby").getUuid();
|
final UUID givenRelationshipUuid = findRelationship("First", "Firby").getUuid();
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "selfregistered-user-drew@hostsharing.org")
|
.header("current-user", "selfregistered-user-drew@hostsharing.org")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/office/relations/" + givenRelationUuid)
|
.get("http://localhost/api/hs/office/relationships/" + givenRelationshipUuid)
|
||||||
.then().log().body().assertThat()
|
.then().log().body().assertThat()
|
||||||
.statusCode(404); // @formatter:on
|
.statusCode(404); // @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Accepts({ "Relation:X(Access Control)" })
|
@Accepts({ "Relationship:X(Access Control)" })
|
||||||
void contactAdminUser_canGetRelatedRelation() {
|
void contactAdminUser_canGetRelatedRelationship() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = findRelation("First", "Firby");
|
final var givenRelationship = findRelationship("First", "Firby");
|
||||||
assertThat(givenRelation.getContact().getLabel()).isEqualTo("first contact");
|
assertThat(givenRelationship.getContact().getLabel()).isEqualTo("first contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "contact-admin@firstcontact.example.com")
|
.header("current-user", "contact-admin@firstcontact.example.com")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/office/relations/" + givenRelation.getUuid())
|
.get("http://localhost/api/hs/office/relationships/" + givenRelationship.getUuid())
|
||||||
.then().log().body().assertThat()
|
.then().log().body().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"anchor": { "tradeName": "First GmbH" },
|
"relAnchor": { "tradeName": "First GmbH" },
|
||||||
"holder": { "familyName": "Firby" },
|
"relHolder": { "familyName": "Firby" },
|
||||||
"contact": { "label": "first contact" }
|
"contact": { "label": "first contact" }
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity findRelation(
|
private HsOfficeRelationshipEntity findRelationship(
|
||||||
final String anchorPersonName,
|
final String anchorPersonName,
|
||||||
final String holderPersoneName) {
|
final String holderPersoneName) {
|
||||||
final var anchorPersonUuid = personRepo.findPersonByOptionalNameLike(anchorPersonName).get(0).getUuid();
|
final var anchorPersonUuid = personRepo.findPersonByOptionalNameLike(anchorPersonName).get(0).getUuid();
|
||||||
final var holderPersonUuid = personRepo.findPersonByOptionalNameLike(holderPersoneName).get(0).getUuid();
|
final var holderPersonUuid = personRepo.findPersonByOptionalNameLike(holderPersoneName).get(0).getUuid();
|
||||||
final var givenRelation = relationRepo
|
final var givenRelationship = relationshipRepo
|
||||||
.findRelationRelatedToPersonUuid(anchorPersonUuid)
|
.findRelationshipRelatedToPersonUuid(anchorPersonUuid)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(r -> r.getHolder().getUuid().equals(holderPersonUuid))
|
.filter(r -> r.getRelHolder().getUuid().equals(holderPersonUuid))
|
||||||
.findFirst().orElseThrow();
|
.findFirst().orElseThrow();
|
||||||
return givenRelation;
|
return givenRelationship;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Accepts({ "Relation:U(Update)" })
|
@Accepts({ "Relationship:U(Update)" })
|
||||||
class PatchRelation {
|
class PatchRelationship {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRole_canPatchContactOfArbitraryRelation() {
|
void globalAdmin_withoutAssumedRole_canPatchContactOfArbitraryRelationship() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler();
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler();
|
||||||
assertThat(givenRelation.getContact().getLabel()).isEqualTo("seventh contact");
|
assertThat(givenRelationship.getContact().getLabel()).isEqualTo("seventh contact");
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
|
||||||
|
|
||||||
final var location = RestAssured // @formatter:off
|
final var location = RestAssured // @formatter:off
|
||||||
@ -370,109 +370,109 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
""".formatted(givenContact.getUuid()))
|
""".formatted(givenContact.getUuid()))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.patch("http://localhost/api/hs/office/relations/" + givenRelation.getUuid())
|
.patch("http://localhost/api/hs/office/relationships/" + givenRelationship.getUuid())
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("uuid", isUuidValid())
|
.body("uuid", isUuidValid())
|
||||||
.body("type", is("REPRESENTATIVE"))
|
.body("relType", is("REPRESENTATIVE"))
|
||||||
.body("anchor.tradeName", is("Erben Bessler"))
|
.body("relAnchor.tradeName", is("Erben Bessler"))
|
||||||
.body("holder.familyName", is("Winkler"))
|
.body("relHolder.familyName", is("Winkler"))
|
||||||
.body("contact.label", is("fourth contact"));
|
.body("contact.label", is("fourth contact"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
// finally, the relation is actually updated
|
// finally, the relationship is actually updated
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
assertThat(relationRepo.findByUuid(givenRelation.getUuid())).isPresent().get()
|
assertThat(relationshipRepo.findByUuid(givenRelationship.getUuid())).isPresent().get()
|
||||||
.matches(rel -> {
|
.matches(rel -> {
|
||||||
assertThat(rel.getAnchor().getTradeName()).contains("Bessler");
|
assertThat(rel.getRelAnchor().getTradeName()).contains("Bessler");
|
||||||
assertThat(rel.getHolder().getFamilyName()).contains("Winkler");
|
assertThat(rel.getRelHolder().getFamilyName()).contains("Winkler");
|
||||||
assertThat(rel.getContact().getLabel()).isEqualTo("fourth contact");
|
assertThat(rel.getContact().getLabel()).isEqualTo("fourth contact");
|
||||||
assertThat(rel.getType()).isEqualTo(HsOfficeRelationType.REPRESENTATIVE);
|
assertThat(rel.getRelType()).isEqualTo(HsOfficeRelationshipType.REPRESENTATIVE);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Accepts({ "Relation:D(Delete)" })
|
@Accepts({ "Relationship:D(Delete)" })
|
||||||
class DeleteRelation {
|
class DeleteRelationship {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRole_canDeleteArbitraryRelation() {
|
void globalAdmin_withoutAssumedRole_canDeleteArbitraryRelationship() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler();
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler();
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.delete("http://localhost/api/hs/office/relations/" + givenRelation.getUuid())
|
.delete("http://localhost/api/hs/office/relationships/" + givenRelationship.getUuid())
|
||||||
.then().log().body().assertThat()
|
.then().log().body().assertThat()
|
||||||
.statusCode(204); // @formatter:on
|
.statusCode(204); // @formatter:on
|
||||||
|
|
||||||
// then the given relation is gone
|
// then the given relationship is gone
|
||||||
assertThat(relationRepo.findByUuid(givenRelation.getUuid())).isEmpty();
|
assertThat(relationshipRepo.findByUuid(givenRelationship.getUuid())).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Accepts({ "Relation:X(Access Control)" })
|
@Accepts({ "Relationship:X(Access Control)" })
|
||||||
void contactAdminUser_canNotDeleteRelatedRelation() {
|
void contactAdminUser_canNotDeleteRelatedRelationship() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler();
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler();
|
||||||
assertThat(givenRelation.getContact().getLabel()).isEqualTo("seventh contact");
|
assertThat(givenRelationship.getContact().getLabel()).isEqualTo("seventh contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "contact-admin@seventhcontact.example.com")
|
.header("current-user", "contact-admin@seventhcontact.example.com")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.delete("http://localhost/api/hs/office/relations/" + givenRelation.getUuid())
|
.delete("http://localhost/api/hs/office/relationships/" + givenRelationship.getUuid())
|
||||||
.then().log().body().assertThat()
|
.then().log().body().assertThat()
|
||||||
.statusCode(403); // @formatter:on
|
.statusCode(403); // @formatter:on
|
||||||
|
|
||||||
// then the given relation is still there
|
// then the given relationship is still there
|
||||||
assertThat(relationRepo.findByUuid(givenRelation.getUuid())).isNotEmpty();
|
assertThat(relationshipRepo.findByUuid(givenRelationship.getUuid())).isNotEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Accepts({ "Relation:X(Access Control)" })
|
@Accepts({ "Relationship:X(Access Control)" })
|
||||||
void normalUser_canNotDeleteUnrelatedRelation() {
|
void normalUser_canNotDeleteUnrelatedRelationship() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler();
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler();
|
||||||
assertThat(givenRelation.getContact().getLabel()).isEqualTo("seventh contact");
|
assertThat(givenRelationship.getContact().getLabel()).isEqualTo("seventh contact");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "selfregistered-user-drew@hostsharing.org")
|
.header("current-user", "selfregistered-user-drew@hostsharing.org")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.delete("http://localhost/api/hs/office/relations/" + givenRelation.getUuid())
|
.delete("http://localhost/api/hs/office/relationships/" + givenRelationship.getUuid())
|
||||||
.then().log().body().assertThat()
|
.then().log().body().assertThat()
|
||||||
.statusCode(404); // @formatter:on
|
.statusCode(404); // @formatter:on
|
||||||
|
|
||||||
// then the given relation is still there
|
// then the given relationship is still there
|
||||||
assertThat(relationRepo.findByUuid(givenRelation.getUuid())).isNotEmpty();
|
assertThat(relationshipRepo.findByUuid(givenRelationship.getUuid())).isNotEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity givenSomeTemporaryRelationBessler() {
|
private HsOfficeRelationshipEntity givenSomeTemporaryRelationshipBessler() {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0);
|
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0);
|
||||||
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Winkler").get(0);
|
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Winkler").get(0);
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("seventh contact").get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("seventh contact").get(0);
|
||||||
final var newRelation = HsOfficeRelationEntity.builder()
|
final var newRelationship = HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.REPRESENTATIVE)
|
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
.anchor(givenAnchorPerson)
|
.relAnchor(givenAnchorPerson)
|
||||||
.holder(givenHolderPerson)
|
.relHolder(givenHolderPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertThat(toCleanup(relationRepo.save(newRelation))).isEqualTo(newRelation);
|
assertThat(toCleanup(relationshipRepo.save(newRelationship))).isEqualTo(newRelationship);
|
||||||
|
|
||||||
return newRelation;
|
return newRelationship;
|
||||||
}).assertSuccessful().returnedValue();
|
}).assertSuccessful().returnedValue();
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationshipPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
import net.hostsharing.test.PatchUnitTestBase;
|
import net.hostsharing.test.PatchUnitTestBase;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -21,12 +21,12 @@ import static org.mockito.Mockito.lenient;
|
|||||||
|
|
||||||
@TestInstance(PER_CLASS)
|
@TestInstance(PER_CLASS)
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class HsOfficeRelationEntityPatcherUnitTest extends PatchUnitTestBase<
|
class HsOfficeRelationshipEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||||
HsOfficeRelationPatchResource,
|
HsOfficeRelationshipPatchResource,
|
||||||
HsOfficeRelationEntity
|
HsOfficeRelationshipEntity
|
||||||
> {
|
> {
|
||||||
|
|
||||||
static final UUID INITIAL_RELATION_UUID = UUID.randomUUID();
|
static final UUID INITIAL_RELATIONSHIP_UUID = UUID.randomUUID();
|
||||||
static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
|
static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
@ -49,24 +49,24 @@ class HsOfficeRelationEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HsOfficeRelationEntity newInitialEntity() {
|
protected HsOfficeRelationshipEntity newInitialEntity() {
|
||||||
final var entity = new HsOfficeRelationEntity();
|
final var entity = new HsOfficeRelationshipEntity();
|
||||||
entity.setUuid(INITIAL_RELATION_UUID);
|
entity.setUuid(INITIAL_RELATIONSHIP_UUID);
|
||||||
entity.setType(HsOfficeRelationType.REPRESENTATIVE);
|
entity.setRelType(HsOfficeRelationshipType.REPRESENTATIVE);
|
||||||
entity.setAnchor(givenInitialAnchorPerson);
|
entity.setRelAnchor(givenInitialAnchorPerson);
|
||||||
entity.setHolder(givenInitialHolderPerson);
|
entity.setRelHolder(givenInitialHolderPerson);
|
||||||
entity.setContact(givenInitialContact);
|
entity.setContact(givenInitialContact);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HsOfficeRelationPatchResource newPatchResource() {
|
protected HsOfficeRelationshipPatchResource newPatchResource() {
|
||||||
return new HsOfficeRelationPatchResource();
|
return new HsOfficeRelationshipPatchResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HsOfficeRelationEntityPatcher createPatcher(final HsOfficeRelationEntity relation) {
|
protected HsOfficeRelationshipEntityPatcher createPatcher(final HsOfficeRelationshipEntity relationship) {
|
||||||
return new HsOfficeRelationEntityPatcher(em, relation);
|
return new HsOfficeRelationshipEntityPatcher(em, relationship);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -74,9 +74,9 @@ class HsOfficeRelationEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
return Stream.of(
|
return Stream.of(
|
||||||
new JsonNullableProperty<>(
|
new JsonNullableProperty<>(
|
||||||
"contact",
|
"contact",
|
||||||
HsOfficeRelationPatchResource::setContactUuid,
|
HsOfficeRelationshipPatchResource::setContactUuid,
|
||||||
PATCHED_CONTACT_UUID,
|
PATCHED_CONTACT_UUID,
|
||||||
HsOfficeRelationEntity::setContact,
|
HsOfficeRelationshipEntity::setContact,
|
||||||
newContact(PATCHED_CONTACT_UUID))
|
newContact(PATCHED_CONTACT_UUID))
|
||||||
.notNullable()
|
.notNullable()
|
||||||
);
|
);
|
@ -0,0 +1,44 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class HsOfficeRelationshipEntityUnitTest {
|
||||||
|
|
||||||
|
private HsOfficePersonEntity anchor = HsOfficePersonEntity.builder()
|
||||||
|
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||||
|
.tradeName("some trade name")
|
||||||
|
.build();
|
||||||
|
private HsOfficePersonEntity holder = HsOfficePersonEntity.builder()
|
||||||
|
.personType(HsOfficePersonType.NATURAL_PERSON)
|
||||||
|
.familyName("Meier")
|
||||||
|
.givenName("Mellie")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toStringReturnsAllProperties() {
|
||||||
|
final var given = HsOfficeRelationshipEntity.builder()
|
||||||
|
.relType(HsOfficeRelationshipType.SUBSCRIBER)
|
||||||
|
.relMark("members-announce")
|
||||||
|
.relAnchor(anchor)
|
||||||
|
.relHolder(holder)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(given.toString()).isEqualTo("rel(relAnchor='LP some trade name', relType='SUBSCRIBER', relMark='members-announce', relHolder='NP Meier, Mellie')");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toShortString() {
|
||||||
|
final var given = HsOfficeRelationshipEntity.builder()
|
||||||
|
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
|
.relAnchor(anchor)
|
||||||
|
.relHolder(holder)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(given.toShortString()).isEqualTo("rel(relAnchor='LP some trade name', relType='REPRESENTATIVE', relHolder='NP Meier, Mellie')");
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
@ -31,10 +31,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
|
|
||||||
@DataJpaTest
|
@DataJpaTest
|
||||||
@Import( { Context.class, JpaAttempt.class })
|
@Import( { Context.class, JpaAttempt.class })
|
||||||
class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
class HsOfficeRelationshipRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeRelationRepository relationRepo;
|
HsOfficeRelationshipRepository relationshipRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficePersonRepository personRepo;
|
HsOfficePersonRepository personRepo;
|
||||||
@ -58,13 +58,13 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
HttpServletRequest request;
|
HttpServletRequest request;
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class CreateRelation {
|
class CreateRelationship {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHostsharingAdmin_withoutAssumedRole_canCreateNewRelation() {
|
public void testHostsharingAdmin_withoutAssumedRole_canCreateNewRelationship() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var count = relationRepo.count();
|
final var count = relationshipRepo.count();
|
||||||
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream()
|
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream()
|
||||||
.filter(p -> p.getPersonType() == UNINCORPORATED_FIRM)
|
.filter(p -> p.getPersonType() == UNINCORPORATED_FIRM)
|
||||||
.findFirst().orElseThrow();
|
.findFirst().orElseThrow();
|
||||||
@ -76,20 +76,20 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newRelation = HsOfficeRelationEntity.builder()
|
final var newRelationship = HsOfficeRelationshipEntity.builder()
|
||||||
.anchor(givenAnchorPerson)
|
.relAnchor(givenAnchorPerson)
|
||||||
.holder(givenHolderPerson)
|
.relHolder(givenHolderPerson)
|
||||||
.type(HsOfficeRelationType.REPRESENTATIVE)
|
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
return toCleanup(relationRepo.save(newRelation));
|
return toCleanup(relationshipRepo.save(newRelationship));
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertSuccessful();
|
result.assertSuccessful();
|
||||||
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeRelationEntity::getUuid).isNotNull();
|
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeRelationshipEntity::getUuid).isNotNull();
|
||||||
assertThatRelationIsPersisted(result.returnedValue());
|
assertThatRelationshipIsPersisted(result.returnedValue());
|
||||||
assertThat(relationRepo.count()).isEqualTo(count + 1);
|
assertThat(relationshipRepo.count()).isEqualTo(count + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -109,62 +109,62 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
.findFirst().orElseThrow();
|
.findFirst().orElseThrow();
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").stream()
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").stream()
|
||||||
.findFirst().orElseThrow();
|
.findFirst().orElseThrow();
|
||||||
final var newRelation = HsOfficeRelationEntity.builder()
|
final var newRelationship = HsOfficeRelationshipEntity.builder()
|
||||||
.anchor(givenAnchorPerson)
|
.relAnchor(givenAnchorPerson)
|
||||||
.holder(givenHolderPerson)
|
.relHolder(givenHolderPerson)
|
||||||
.type(HsOfficeRelationType.REPRESENTATIVE)
|
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
return toCleanup(relationRepo.save(newRelation));
|
return toCleanup(relationshipRepo.save(newRelationship));
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
||||||
initialRoleNames,
|
initialRoleNames,
|
||||||
"hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner",
|
"hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner",
|
||||||
"hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin",
|
"hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin",
|
||||||
"hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent",
|
"hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent",
|
||||||
"hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant"));
|
"hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant"));
|
||||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted(
|
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
"{ grant perm INSERT on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }",
|
"{ grant perm INSERT on hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }",
|
||||||
|
|
||||||
"{ grant perm DELETE on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner by system and assume }",
|
"{ grant perm DELETE on hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner by system and assume }",
|
||||||
"{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner to role global#global.admin by system and assume }",
|
"{ grant role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner to role global#global.admin by system and assume }",
|
||||||
"{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner to user superuser-alex@hostsharing.net by hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner and assume }",
|
"{ grant role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner to user superuser-alex@hostsharing.net by hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner and assume }",
|
||||||
|
|
||||||
"{ grant perm UPDATE on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }",
|
"{ grant perm UPDATE on hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relationship#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_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin to role hs_office_relationship#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_relationship#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.agent to role hs_office_person#BesslerBert.admin by system and assume }",
|
"{ grant role hs_office_relationship#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_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }",
|
"{ grant role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }",
|
||||||
|
|
||||||
"{ grant perm SELECT on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
"{ grant perm SELECT on hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
||||||
"{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent by system and assume }",
|
"{ grant role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent by system and assume }",
|
||||||
"{ grant role hs_office_person#BesslerBert.referrer to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
"{ grant role hs_office_person#BesslerBert.referrer to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
||||||
"{ grant role hs_office_person#ErbenBesslerMelBessler.referrer to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
"{ grant role hs_office_person#ErbenBesslerMelBessler.referrer to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
||||||
"{ grant role hs_office_contact#fourthcontact.referrer to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
"{ grant role hs_office_contact#fourthcontact.referrer to role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }",
|
||||||
|
|
||||||
// REPRESENTATIVE holder person -> (represented) anchor person
|
// 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_relationship#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 }",
|
"{ grant role hs_office_relationship#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant to role hs_office_person#BesslerBert.admin by system and assume }",
|
||||||
|
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertThatRelationIsPersisted(final HsOfficeRelationEntity saved) {
|
private void assertThatRelationshipIsPersisted(final HsOfficeRelationshipEntity saved) {
|
||||||
final var found = relationRepo.findByUuid(saved.getUuid());
|
final var found = relationshipRepo.findByUuid(saved.getUuid());
|
||||||
assertThat(found).isNotEmpty().get().usingRecursiveComparison().isEqualTo(saved);
|
assertThat(found).isNotEmpty().get().usingRecursiveComparison().isEqualTo(saved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class FindAllRelations {
|
class FindAllRelationships {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void globalAdmin_withoutAssumedRole_canViewAllRelationsOfArbitraryPerson() {
|
public void globalAdmin_withoutAssumedRole_canViewAllRelationshipsOfArbitraryPerson() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var person = personRepo.findPersonByOptionalNameLike("Smith").stream()
|
final var person = personRepo.findPersonByOptionalNameLike("Smith").stream()
|
||||||
@ -172,18 +172,18 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
.findFirst().orElseThrow();
|
.findFirst().orElseThrow();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = relationRepo.findRelationRelatedToPersonUuid(person.getUuid());
|
final var result = relationshipRepo.findRelationshipRelatedToPersonUuid(person.getUuid());
|
||||||
|
|
||||||
// then
|
// then
|
||||||
allTheseRelationsAreReturned(
|
allTheseRelationshipsAreReturned(
|
||||||
result,
|
result,
|
||||||
"rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Smith, Peter', contact='sixth contact')",
|
"rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='NP Smith, Peter', contact='sixth contact')",
|
||||||
"rel(anchor='LP Second e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
|
"rel(relAnchor='LP Second e.K.', relType='REPRESENTATIVE', relHolder='NP Smith, Peter', contact='second contact')",
|
||||||
"rel(anchor='IF Third OHG', type='SUBSCRIBER', mark='members-announce', holder='NP Smith, Peter', contact='third contact')");
|
"rel(relAnchor='IF Third OHG', relType='SUBSCRIBER', relMark='members-announce', relHolder='NP Smith, Peter', contact='third contact')");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void normalUser_canViewRelationsOfOwnedPersons() {
|
public void normalUser_canViewRelationshipsOfOwnedPersons() {
|
||||||
// given:
|
// given:
|
||||||
context("person-SmithPeter@example.com");
|
context("person-SmithPeter@example.com");
|
||||||
final var person = personRepo.findPersonByOptionalNameLike("Smith").stream()
|
final var person = personRepo.findPersonByOptionalNameLike("Smith").stream()
|
||||||
@ -191,124 +191,124 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
.findFirst().orElseThrow();
|
.findFirst().orElseThrow();
|
||||||
|
|
||||||
// when:
|
// when:
|
||||||
final var result = relationRepo.findRelationRelatedToPersonUuid(person.getUuid());
|
final var result = relationshipRepo.findRelationshipRelatedToPersonUuid(person.getUuid());
|
||||||
|
|
||||||
// then:
|
// then:
|
||||||
exactlyTheseRelationsAreReturned(
|
exactlyTheseRelationshipsAreReturned(
|
||||||
result,
|
result,
|
||||||
"rel(anchor='LP Second e.K.', type='REPRESENTATIVE', holder='NP Smith, Peter', contact='second contact')",
|
"rel(relAnchor='LP Second e.K.', relType='REPRESENTATIVE', relHolder='NP Smith, Peter', contact='second contact')",
|
||||||
"rel(anchor='IF Third OHG', type='SUBSCRIBER', mark='members-announce', holder='NP Smith, Peter', contact='third contact')",
|
"rel(relAnchor='IF Third OHG', relType='SUBSCRIBER', relMark='members-announce', relHolder='NP Smith, Peter', contact='third contact')",
|
||||||
"rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Smith, Peter', contact='sixth contact')",
|
"rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='NP Smith, Peter', contact='sixth contact')",
|
||||||
"rel(anchor='NP Smith, Peter', type='DEBITOR', holder='NP Smith, Peter', contact='third contact')");
|
"rel(relAnchor='NP Smith, Peter', relType='ACCOUNTING', relHolder='NP Smith, Peter', contact='third contact')");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class UpdateRelation {
|
class UpdateRelationship {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void hostsharingAdmin_withoutAssumedRole_canUpdateContactOfArbitraryRelation() {
|
public void hostsharingAdmin_withoutAssumedRole_canUpdateContactOfArbitraryRelationship() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Bert", "fifth contact");
|
"Bert", "fifth contact");
|
||||||
assertThatRelationIsVisibleForUserWithRole(
|
assertThatRelationshipIsVisibleForUserWithRole(
|
||||||
givenRelation,
|
givenRelationship,
|
||||||
"hs_office_person#ErbenBesslerMelBessler.admin");
|
"hs_office_person#ErbenBesslerMelBessler.admin");
|
||||||
assertThatRelationActuallyInDatabase(givenRelation);
|
assertThatRelationshipActuallyInDatabase(givenRelationship);
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("sixth contact").stream().findFirst().orElseThrow();
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("sixth contact").stream().findFirst().orElseThrow();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
givenRelation.setContact(givenContact);
|
givenRelationship.setContact(givenContact);
|
||||||
return toCleanup(relationRepo.save(givenRelation));
|
return toCleanup(relationshipRepo.save(givenRelationship));
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertSuccessful();
|
result.assertSuccessful();
|
||||||
assertThat(result.returnedValue().getContact().getLabel()).isEqualTo("sixth contact");
|
assertThat(result.returnedValue().getContact().getLabel()).isEqualTo("sixth contact");
|
||||||
assertThatRelationIsVisibleForUserWithRole(
|
assertThatRelationshipIsVisibleForUserWithRole(
|
||||||
result.returnedValue(),
|
result.returnedValue(),
|
||||||
"global#global.admin");
|
"global#global.admin");
|
||||||
assertThatRelationIsVisibleForUserWithRole(
|
assertThatRelationshipIsVisibleForUserWithRole(
|
||||||
result.returnedValue(),
|
result.returnedValue(),
|
||||||
"hs_office_contact#sixthcontact.admin");
|
"hs_office_contact#sixthcontact.admin");
|
||||||
|
|
||||||
assertThatRelationIsNotVisibleForUserWithRole(
|
assertThatRelationshipIsNotVisibleForUserWithRole(
|
||||||
result.returnedValue(),
|
result.returnedValue(),
|
||||||
"hs_office_contact#fifthcontact.admin");
|
"hs_office_contact#fifthcontact.admin");
|
||||||
|
|
||||||
relationRepo.deleteByUuid(givenRelation.getUuid());
|
relationshipRepo.deleteByUuid(givenRelationship.getUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void holderAdmin_canNotUpdateRelatedRelation() {
|
public void relHolderAdmin_canNotUpdateRelatedRelationship() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Anita", "eighth");
|
"Anita", "eighth");
|
||||||
assertThatRelationIsVisibleForUserWithRole(
|
assertThatRelationshipIsVisibleForUserWithRole(
|
||||||
givenRelation,
|
givenRelationship,
|
||||||
"hs_office_person#BesslerAnita.admin");
|
"hs_office_person#BesslerAnita.admin");
|
||||||
assertThatRelationActuallyInDatabase(givenRelation);
|
assertThatRelationshipActuallyInDatabase(givenRelationship);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita.admin");
|
context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita.admin");
|
||||||
givenRelation.setContact(null);
|
givenRelationship.setContact(null);
|
||||||
return relationRepo.save(givenRelation);
|
return relationshipRepo.save(givenRelationship);
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
||||||
"[403] Subject ", " is not allowed to update hs_office_relation uuid");
|
"[403] Subject ", " is not allowed to update hs_office_relationship uuid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contactAdmin_canNotUpdateRelatedRelation() {
|
public void contactAdmin_canNotUpdateRelatedRelationship() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Anita", "ninth");
|
"Anita", "ninth");
|
||||||
assertThatRelationIsVisibleForUserWithRole(
|
assertThatRelationshipIsVisibleForUserWithRole(
|
||||||
givenRelation,
|
givenRelationship,
|
||||||
"hs_office_contact#ninthcontact.admin");
|
"hs_office_contact#ninthcontact.admin");
|
||||||
assertThatRelationActuallyInDatabase(givenRelation);
|
assertThatRelationshipActuallyInDatabase(givenRelationship);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net", "hs_office_contact#ninthcontact.admin");
|
context("superuser-alex@hostsharing.net", "hs_office_contact#ninthcontact.admin");
|
||||||
givenRelation.setContact(null); // TODO
|
givenRelationship.setContact(null); // TODO
|
||||||
return relationRepo.save(givenRelation);
|
return relationshipRepo.save(givenRelationship);
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
||||||
"[403] Subject ", " is not allowed to update hs_office_relation uuid");
|
"[403] Subject ", " is not allowed to update hs_office_relationship uuid");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertThatRelationActuallyInDatabase(final HsOfficeRelationEntity saved) {
|
private void assertThatRelationshipActuallyInDatabase(final HsOfficeRelationshipEntity saved) {
|
||||||
final var found = relationRepo.findByUuid(saved.getUuid());
|
final var found = relationshipRepo.findByUuid(saved.getUuid());
|
||||||
assertThat(found).isNotEmpty().get().isNotSameAs(saved).usingRecursiveComparison().isEqualTo(saved);
|
assertThat(found).isNotEmpty().get().isNotSameAs(saved).usingRecursiveComparison().isEqualTo(saved);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertThatRelationIsVisibleForUserWithRole(
|
private void assertThatRelationshipIsVisibleForUserWithRole(
|
||||||
final HsOfficeRelationEntity entity,
|
final HsOfficeRelationshipEntity entity,
|
||||||
final String assumedRoles) {
|
final String assumedRoles) {
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net", assumedRoles);
|
context("superuser-alex@hostsharing.net", assumedRoles);
|
||||||
assertThatRelationActuallyInDatabase(entity);
|
assertThatRelationshipActuallyInDatabase(entity);
|
||||||
}).assertSuccessful();
|
}).assertSuccessful();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertThatRelationIsNotVisibleForUserWithRole(
|
private void assertThatRelationshipIsNotVisibleForUserWithRole(
|
||||||
final HsOfficeRelationEntity entity,
|
final HsOfficeRelationshipEntity entity,
|
||||||
final String assumedRoles) {
|
final String assumedRoles) {
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net", assumedRoles);
|
context("superuser-alex@hostsharing.net", assumedRoles);
|
||||||
final var found = relationRepo.findByUuid(entity.getUuid());
|
final var found = relationshipRepo.findByUuid(entity.getUuid());
|
||||||
assertThat(found).isEmpty();
|
assertThat(found).isEmpty();
|
||||||
}).assertSuccessful();
|
}).assertSuccessful();
|
||||||
}
|
}
|
||||||
@ -318,63 +318,63 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
class DeleteByUuid {
|
class DeleteByUuid {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void globalAdmin_withoutAssumedRole_canDeleteAnyRelation() {
|
public void globalAdmin_withoutAssumedRole_canDeleteAnyRelationship() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net", null);
|
context("superuser-alex@hostsharing.net", null);
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Anita", "tenth");
|
"Anita", "tenth");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
relationRepo.deleteByUuid(givenRelation.getUuid());
|
relationshipRepo.deleteByUuid(givenRelationship.getUuid());
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertSuccessful();
|
result.assertSuccessful();
|
||||||
assertThat(jpaAttempt.transacted(() -> {
|
assertThat(jpaAttempt.transacted(() -> {
|
||||||
context("superuser-fran@hostsharing.net", null);
|
context("superuser-fran@hostsharing.net", null);
|
||||||
return relationRepo.findByUuid(givenRelation.getUuid());
|
return relationshipRepo.findByUuid(givenRelationship.getUuid());
|
||||||
}).assertSuccessful().returnedValue()).isEmpty();
|
}).assertSuccessful().returnedValue()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contactUser_canViewButNotDeleteTheirRelatedRelation() {
|
public void contactUser_canViewButNotDeleteTheirRelatedRelationship() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net", null);
|
context("superuser-alex@hostsharing.net", null);
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Anita", "eleventh");
|
"Anita", "eleventh");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("contact-admin@eleventhcontact.example.com");
|
context("contact-admin@eleventhcontact.example.com");
|
||||||
assertThat(relationRepo.findByUuid(givenRelation.getUuid())).isPresent();
|
assertThat(relationshipRepo.findByUuid(givenRelationship.getUuid())).isPresent();
|
||||||
relationRepo.deleteByUuid(givenRelation.getUuid());
|
relationshipRepo.deleteByUuid(givenRelationship.getUuid());
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(
|
result.assertExceptionWithRootCauseMessage(
|
||||||
JpaSystemException.class,
|
JpaSystemException.class,
|
||||||
"[403] Subject ", " not allowed to delete hs_office_relation");
|
"[403] Subject ", " not allowed to delete hs_office_relationship");
|
||||||
assertThat(jpaAttempt.transacted(() -> {
|
assertThat(jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
return relationRepo.findByUuid(givenRelation.getUuid());
|
return relationshipRepo.findByUuid(givenRelationship.getUuid());
|
||||||
}).assertSuccessful().returnedValue()).isPresent(); // still there
|
}).assertSuccessful().returnedValue()).isPresent(); // still there
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deletingARelationAlsoDeletesRelatedRolesAndGrants() {
|
public void deletingARelationshipAlsoDeletesRelatedRolesAndGrants() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll()));
|
final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll()));
|
||||||
final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
|
final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
|
||||||
final var givenRelation = givenSomeTemporaryRelationBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Anita", "twelfth");
|
"Anita", "twelfth");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
return relationRepo.deleteByUuid(givenRelation.getUuid());
|
return relationshipRepo.deleteByUuid(givenRelationship.getUuid());
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@ -391,7 +391,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_relation';
|
where targettable = 'hs_office_relationship';
|
||||||
""");
|
""");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -399,40 +399,40 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating relation test-data HostsharingeG-FirstGmbH, hs_office_relation, INSERT]",
|
"[creating relationship test-data HostsharingeG-FirstGmbH, hs_office_relationship, INSERT]",
|
||||||
"[creating relation test-data FirstGmbH-Firby, hs_office_relation, INSERT]");
|
"[creating relationship test-data FirstGmbH-Firby, hs_office_relationship, INSERT]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationEntity givenSomeTemporaryRelationBessler(final String holderPerson, final String contact) {
|
private HsOfficeRelationshipEntity givenSomeTemporaryRelationshipBessler(final String holderPerson, final String contact) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0);
|
final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0);
|
||||||
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike(holderPerson).get(0);
|
final var givenHolderPerson = personRepo.findPersonByOptionalNameLike(holderPerson).get(0);
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
||||||
final var newRelation = HsOfficeRelationEntity.builder()
|
final var newRelationship = HsOfficeRelationshipEntity.builder()
|
||||||
.type(HsOfficeRelationType.REPRESENTATIVE)
|
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
.anchor(givenAnchorPerson)
|
.relAnchor(givenAnchorPerson)
|
||||||
.holder(givenHolderPerson)
|
.relHolder(givenHolderPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return toCleanup(relationRepo.save(newRelation));
|
return toCleanup(relationshipRepo.save(newRelationship));
|
||||||
}).assertSuccessful().returnedValue();
|
}).assertSuccessful().returnedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void exactlyTheseRelationsAreReturned(
|
void exactlyTheseRelationshipsAreReturned(
|
||||||
final List<HsOfficeRelationEntity> actualResult,
|
final List<HsOfficeRelationshipEntity> actualResult,
|
||||||
final String... relationNames) {
|
final String... relationshipNames) {
|
||||||
assertThat(actualResult)
|
assertThat(actualResult)
|
||||||
.extracting(HsOfficeRelationEntity::toString)
|
.extracting(HsOfficeRelationshipEntity::toString)
|
||||||
.containsExactlyInAnyOrder(relationNames);
|
.containsExactlyInAnyOrder(relationshipNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void allTheseRelationsAreReturned(
|
void allTheseRelationshipsAreReturned(
|
||||||
final List<HsOfficeRelationEntity> actualResult,
|
final List<HsOfficeRelationshipEntity> actualResult,
|
||||||
final String... relationNames) {
|
final String... relationshipNames) {
|
||||||
assertThat(actualResult)
|
assertThat(actualResult)
|
||||||
.extracting(HsOfficeRelationEntity::toString)
|
.extracting(HsOfficeRelationshipEntity::toString)
|
||||||
.contains(relationNames);
|
.contains(relationshipNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -357,7 +357,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
|
|||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get()
|
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get()
|
||||||
.matches(mandate -> {
|
.matches(mandate -> {
|
||||||
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(D-1000111: rel(anchor='LP First GmbH', type='DEBITOR', holder='LP First GmbH'), fir)");
|
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(D-1000111: rel(relAnchor='LP First GmbH', relType='ACCOUNTING', relHolder='LP First GmbH'), fir)");
|
||||||
assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH");
|
assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH");
|
||||||
assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z - patched");
|
assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z - patched");
|
||||||
assertThat(mandate.getValidFrom()).isEqualTo("2020-06-05");
|
assertThat(mandate.getValidFrom()).isEqualTo("2020-06-05");
|
||||||
@ -398,7 +398,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
|
|||||||
// finally, the sepaMandate is actually updated
|
// finally, the sepaMandate is actually updated
|
||||||
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get()
|
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get()
|
||||||
.matches(mandate -> {
|
.matches(mandate -> {
|
||||||
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(D-1000111: rel(anchor='LP First GmbH', type='DEBITOR', holder='LP First GmbH'), fir)");
|
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(D-1000111: rel(relAnchor='LP First GmbH', relType='ACCOUNTING', relHolder='LP First GmbH'), fir)");
|
||||||
assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH");
|
assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH");
|
||||||
assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z");
|
assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z");
|
||||||
assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2023-01-01)");
|
assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2023-01-01)");
|
||||||
@ -503,8 +503,8 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
|
|||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).get(0);
|
final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).get(0);
|
||||||
final var bankAccountHolder = ofNullable(givenDebitor.getPartner().getPartnerRel().getHolder().getTradeName())
|
final var bankAccountHolder = ofNullable(givenDebitor.getPartner().getPartnerRole().getRelHolder().getTradeName())
|
||||||
.orElse(givenDebitor.getPartner().getPartnerRel().getHolder().getFamilyName());
|
.orElse(givenDebitor.getPartner().getPartnerRole().getRelHolder().getFamilyName());
|
||||||
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0);
|
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0);
|
||||||
final var newSepaMandate = HsOfficeSepaMandateEntity.builder()
|
final var newSepaMandate = HsOfficeSepaMandateEntity.builder()
|
||||||
.uuid(UUID.randomUUID())
|
.uuid(UUID.randomUUID())
|
||||||
|
@ -138,14 +138,14 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
// agent
|
// agent
|
||||||
"{ grant role bankaccount#DE02600501010002034304.referrer to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }",
|
"{ grant role bankaccount#DE02600501010002034304.referrer to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }",
|
||||||
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).admin by system and assume }",
|
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).admin by system and assume }",
|
||||||
"{ grant role relation#FirstGmbH-with-DEBITOR-FirstGmbH.agent to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FirstGmbH.agent to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }",
|
||||||
|
|
||||||
// referrer
|
// referrer
|
||||||
"{ grant perm SELECT on sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01) to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer by system and assume }",
|
"{ grant perm SELECT on sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01) to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer by system and assume }",
|
||||||
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }",
|
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }",
|
||||||
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role bankaccount#DE02600501010002034304.admin by system and assume }",
|
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role bankaccount#DE02600501010002034304.admin by system and assume }",
|
||||||
"{ grant role relation#FirstGmbH-with-DEBITOR-FirstGmbH.tenant to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer by system and assume }",
|
"{ grant role relationship#FirstGmbH-with-ACCOUNTING-FirstGmbH.tenant to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer by system and assume }",
|
||||||
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role relation#FirstGmbH-with-DEBITOR-FirstGmbH.agent by system and assume }",
|
"{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role relationship#FirstGmbH-with-ACCOUNTING-FirstGmbH.agent by system and assume }",
|
||||||
|
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
|
41
tools/generate
Executable file
41
tools/generate
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
sourceLower=partner
|
||||||
|
targetLower=relationship
|
||||||
|
|
||||||
|
sourceStudly=Partner
|
||||||
|
targetStudly=Relationship
|
||||||
|
|
||||||
|
## for source in `find src -iname ""*$sourceLower*"" -type f \( -iname \*.yaml -o -iname \*.sql -o -iname \*.java \)`; do
|
||||||
|
for source in `find src -iname ""*$sourceLower*"" -type f \( -iname \*.yaml \)`; do
|
||||||
|
target=`echo $source | sed -e "s/$sourceStudly/$targetStudly/g" -e "s/$sourceLower/$targetLower/g"`
|
||||||
|
echo "Generating $target from $source:"
|
||||||
|
|
||||||
|
mkdir -p `dirname $target`
|
||||||
|
|
||||||
|
sed -e 's/hs-office-partner/hs-office-relationship/g' \
|
||||||
|
-e 's/hs_office_partner/hs_office_relationship/g' \
|
||||||
|
-e 's/HsOfficePartner/HsOfficeRelationship/g' \
|
||||||
|
-e 's/hsOfficePartner/hsOfficeRelationship/g' \
|
||||||
|
-e 's/partner/relationship/g' \
|
||||||
|
\
|
||||||
|
-e 's/addPartner/addRelationship/g' \
|
||||||
|
-e 's/listPartners/listRelationships/g' \
|
||||||
|
-e 's/getPartnerByUuid/getRelationshipByUuid/g' \
|
||||||
|
-e 's/patchPartner/patchRelationship/g' \
|
||||||
|
-e 's/person/relHolder/g' \
|
||||||
|
-e 's/registrationOffice/relType/g' \
|
||||||
|
<$source >$target
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
cat >>src/main/resources/db/changelog/db.changelog-master.yaml <<EOF
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2X0-hs-office-$sourceLower.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2X3-hs-office-$sourceLower-rbac.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/2X8-hs-office-$sourceLower-test-data.sql
|
||||||
|
EOF
|
Loading…
Reference in New Issue
Block a user