This commit is contained in:
Michael Hoennig 2024-03-13 17:02:49 +01:00
parent fe23a496e6
commit 2774707801
15 changed files with 374 additions and 342 deletions

View File

@ -13,7 +13,10 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
@Query(""" @Query("""
SELECT debitor FROM HsOfficeDebitorEntity debitor SELECT debitor FROM HsOfficeDebitorEntity debitor
WHERE cast(debitor.partner.partnerNumber as integer) = :partnerNumber JOIN HsOfficePartnerEntity partner
ON partner.partnerRole.relHolder = debitor.debitorRel.relAnchor
AND partner.partnerRole.relType = 'PARTNER' AND debitor.debitorRel.relType = 'ACCOUNTING'
WHERE cast(partner.partnerNumber as integer) = :partnerNumber
AND cast(debitor.debitorNumberSuffix as integer) = :debitorNumberSuffix AND cast(debitor.debitorNumberSuffix as integer) = :debitorNumberSuffix
""") """)
List<HsOfficeDebitorEntity> findDebitorByDebitorNumber(int partnerNumber, byte debitorNumberSuffix); List<HsOfficeDebitorEntity> findDebitorByDebitorNumber(int partnerNumber, byte debitorNumberSuffix);
@ -24,11 +27,15 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
@Query(""" @Query("""
SELECT debitor FROM HsOfficeDebitorEntity debitor SELECT debitor FROM HsOfficeDebitorEntity debitor
JOIN HsOfficePartnerEntity partner ON partner.uuid = debitor.partner.uuid JOIN HsOfficePartnerEntity partner
JOIN HsOfficeRelationshipEntity rel ON rel.uuid = partner.partnerRole.uuid ON partner.partnerRole.relHolder = debitor.debitorRel.relAnchor
JOIN HsOfficePersonEntity person ON person.uuid = rel.relHolder.uuid AND partner.partnerRole.relType = 'PARTNER' AND debitor.debitorRel.relType = 'ACCOUNTING'
JOIN HsOfficePersonEntity person
ON person.uuid = partner.partnerRole.relHolder.uuid
OR person.uuid = debitor.debitorRel.relHolder.uuid
JOIN HsOfficeContactEntity contact JOIN HsOfficeContactEntity contact
ON contact.uuid = debitor.billingContact.uuid OR contact.uuid = rel.contact.uuid ON contact.uuid = debitor.debitorRel.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), '%')

View File

@ -71,11 +71,12 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
public static RbacView rbac() { public static RbacView rbac() {
return rbacViewFor("partnerDetails", HsOfficePartnerDetailsEntity.class) return rbacViewFor("partnerDetails", HsOfficePartnerDetailsEntity.class)
.withIdentityView(SQL.query(""" .withIdentityView(SQL.query("""
SELECT partner_iv.idName || '-details' SELECT partnerDetails.uuid as uuid, partner_iv.idName || '-details' as idName
FROM hs_office_partner_details AS partnerDetails FROM hs_office_partner_details AS partnerDetails
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
""")) """))
.withRestrictedViewOrderBy(SQL.expression("uuid"))
.withUpdatableColumns( .withUpdatableColumns(
"registrationOffice", "registrationOffice",
"registrationNumber", "registrationNumber",
@ -83,17 +84,7 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
"birthName", "birthName",
"birthday", "birthday",
"dateOfDeath") "dateOfDeath")
.toRole("global", ADMIN).grantPermission("partner-details", INSERT) .toRole("global", ADMIN).grantPermission("partnerDetails", INSERT)
.importRootEntityAliasProxy("partnerRel", HsOfficeRelationshipEntity.class,
fetchedBySql("""
SELECT partnerRel.*
FROM hs_office_relationship AS partnerRel
JOIN hs_office_partner AS partner
ON partner.detailsUuid = ${ref}.uuid
WHERE partnerRel.uuid = partner.partnerRoleUuid
"""),
dependsOnColumn("partnerRoleUuid"))
// The grants are defined in HsOfficePartnerEntity.rbac() // The grants are defined in HsOfficePartnerEntity.rbac()
// because they have to be changed when its partnerRel changes, // because they have to be changed when its partnerRel changes,
@ -102,6 +93,6 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
rbac().generateWithBaseFileName("234-hs-office-partner-details-rbac-generated"); rbac().generateWithBaseFileName("234-hs-office-partner-details-rbac");
} }
} }

View File

@ -94,16 +94,8 @@ 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.query(""" .withIdentityView(SQL.projection("'P-' || partnerNumber"))
SELECT partner.partnerNumber .withUpdatableColumns("partnerroleuuid")
|| ':' || (SELECT idName FROM hs_office_person_iv p WHERE p.uuid = partner.personUuid)
|| '-' || (SELECT idName FROM hs_office_contact_iv c WHERE c.uuid = partner.contactUuid)
FROM hs_office_partner AS partner
"""))
.withUpdatableColumns(
"partnerRoleUuid",
"personUuid",
"contactUuid")
.toRole("global", ADMIN).grantPermission("partner", INSERT) // FIXME: global -> partnerRel.relAnchor? .toRole("global", ADMIN).grantPermission("partner", INSERT) // FIXME: global -> partnerRel.relAnchor?
.importRootEntityAliasProxy("partnerRel", HsOfficeRelationshipEntity.class, .importRootEntityAliasProxy("partnerRel", HsOfficeRelationshipEntity.class,
@ -122,6 +114,6 @@ public class HsOfficePartnerEntity implements Stringifyable, HasUuid {
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
rbac().generateWithBaseFileName("233-hs-office-partner-rbac-generated"); rbac().generateWithBaseFileName("233-hs-office-partner-rbac");
} }
} }

View File

@ -10,6 +10,7 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.JoinFormula;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.io.IOException; import java.io.IOException;
@ -55,15 +56,17 @@ public class HsOfficePersonEntity implements HasUuid, Stringifyable {
@Column(name = "givenname") @Column(name = "givenname")
private String givenName; private String givenName;
@OneToOne(cascade = CascadeType.ALL) @ManyToOne(cascade = CascadeType.ALL)
@JoinTable(name = "hs_office_relationship", @JoinFormula(
joinColumns = referencedColumnName = "uuid",
{ @JoinColumn(name = "uuid", referencedColumnName = "relanchoruuid") }, value = """
inverseJoinColumns = (SELECT partner.uuid AS uuid
{ @JoinColumn(name = "relanchoruuid", referencedColumnName = "uuid") }) FROM hs_office_partner partner
private HsOfficePartnerEntity optionalPartner; JOIN hs_office_relationship partnerRel
ON partnerRel.uuid = partner.partnerRoleUuid AND partnerRel.relType = 'PARTNER'
@Override WHERE partnerRel.relHolderUuid = h1_0.uuid)
""") // FIXME: h1_0 is the generated self-reference, I should find a better solution
private HsOfficePartnerEntity optionalPartner; @Override
public String toString() { public String toString() {
return toString.apply(this); return toString.apply(this);
} }

View File

@ -698,6 +698,7 @@ declare
superRoleId uuid; superRoleId uuid;
subRoleId uuid; subRoleId uuid;
begin begin
if ( superRoleId is null ) then return; end if;
superRoleId := findRoleId(superRole); superRoleId := findRoleId(superRole);
if ( subRoleId is null ) then return; end if; if ( subRoleId is null ) then return; end if;
subRoleId := findRoleId(subRole); subRoleId := findRoleId(subRole);

View File

@ -0,0 +1,45 @@
### rbac person
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-13T15:28:12.347550922.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph person["`**person**`"]
direction TB
style person fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph person:roles[ ]
style person:roles fill:#dd4901,stroke:white
role:person:owner[[person:owner]]
role:person:admin[[person:admin]]
role:person:referrer[[person:referrer]]
end
subgraph person:permissions[ ]
style person:permissions fill:#dd4901,stroke:white
perm:person:INSERT{{person:INSERT}}
perm:person:DELETE{{person:DELETE}}
perm:person:UPDATE{{person:UPDATE}}
perm:person:SELECT{{person:SELECT}}
end
end
%% granting roles to users
user:creator ==> role:person:owner
%% granting roles to roles
role:global:admin ==> role:person:owner
role:person:owner ==> role:person:admin
role:person:admin ==> role:person:referrer
%% granting permissions to roles
role:global:guest ==> perm:person:INSERT
role:person:owner ==> perm:person:DELETE
role:person:admin ==> perm:person:UPDATE
role:person:referrer ==> perm:person:SELECT
```

View File

@ -1,5 +1,6 @@
--liquibase formatted sql --liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T15:13:04.479330676. -- This code generated was by RbacViewPostgresGenerator at 2024-03-13T15:28:12.357028926.
-- ============================================================================ -- ============================================================================
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--// --changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
@ -72,9 +73,9 @@ create trigger insertTriggerForHsOfficePerson_tg
after insert on hs_office_person after insert on hs_office_person
for each row for each row
execute procedure insertTriggerForHsOfficePerson_tf(); execute procedure insertTriggerForHsOfficePerson_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-person-rbac-INSERT:1 endDelimiter:--// --changeset hs-office-person-rbac-INSERT:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -108,8 +109,8 @@ create or replace function hs_office_person_global_insert_tf()
strict as $$ strict as $$
begin begin
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_person'), globalGuest(),
globalGuest()); createPermission(NEW.uuid, 'INSERT', 'hs_office_person'));
return NEW; return NEW;
end; $$; end; $$;
@ -128,8 +129,8 @@ begin
raise exception '[403] insert into hs_office_person not allowed for current subjects % (%)', raise exception '[403] insert into hs_office_person not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -137,13 +138,15 @@ end; $$;
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$ call generateRbacIdentityViewFromProjection('hs_office_person', $idName$
concat(tradeName, familyName, givenName) concat(tradeName, familyName, givenName)
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_person', call generateRbacRestrictedView('hs_office_person',
'concat(tradeName, familyName, givenName)', $orderBy$
concat(tradeName, familyName, givenName)
$orderBy$,
$updates$ $updates$
personType = new.personType, personType = new.personType,
tradeName = new.tradeName, tradeName = new.tradeName,
@ -152,4 +155,3 @@ call generateRbacRestrictedView('hs_office_person',
$updates$); $updates$);
--// --//

View File

@ -1,6 +1,6 @@
### rbac partner ### rbac partner
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T15:29:41.494727519. This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-13T15:28:17.873062752.
```mermaid ```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
@ -26,7 +26,7 @@ subgraph partner["`**partner**`"]
subgraph partner:permissions[ ] subgraph partner:permissions[ ]
style partner:permissions fill:#dd4901,stroke:white style partner:permissions fill:#dd4901,stroke:white
perm:partner:new-partner{{partner:new-partner}} perm:partner:INSERT{{partner:INSERT}}
perm:partner:DELETE{{partner:DELETE}} perm:partner:DELETE{{partner:DELETE}}
perm:partner:UPDATE{{partner:UPDATE}} perm:partner:UPDATE{{partner:UPDATE}}
perm:partner:SELECT{{partner:SELECT}} perm:partner:SELECT{{partner:SELECT}}
@ -147,7 +147,7 @@ role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
%% granting permissions to roles %% granting permissions to roles
role:global:admin ==> perm:partner:new-partner role:global:admin ==> perm:partner:INSERT
role:partnerRel:admin ==> perm:partner:DELETE role:partnerRel:admin ==> perm:partner:DELETE
role:partnerRel:agent ==> perm:partner:UPDATE role:partnerRel:agent ==> perm:partner:UPDATE
role:partnerRel:tenant ==> perm:partner:SELECT role:partnerRel:tenant ==> perm:partner:SELECT

View File

@ -1,4 +1,6 @@
--liquibase formatted sql --liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-13T15:28:17.881206014.
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--// --changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--//
@ -8,245 +10,147 @@ call generateRelatedRbacObject('hs_office_partner');
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-ROLES-CREATION:1 endDelimiter:--// --changeset hs-office-partner-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
/*
Creates and updates the roles and their assignments for partner entities.
*/
create or replace function hsOfficePartnerRbacRolesTrigger()
returns trigger
language plpgsql
strict as $$
declare
partnerUuid uuid default new.uuid;
partnerDetailsUuid uuid default new.detailsUuid;
oldPartnerRel hs_office_relationship;
newPartnerRel hs_office_relationship;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_relationship as r where r.uuid = NEW.partnerroleuuid into newPartnerRel;
if TG_OP = 'INSERT' then
-- Permissions and Grants for Partner
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
createPermissions(partnerUuid, array ['DELETE'])
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
createPermissions(partnerUuid, array ['UPDATE'])
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipTenant(newPartnerRel)),
createPermissions(partnerUuid, array ['SELECT'])
);
-- Permissions and Grants for PartnerDetails
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
createPermissions(partnerDetailsUuid, array ['DELETE'])
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
createPermissions(partnerDetailsUuid, array ['UPDATE'])
);
call grantPermissionsToRole(
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficeRelationshipTENANT.
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
-- Otherwise package-admins etc. would be able to read the data.
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
createPermissions(partnerDetailsUuid, array ['SELECT'])
);
elsif TG_OP = 'UPDATE' then
if OLD.partnerRoleUuid <> NEW.partnerRoleUuid then
select * from hs_office_relationship as r where r.uuid = OLD.partnerRoleUuid into oldPartnerRel;
-- Revokes from Partner
call revokePermissionFromRole(
findPermissionId(partnerUuid, 'SELECT'),
hsOfficeRelationshipTenant(oldPartnerRel)
);
-- call revokePermissionFromRole(
-- findPermissionId(partnerUuid, 'edit'),
-- hsOfficeRelationshipAdmin(oldPartnerRel)
-- );
--
-- call revokePermissionFromRole(
-- findPermissionId(partnerUuid, '*'),
-- hsOfficeRelationshipOwner(oldPartnerRel)
-- );
-- Grants for Partner
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
array[findPermissionId(partnerUuid, 'DELETE')]
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
array[findPermissionId(partnerUuid, 'UPDATE')]
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipTenant(newPartnerRel)),
array[findPermissionId(partnerUuid, 'SELECT')]
);
-- Revokes from PartnerDetails
-- call revokePermissionFromRole(
-- findPermissionId(partnerDetailsUuid, 'SELECT'),
-- hsOfficeRelationshipAgent(oldPartnerRel)
-- );
--
-- call revokePermissionFromRole(
-- findPermissionId(partnerDetailsUuid, 'UPDATE'),
-- hsOfficeRelationshipAdmin(oldPartnerRel)
-- );
--
-- call revokePermissionFromRole(
-- findPermissionId(partnerDetailsUuid, 'DELETE'),
-- hsOfficeRelationshipOwner(oldPartnerRel)
-- );
-- Grants for PartnerDetails
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
array[findPermissionId(partnerDetailsUuid, 'DELETE')]
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
array[findPermissionId(partnerDetailsUuid, 'UPDATE')]
);
call grantPermissionsToRole(
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
-- Otherwise package-admins etc. would be able to read the data.
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
array[findPermissionId(partnerDetailsUuid, 'SELECT')]
);
end if;
else
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(partnerUuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
*/
create trigger createRbacRolesForHsOfficePartner_Trigger
after insert
on hs_office_partner
for each row
execute procedure hsOfficePartnerRbacRolesTrigger();
/*
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
*/
create trigger updateRbacRolesForHsOfficePartner_Trigger
after update
on hs_office_partner
for each row
execute procedure hsOfficePartnerRbacRolesTrigger();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-partner-rbac-insert-trigger:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_partner', $idName$
partnerNumber || ':' || /*
(select idName Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
from hs_office_person_iv p */
left join hs_office_relationship r on r.uuid = target.partnerRoleUuid
where p.uuid = r.relHolderUuid) create or replace procedure buildRbacSystemForHsOfficePartner(
|| '-' || NEW hs_office_partner
(select idName )
from hs_office_contact_iv c language plpgsql as $$
left join hs_office_relationship r on r.uuid = target.partnerRoleUuid
where c.uuid = r.contactUuid) declare
$idName$); newPartnerRel hs_office_relationship;
newPartnerDetails hs_office_partner_details;
begin
call enterTriggerForObjectUuid(NEW.uuid);
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);
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);
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationshipAdmin(newPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationshipTenant(newPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationshipAgent(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationshipAdmin(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationshipAgent(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationshipAgent(newPartnerRel));
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner row.
*/
create or replace function insertTriggerForHsOfficePartner_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePartner(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePartner_tg
after insert on hs_office_partner
for each row
execute procedure insertTriggerForHsOfficePartner_tf();
--// --//
-- ============================================================================
--changeset hs-office-partner-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_partner permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO hs_office_partner permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalAdmin());
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_partner');
call grantPermissionToRole(permissionUuid, roleUuid);
END LOOP;
END;
$$;
/**
Adds hs_office_partner INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_partner_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
globalAdmin(),
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'));
return NEW;
end; $$;
create trigger hs_office_partner_global_insert_tg
after insert on global
for each row
execute procedure hs_office_partner_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner.
*/
create or replace function hs_office_partner_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_partner not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_partner_insert_permission_check_tg
before insert on hs_office_partner
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_partner_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_partner', $idName$
'P-' || partnerNumber
$idName$);
--//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner', call generateRbacRestrictedView('hs_office_partner',
'target.partnerNumber', $orderBy$
'P-' || partnerNumber
$orderBy$,
$updates$ $updates$
partnerRoleUuid = new.partnerRoleUuid partnerroleuuid = new.partnerroleuuid
$updates$); $updates$);
--// --//
-- ============================================================================
--changeset hs-office-partner-rbac-NEW-PARTNER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-partner and assigns it to the Hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-partner permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-partner']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficePartnerNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-partner not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to create a new customer.
*/
create trigger hs_office_partner_insert_trigger
before insert
on hs_office_partner
for each row
-- TODO.spec: who is allowed to create new partners
when ( not hasAssumedRole() )
execute procedure addHsOfficePartnerNotAllowedForCurrentSubjects();
--//

View File

@ -0,0 +1,23 @@
### rbac partnerDetails
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-13T15:35:19.438833295.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph partnerDetails["`**partnerDetails**`"]
direction TB
style partnerDetails fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph partnerDetails:permissions[ ]
style partnerDetails:permissions fill:#dd4901,stroke:white
perm:partnerDetails:INSERT{{partnerDetails:INSERT}}
end
end
%% granting permissions to roles
role:global:admin ==> perm:partnerDetails:INSERT
```

View File

@ -1,4 +1,6 @@
--liquibase formatted sql --liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-13T15:35:19.446996853.
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--// --changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
@ -8,21 +10,134 @@ call generateRelatedRbacObject('hs_office_partner_details');
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-partner-details-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_partner_details', $idName$ call generateRbacRoleDescriptors('hsOfficePartnerDetails', 'hs_office_partner_details');
(select idName || '-details' from hs_office_partner_iv partner_iv
join hs_office_partner partner on (partner_iv.uuid = partner.uuid)
where partner.detailsUuid = target.uuid)
$idName$);
--// --//
-- ============================================================================
--changeset hs-office-partner-details-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficePartnerDetails(
NEW hs_office_partner_details
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner_details row.
*/
create or replace function insertTriggerForHsOfficePartnerDetails_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePartnerDetails(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePartnerDetails_tg
after insert on hs_office_partner_details
for each row
execute procedure insertTriggerForHsOfficePartnerDetails_tf();
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_partner_details permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO hs_office_partner_details permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalAdmin());
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_partner_details');
call grantPermissionToRole(permissionUuid, roleUuid);
END LOOP;
END;
$$;
/**
Adds hs_office_partner_details INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_partner_details_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
globalAdmin(),
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'));
return NEW;
end; $$;
create trigger hs_office_partner_details_global_insert_tg
after insert on global
for each row
execute procedure hs_office_partner_details_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details.
*/
create or replace function hs_office_partner_details_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_partner_details_insert_permission_check_tg
before insert on hs_office_partner_details
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_partner_details_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner_details', $idName$
SELECT partnerDetails.uuid as uuid, partner_iv.idName || '-details' as idName
FROM hs_office_partner_details AS partnerDetails
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
$idName$);
--//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner_details', call generateRbacRestrictedView('hs_office_partner_details',
'target.uuid', -- no specific order required $orderBy$
uuid
$orderBy$,
$updates$ $updates$
registrationOffice = new.registrationOffice, registrationOffice = new.registrationOffice,
registrationNumber = new.registrationNumber, registrationNumber = new.registrationNumber,
@ -33,51 +148,3 @@ call generateRbacRestrictedView('hs_office_partner_details',
$updates$); $updates$);
--// --//
-- ============================================================================
--changeset hs-office-partner-details-rbac-NEW-PARTNER-DETAILS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-partner-details and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-partner-details permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-partner-details']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
-- TODO.refa: the code below could be moved to a generator, maybe even the code above.
-- Additionally, the code below is not necessary for all entities, specify when it is!
/**
Used by the trigger to prevent the add-partner-details to current user respectively assumed roles.
*/
create or replace function addHsOfficePartnerDetailsNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-partner-details not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to create new partner-details.
*/
create trigger hs_office_partner_details_insert_trigger
before insert
on hs_office_partner_details
for each row
when ( not hasAssumedRole() )
execute procedure addHsOfficePartnerDetailsNotAllowedForCurrentSubjects();
--//

View File

@ -42,7 +42,7 @@ begin
-- coopsharestransactions cannot be edited nor deleted, just created+viewed -- coopsharestransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole( call grantPermissionsToRole(
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership)), getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT']) createPermissions(NEW.uuid, array ['SELECT'])
); );

View File

@ -42,7 +42,7 @@ begin
-- coopassetstransactions cannot be edited nor deleted, just created+viewed -- coopassetstransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole( call grantPermissionsToRole(
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership)), getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT']) createPermissions(NEW.uuid, array ['SELECT'])
); );

View File

@ -286,7 +286,6 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
"hs_office_person#ErbenBesslerMelBessler.admin"); "hs_office_person#ErbenBesslerMelBessler.admin");
assertThatPartnerActuallyInDatabase(givenPartner); assertThatPartnerActuallyInDatabase(givenPartner);
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
@ -332,7 +331,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
private void assertThatPartnerActuallyInDatabase(final HsOfficePartnerEntity saved) { private void assertThatPartnerActuallyInDatabase(final HsOfficePartnerEntity saved) {
final var found = partnerRepo.findByUuid(saved.getUuid()); final var found = partnerRepo.findByUuid(saved.getUuid());
assertThat(found).isNotEmpty().get().isNotSameAs(saved).usingRecursiveComparison().isEqualTo(saved); assertThat(found).isNotEmpty().get().isNotSameAs(saved).extracting(HsOfficePartnerEntity::toString).isEqualTo(saved.toString());
} }
private void assertThatPartnerIsVisibleForUserWithRole( private void assertThatPartnerIsVisibleForUserWithRole(

View File

@ -110,11 +110,9 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder( assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(
Array.from( Array.from(
initialGrantNames, initialGrantNames,
"{ grant perm * on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.owner by system and assume }", "{ grant role hs_office_person#anothernewperson.owner to user selfregistered-user-drew@hostsharing.org by hs_office_person#anothernewperson.owner and assume }",
"{ grant role hs_office_person#anothernewperson.owner to user selfregistered-user-drew@hostsharing.org by global#global.admin and assume }",
"{ grant role hs_office_person#anothernewperson.owner to role global#global.admin by system and assume }", "{ grant role hs_office_person#anothernewperson.owner to role global#global.admin by system and assume }",
"{ grant perm UPDATE on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.admin by system and assume }", "{ grant perm UPDATE on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.admin by system and assume }",
"{ grant role hs_office_person#anothernewperson.tenant to role hs_office_person#anothernewperson.admin by system and assume }",
"{ grant perm DELETE on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.owner by system and assume }", "{ grant perm DELETE on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.owner by system and assume }",
"{ grant role hs_office_person#anothernewperson.admin to role hs_office_person#anothernewperson.owner by system and assume }", "{ grant role hs_office_person#anothernewperson.admin to role hs_office_person#anothernewperson.owner by system and assume }",