1
0

add-trigger-object-to-rbacgrant (#18)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/18
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-02-24 09:04:07 +01:00
parent c7003148ae
commit d9558f2cfe
17 changed files with 116 additions and 36 deletions

View File

@ -467,12 +467,13 @@ end $$;
create table RbacGrants
(
uuid uuid primary key default uuid_generate_v4(),
grantedByTriggerOf uuid references RbacObject (uuid) on delete cascade initially deferred ,
grantedByRoleUuid uuid references RbacRole (uuid),
ascendantUuid uuid references RbacReference (uuid),
descendantUuid uuid references RbacReference (uuid),
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
unique (ascendantUuid, descendantUuid)
);
unique (ascendantUuid, descendantUuid),
constraint rbacGrant_createdBy check ( grantedByRoleUuid is null or grantedByTriggerOf is null) );
create index on RbacGrants (ascendantUuid);
create index on RbacGrants (descendantUuid);
@ -576,8 +577,8 @@ begin
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
insert
into RbacGrants (ascendantUuid, descendantUuid, assumed)
values (roleUuid, permissionIds[i], true)
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
values (currentTriggerObjectUuid(), roleUuid, permissionIds[i], true)
on conflict do nothing; -- allow granting multiple times
end loop;
end;
@ -594,8 +595,8 @@ begin
end if;
insert
into RbacGrants (ascendantuuid, descendantUuid, assumed)
values (superRoleId, subRoleId, doAssume)
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
on conflict do nothing; -- allow granting multiple times
end; $$;
@ -617,8 +618,8 @@ begin
end if;
insert
into RbacGrants (ascendantuuid, descendantUuid, assumed)
values (superRoleId, subRoleId, doAssume)
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
on conflict do nothing; -- allow granting multiple times
end; $$;
@ -640,8 +641,8 @@ begin
end if;
insert
into RbacGrants (ascendantuuid, descendantUuid, assumed)
values (superRoleId, subRoleId, doAssume)
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
on conflict do nothing; -- allow granting multiple times
end; $$;

View File

@ -56,6 +56,7 @@ drop view if exists rbacgrants_ev;
create or replace view rbacgrants_ev as
-- @formatter:off
select x.grantUuid as uuid,
x.grantedByTriggerOf as grantedByTriggerOf,
go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName,
x.ascendingIdName as ascendantIdName,
x.descendingIdName as descendantIdName,
@ -65,6 +66,7 @@ create or replace view rbacgrants_ev as
x.assumed
from (
select g.uuid as grantUuid,
g.grantedbytriggerof as grantedbytriggerof,
g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
coalesce(

View File

@ -0,0 +1,61 @@
--liquibase formatted sql
-- ============================================================================
--changeset rbac-trigger-context-ENTER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace procedure enterTriggerForObjectUuid(currentObjectUuid uuid)
language plpgsql as $$
declare
existingObjectUuid text;
begin
existingObjectUuid = current_setting('hsadminng.currentObjectUuid', true);
if (existingObjectUuid > '' ) then
raise exception '[500] currentObjectUuid already defined, already in trigger of "%"', existingObjectUuid;
end if;
execute format('set local hsadminng.currentObjectUuid to %L', currentObjectUuid);
end; $$;
-- ============================================================================
--changeset rbac-trigger-context-CURRENT-ID:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Returns the uuid of the object uuid whose trigger is currently executed as set via `enterTriggerForObjectUuid(...)`.
*/
create or replace function currentTriggerObjectUuid()
returns uuid
stable -- leakproof
language plpgsql as $$
declare
currentObjectUuid uuid;
begin
begin
currentObjectUuid = current_setting('hsadminng.currentObjectUuid')::uuid;
return currentObjectUuid;
exception
when others then
return null::uuid;
end;
end; $$;
--//
-- ============================================================================
--changeset rbac-trigger-context-LEAVE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace procedure leaveTriggerForObjectUuid(currentObjectUuid uuid)
language plpgsql as $$
declare
existingObjectUuid uuid;
begin
existingObjectUuid = current_setting('hsadminng.currentObjectUuid', true);
if ( existingObjectUuid <> currentObjectUuid ) then
raise exception '[500] currentObjectUuid does not match: "%"', existingObjectUuid;
end if;
execute format('reset hsadminng.currentObjectUuid');
end; $$;

View File

@ -34,6 +34,8 @@ begin
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
call enterTriggerForObjectUuid(NEW.uuid);
-- the owner role with full access for Hostsharing administrators
testCustomerOwnerUuid = createRoleWithGrants(
testCustomerOwner(NEW),
@ -59,6 +61,7 @@ begin
permissions => array['view']
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -26,13 +26,13 @@ create or replace function createRbacRolesForTestPackage()
strict as $$
declare
parentCustomer test_customer;
packageOwnerRoleUuid uuid;
packageAdminRoleUuid uuid;
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
call enterTriggerForObjectUuid(NEW.uuid);
select * from test_customer as c where c.uuid = NEW.customerUuid into parentCustomer;
-- an owner role is created and assigned to the customer's admin role
@ -57,6 +57,7 @@ begin
outgoingSubRoles => array[testCustomerTenant(parentCustomer)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -53,6 +53,8 @@ begin
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
call enterTriggerForObjectUuid(NEW.uuid);
select * from test_package where uuid = NEW.packageUuid into parentPackage;
-- an owner role is created and assigned to the package's admin group
@ -72,6 +74,7 @@ begin
-- a tenent role is only created on demand
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -33,6 +33,7 @@ declare
oldContact hs_office_contact;
newContact hs_office_contact;
begin
call enterTriggerForObjectUuid(NEW.uuid);
hsOfficeRelationshipTenant := hsOfficeRelationshipTenant(NEW);
@ -96,6 +97,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -36,6 +36,7 @@ declare
oldContact hs_office_contact;
newContact hs_office_contact;
begin
call enterTriggerForObjectUuid(NEW.uuid);
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;
@ -159,6 +160,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -30,6 +30,7 @@ declare
newHsOfficeDebitor hs_office_debitor;
newHsOfficeBankAccount hs_office_bankAccount;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_debitor as p where p.uuid = NEW.debitorUuid into newHsOfficeDebitor;
select * from hs_office_bankAccount as c where c.uuid = NEW.bankAccountUuid into newHsOfficeBankAccount;
@ -75,6 +76,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -36,6 +36,7 @@ declare
newBankAccount hs_office_bankaccount;
oldBankAccount hs_office_bankaccount;
begin
call enterTriggerForObjectUuid(NEW.uuid);
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
@ -145,6 +146,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -30,6 +30,7 @@ declare
newHsOfficePartner hs_office_partner;
newHsOfficeDebitor hs_office_debitor;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner;
select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor;
@ -74,6 +75,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -29,6 +29,7 @@ create or replace function hsOfficeCoopSharesTransactionRbacRolesTrigger()
declare
newHsOfficeMembership hs_office_membership;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
@ -49,6 +50,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -29,6 +29,7 @@ create or replace function hsOfficeCoopAssetsTransactionRbacRolesTrigger()
declare
newHsOfficeMembership hs_office_membership;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
@ -49,6 +50,7 @@ begin
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;

View File

@ -25,6 +25,8 @@ databaseChangeLog:
file: db/changelog/054-rbac-context.sql
- include:
file: db/changelog/055-rbac-views.sql
- include:
file: db/changelog/056-rbac-trigger-context.sql
- include:
file: db/changelog/057-rbac-role-builder.sql
- include: