introduce-partner-business-role #16
14
doc/hs-office-mailinglist-subscriptions.md
Normal file
14
doc/hs-office-mailinglist-subscriptions.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Sketch UI for mailinglist subscriptions
|
||||
|
||||
```PlantUML
|
||||
@startsalt
|
||||
{{^==Mailinglist-Subscriptions
|
||||
Members-Announce: | [<color:#9a9a9a>X</color>] | ^frank.meiler@example.org^ | [Create New]
|
||||
Members-Discussion: | [X] | ^frank.meiler@example.org^ | [Create New]
|
||||
Customers-Announce: | [<color:#9a9a9a>X</color>] | ^frank.meiler@example.org^ | [Create New]
|
||||
Operations-Announce: | [<color:#9a9a9a>X</color>] | ^Default Contact Data^ | [Create New]
|
||||
Operations-Discussion: | [ ] | ^ ^ | [Create New]
|
||||
|
||||
}}
|
||||
@endsalt
|
||||
```
|
@ -33,7 +33,7 @@ create table hs_office_partner
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
partnerNumber numeric(5),
|
||||
partnerRoleUuid uuid not null references hs_office_relationship(uuid),
|
||||
partnerRoleUuid uuid not null references hs_office_relationship(uuid) on delete cascade,
|
||||
personUuid uuid not null references hs_office_person(uuid), -- TODO: remove, replaced by partnerRoleUuid
|
||||
contactUuid uuid not null references hs_office_contact(uuid), -- TODO: remove, replaced by partnerRoleUuid
|
||||
detailsUuid uuid not null references hs_office_partner_details(uuid) on delete cascade
|
||||
|
@ -27,12 +27,17 @@ create or replace function hsOfficePartnerRbacRolesTrigger()
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
oldPartnerRole hs_office_relationship;
|
||||
newPartnerRole hs_office_relationship;
|
||||
|
||||
oldPerson hs_office_person;
|
||||
newPerson hs_office_person;
|
||||
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
begin
|
||||
|
||||
select * from hs_office_relationship as r where r.uuid = NEW.partnerroleuuid into newPartnerRole;
|
||||
select * from hs_office_person as p where p.uuid = NEW.personUuid into newPerson;
|
||||
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
|
||||
|
||||
@ -52,6 +57,7 @@ begin
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerOwner(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newPartnerRole),
|
||||
hsOfficePersonTenant(newPerson),
|
||||
hsOfficeContactTenant(newContact)]
|
||||
);
|
||||
@ -60,6 +66,7 @@ begin
|
||||
hsOfficePartnerAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerAdmin(NEW),
|
||||
hsOfficeRelationshipAdmin(newPartnerRole),
|
||||
hsOfficePersonAdmin(newPerson),
|
||||
hsOfficeContactAdmin(newContact)]
|
||||
);
|
||||
@ -69,6 +76,7 @@ begin
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerAgent(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newPartnerRole),
|
||||
hsOfficePersonGuest(newPerson),
|
||||
hsOfficeContactGuest(newContact)]
|
||||
);
|
||||
@ -109,6 +117,19 @@ begin
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.partnerRoleUuid <> NEW.partnerRoleUuid then
|
||||
select * from hs_office_relationship as r where r.uuid = OLD.partnerRoleUuid into oldPartnerRole;
|
||||
|
||||
call revokeRoleFromRole(hsOfficeRelationshipTenant(oldPerson), hsOfficePartnerAdmin(OLD));
|
||||
call grantRoleToRole(hsOfficeRelationshipTenant(newPerson), hsOfficePartnerAdmin(NEW));
|
||||
|
||||
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficeRelationshipAdmin(oldPerson));
|
||||
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeRelationshipAdmin(newPerson));
|
||||
|
||||
call revokeRoleFromRole(hsOfficeRelationshipGuest(oldPerson), hsOfficePartnerTenant(OLD));
|
||||
call grantRoleToRole(hsOfficeRelationshipGuest(newPerson), hsOfficePartnerTenant(NEW));
|
||||
end if;
|
||||
|
||||
if OLD.personUuid <> NEW.personUuid then
|
||||
select * from hs_office_person as p where p.uuid = OLD.personUuid into oldPerson;
|
||||
|
||||
@ -179,7 +200,7 @@ call generateRbacIdentityView('hs_office_partner', $idName$
|
||||
call generateRbacRestrictedView('hs_office_partner',
|
||||
'(select idName from hs_office_person_iv p where p.uuid = target.personUuid)',
|
||||
$updates$
|
||||
partherRoleUuid = new.partnerRoleUuid,
|
||||
partnerRoleUuid = new.partnerRoleUuid,
|
||||
personUuid = new.personUuid,
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
@ -191,7 +212,7 @@ call generateRbacRestrictedView('hs_office_partner',
|
||||
--changeset hs-office-partner-rbac-NEW-PARTNER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-partner and assigns it to the hostsharing admins role.
|
||||
Creates a global permission for new-partner and assigns it to the Hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
|
@ -763,7 +763,8 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
if (containsRole(rec, "vip-contact")) {
|
||||
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.VIP_CONTACT);
|
||||
}
|
||||
verifyContainsOnly(rec.getString("roles"), "partner", "vip-contact", "ex-partner", "billing", "contractual", "operation");
|
||||
verifyContainsOnly(rec.getString("roles"),
|
||||
"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation");
|
||||
});
|
||||
|
||||
optionallyAddMissingContractualRelationships();
|
||||
|
@ -122,7 +122,7 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -191,8 +191,9 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
void globalAdmin_canNotAddPartner_ifPersonDoesNotExist() {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var mandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
||||
final var givenPersonUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
@ -201,11 +202,22 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
.body("""
|
||||
{
|
||||
"partnerNumber": "12345",
|
||||
"contactUuid": "%s",
|
||||
"partnerRole": {
|
||||
"relAnchorUuid": "%s",
|
||||
"relType": "PARTNER",
|
||||
"relHolder": "%s",
|
||||
"contact": "%s",
|
||||
},
|
||||
"personUuid": "%s",
|
||||
"contactUuid": "%s",
|
||||
"details": {}
|
||||
}
|
||||
""".formatted(givenContact.getUuid(), givenPersonUuid))
|
||||
""".formatted(
|
||||
mandantPerson.getUuid(),
|
||||
givenPersonUuid,
|
||||
givenContact.getUuid(),
|
||||
givenPersonUuid,
|
||||
givenContact.getUuid()))
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/hs/office/partners")
|
||||
|
@ -74,13 +74,23 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// given
|
||||
context("superuser-alex@hostsharing.net");
|
||||
final var count = partnerRepo.count();
|
||||
final var givenPerson = personRepo.findPersonByOptionalNameLike("First GmbH").get(0);
|
||||
final var givenMandantorPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
||||
final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike("First GmbH").get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("first contact").get(0);
|
||||
|
||||
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
||||
.relHolder(givenPartnerPerson)
|
||||
.relType(HsOfficeRelationshipType.PARTNER)
|
||||
.relAnchor(givenMandantorPerson)
|
||||
.contact(givenContact)
|
||||
.build();
|
||||
relationshipRepo.save(partnerRole);
|
||||
|
||||
// when
|
||||
final var result = attempt(em, () -> {
|
||||
final var newPartner = toCleanup(HsOfficePartnerEntity.builder()
|
||||
.person(givenPerson)
|
||||
.partnerRole(partnerRole)
|
||||
.person(givenPartnerPerson)
|
||||
.contact(givenContact)
|
||||
.details(HsOfficePartnerDetailsEntity.builder()
|
||||
.build())
|
||||
@ -148,11 +158,12 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
.containsExactlyInAnyOrder(Array.fromFormatted(
|
||||
initialGrantNames,
|
||||
// relationship - TODO: check and cleanup
|
||||
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.tenant to role partner#22222:EBess-4th.admin by system and assume }",
|
||||
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.tenant to role partner#22222:EBess-4th.tenant by system and assume }",
|
||||
"{ grant role partner#22222:EBess-4th.agent to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.owner to role global#global.admin by system and assume }",
|
||||
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.tenant to role contact#4th.admin by system and assume }",
|
||||
"{ grant role person#HostsharingeG.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 person#EBess.tenant to role person#HostsharingeG.admin by system and assume }",
|
||||
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.owner to role person#HostsharingeG.admin by system and assume }",
|
||||
"{ grant role relationship#HostsharingeG-with-PARTNER-EBess.tenant to role person#HostsharingeG.admin by system and assume }",
|
||||
"{ grant perm edit on relationship#HostsharingeG-with-PARTNER-EBess to role relationship#HostsharingeG-with-PARTNER-EBess.admin by system and assume }",
|
||||
@ -311,6 +322,10 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// given
|
||||
context("superuser-alex@hostsharing.net");
|
||||
final var givenPartner = givenSomeTemporaryPartnerBessler(22222, "Erben Bessler", "ninth");
|
||||
final var newPartnerRole = em.createNativeQuery(
|
||||
"select uuid from hs_office_relationship where uuid=:partnerRoleUuid")
|
||||
.setParameter("partnerRoleUuid", givenPartner.getPartnerRole().getUuid())
|
||||
.getSingleResult();
|
||||
assertThatPartnerIsVisibleForUserWithRole(
|
||||
givenPartner,
|
||||
"hs_office_partner#22222:ErbenBesslerMelBessler-ninthcontact.agent");
|
||||
@ -412,7 +427,8 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// when
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
context("superuser-alex@hostsharing.net");
|
||||
return partnerRepo.deleteByUuid(givenPartner.getUuid());
|
||||
return relationshipRepo.deleteByUuid(givenPartner.getPartnerRole().getUuid());
|
||||
// return partnerRepo.deleteByUuid(givenPartner.getUuid());
|
||||
});
|
||||
|
||||
// then
|
||||
@ -455,11 +471,23 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
|
||||
final Integer partnerNumber, final String person, final String contact) {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
context("superuser-alex@hostsharing.net");
|
||||
final var givenPerson = personRepo.findPersonByOptionalNameLike(person).get(0);
|
||||
final var givenMandantorPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
|
||||
final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike(person).get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
||||
|
||||
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
||||
.relHolder(givenPartnerPerson)
|
||||
.relType(HsOfficeRelationshipType.PARTNER)
|
||||
.relAnchor(givenMandantorPerson)
|
||||
.contact(givenContact)
|
||||
.build();
|
||||
relationshipRepo.save(partnerRole);
|
||||
em.flush(); // TODO: why is that necessary?
|
||||
|
||||
final var newPartner = HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(partnerNumber)
|
||||
.person(givenPerson)
|
||||
.partnerRole(partnerRole)
|
||||
.person(givenPartnerPerson)
|
||||
.contact(givenContact)
|
||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||
.build();
|
||||
|
Loading…
Reference in New Issue
Block a user