consolidating role deletion from business objects to rbac system

This commit is contained in:
Michael Hoennig 2022-09-13 10:58:54 +02:00
parent ac5f19e399
commit 0b48e8d1b7
12 changed files with 136 additions and 263 deletions

View File

@ -122,7 +122,17 @@ create table RbacObject
call create_journal('RbacObject');
create or replace function createRbacObject()
--//
-- ============================================================================
--changeset rbac-base-GENERATE-RELATED-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Inserts related RbacObject for use in the BEFORE ONSERT TRIGGERs on the business objects.
*/
create or replace function insertRelatedRbacObject()
returns trigger
language plpgsql
strict as $$
@ -147,8 +157,51 @@ begin
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
end; $$;
/*
Deletes related RbacObject for use in the BEFORE DELETE TRIGGERs on the business objects.
*/
create or replace function deleteRelatedRbacObject()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
delete from RbacObject where rbacobject.uuid = old.uuid;
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
return old;
end; $$;
create or replace procedure generateRelatedRbacObject(targetTable varchar)
language plpgsql as $$
declare
createInsertTriggerSQL text;
createDeleteTriggerSQL text;
begin
createInsertTriggerSQL = format($sql$
create trigger createRbacObjectFor_%s_Trigger
before insert
on %s
for each row
execute procedure insertRelatedRbacObject();
$sql$, targetTable, targetTable);
execute createInsertTriggerSQL;
createDeleteTriggerSQL = format($sql$
create trigger deleteRbacRulesFor_%s_Trigger
before delete
on %s
for each row
execute procedure deleteRelatedRbacObject();
$sql$, targetTable, targetTable);
execute createDeleteTriggerSQL;
end; $$;
--//
-- ============================================================================
--changeset rbac-base-ROLE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
@ -160,8 +213,8 @@ create type RbacRoleType as enum ('owner', 'admin', 'tenant');
create table RbacRole
(
uuid uuid primary key references RbacReference (uuid) on delete cascade,
objectUuid uuid references RbacObject (uuid) not null,
uuid uuid primary key references RbacReference (uuid) on delete cascade initially deferred, -- initially deferred
objectUuid uuid not null references RbacObject (uuid) initially deferred,
roleType RbacRoleType not null,
unique (objectUuid, roleType)
);
@ -269,13 +322,13 @@ $$;
-- ============================================================================
--changeset hs-admin-person-rbac-ROLES-REMOVAL:1 endDelimiter:--//
--changeset rbac-base-BEFORE-DELETE-ROLE-TRIGGER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
RbacRole BEFORE DELETE TRIGGER function which deletes all related roles.
*/
create or replace function deleteRbacGrantsForRbacRole()
create or replace function deleteRbacGrantsOfRbacRole()
returns trigger
language plpgsql
strict as $$
@ -291,11 +344,43 @@ end; $$;
/*
Installs the RbacRole BEFORE DELETE TRIGGER.
*/
create trigger deleteRbacGrantsForRbacRole_Trigger
create trigger deleteRbacGrantsOfRbacRole_Trigger
before delete
on RbacRole
for each row
execute procedure deleteRbacGrantsForRbacRole();
execute procedure deleteRbacGrantsOfRbacRole();
--//
-- ============================================================================
--changeset rbac-base-BEFORE-DELETE-OBJECT-TRIGGER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
RbacObject BEFORE DELETE TRIGGER function which deletes all related roles.
*/
create or replace function deleteRbacRolesOfRbacObject()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
delete from RbacPermission p where p.objectuuid = old.uuid;
delete from RbacRole r where r.objectUuid = old.uuid;
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
return old;
end; $$;
/*
Installs the RbacRole BEFORE DELETE TRIGGER.
*/
create trigger deleteRbacRolesOfRbacObject_Trigger
before delete
on RbacObject
for each row
execute procedure deleteRbacRolesOfRbacObject();
--//

View File

@ -12,7 +12,7 @@ create trigger createRbacObjectForCustomer_Trigger
before insert
on test_customer
for each row
execute procedure createRbacObject();
execute procedure insertRelatedRbacObject();
--//
-- ============================================================================
@ -106,40 +106,6 @@ execute procedure createRbacRolesForTestCustomer();
--//
-- ============================================================================
--changeset test-customer-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Deletes the roles and their assignments of a deleted customer for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForTestCustomer()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(testCustomerOwner(OLD)));
call deleteRole(findRoleId(testCustomerAdmin(OLD)));
call deleteRole(findRoleId(testCustomerTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a customer.
*/
drop trigger if exists deleteRbacRulesForTestCustomer_Trigger on test_customer;
create trigger deleteRbacRulesForTestCustomer_Trigger
before delete
on test_customer
for each row
execute procedure deleteRbacRulesForTestCustomer();
--//
-- ============================================================================
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@ -11,7 +11,7 @@ create trigger createRbacObjectForPackage_Trigger
before insert
on test_package
for each row
execute procedure createRbacObject();
execute procedure insertRelatedRbacObject();
--//
@ -103,40 +103,6 @@ create trigger createRbacRolesForTestPackage_Trigger
execute procedure createRbacRolesForTestPackage();
--//
-- ============================================================================
--changeset test-package-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Deletes the roles and their assignments of a deleted package for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForTestPackage()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(testPackageOwner(OLD)));
call deleteRole(findRoleId(testPackageAdmin(OLD)));
call deleteRole(findRoleId(testPackageTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a package.
*/
drop trigger if exists deleteRbacRulesForTestPackage_Trigger on test_package;
create trigger deleteRbacRulesForTestPackage_Trigger
before delete
on test_package
for each row
execute procedure deleteRbacRulesForTestPackage();
--//
-- ============================================================================
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//

View File

@ -11,7 +11,7 @@ create trigger createRbacObjectFortest_domain_Trigger
before insert
on test_domain
for each row
execute procedure createRbacObject();
execute procedure insertRelatedRbacObject();
--//
@ -121,41 +121,6 @@ execute procedure createRbacRulesForTestDomain();
--//
-- ============================================================================
--changeset test-domain-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Deletes the roles and their assignments of a deleted domain for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForTestDomain()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(testdomainOwner(OLD)));
call deleteRole(findRoleId(testdomainAdmin(OLD)));
call deleteRole(findRoleId(testdomainTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a domain.
*/
drop trigger if exists deleteRbacRulesForTestDomain_Trigger on test_package;
create trigger deleteRbacRulesForTestDomain_Trigger
before delete
on test_domain
for each row
execute procedure deleteRbacRulesForTestDomain();
--//
-- ============================================================================
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@ -6,7 +6,7 @@
create table if not exists hs_admin_contact
(
uuid uuid unique references RbacObject (uuid) on delete cascade,
uuid uuid unique references RbacObject (uuid) initially deferred,
label varchar(96) not null,
postalAddress text,
emailAddresses text, -- TODO.feat: change to json

View File

@ -1,19 +1,12 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-admin-contact-rbac-CREATE-OBJECT:1 endDelimiter:--//
--changeset hs-admin-contact-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the related RbacObject through a BEFORE INSERT TRIGGER.
*/
create trigger createRbacObjectForHsAdminCustomer_Trigger
before insert
on hs_admin_contact
for each row
execute procedure createRbacObject();
call generateRelatedRbacObject('hs_admin_contact');
--//
-- ============================================================================
--changeset hs-admin-contact-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
@ -103,37 +96,6 @@ execute procedure createRbacRolesForHsAdminContact();
--//
-- ============================================================================
--changeset hs-admin-contact-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Deletes the roles and their assignments of a deleted contact for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForHsAdminContact()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(hsAdminContactOwner(OLD)));
call deleteRole(findRoleId(hsAdminContactTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
return old;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a contact.
*/
create trigger deleteRbacRulesForTestContact_Trigger
before delete
on hs_admin_contact
for each row
execute procedure deleteRbacRulesForHsAdminContact();
--//
-- ============================================================================
--changeset hs-admin-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@ -10,7 +10,7 @@ CREATE CAST (character varying as HsAdminPersonType) WITH INOUT AS IMPLICIT;
create table if not exists hs_admin_person
(
uuid uuid unique references RbacObject (uuid) on delete cascade,
uuid uuid unique references RbacObject (uuid) initially deferred,
personType HsAdminPersonType not null,
tradeName varchar(96),
givenName varchar(48),

View File

@ -1,19 +1,13 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-admin-person-rbac-CREATE-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the related RbacObject through a BEFORE INSERT TRIGGER.
*/
create trigger createRbacObjectForHsAdminPerson_Trigger
before insert
on hs_admin_person
for each row
execute procedure createRbacObject();
-- ============================================================================
--changeset hs-admin-person-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_admin_person');
--//
-- ============================================================================
--changeset hs-admin-person-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
@ -103,40 +97,6 @@ execute procedure createRbacRolesForHsAdminPerson();
--//
-- ============================================================================
--changeset hs-admin-person-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
-- TODO: can we replace all these delete triggers by a delete trigger on RbacObject?
/*
Deletes the roles and their assignments of a deleted person for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForHsAdminPerson()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(hsAdminPersonOwner(OLD)));
call deleteRole(findRoleId(hsAdminPersonAdmin(OLD)));
call deleteRole(findRoleId(hsAdminPersonTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
return old;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a person.
*/
create trigger deleteRbacRulesForTestPerson_Trigger
before delete
on hs_admin_person
for each row
execute procedure deleteRbacRulesForHsAdminPerson();
--//
-- ============================================================================
--changeset hs-admin-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@ -6,7 +6,7 @@
create table if not exists hs_admin_partner
(
uuid uuid unique references RbacObject (uuid) on delete cascade,
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
personUuid uuid not null references hs_admin_person(uuid),
contactUuid uuid not null references hs_admin_contact(uuid),
registrationOffice varchar(96),

View File

@ -1,19 +1,12 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-admin-partner-rbac-CREATE-OBJECT:1 endDelimiter:--//
--changeset hs-admin-partner-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the related RbacObject through a BEFORE INSERT TRIGGER.
*/
create trigger createRbacObjectForHsAdminPartner_Trigger
before insert
on hs_admin_partner
for each row
execute procedure createRbacObject();
call generateRelatedRbacObject('hs_admin_partner');
--//
-- ============================================================================
--changeset hs-admin-partner-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
@ -106,38 +99,6 @@ execute procedure createRbacRolesForHsAdminPartner();
--//
-- ============================================================================
--changeset hs-admin-partner-rbac-ROLES-REMOVAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Deletes the roles and their assignments of a deleted partner for the BEFORE DELETE TRIGGER.
*/
create or replace function deleteRbacRulesForHsAdminPartner()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
call deleteRole(findRoleId(hsAdminPartnerOwner(OLD)));
call deleteRole(findRoleId(hsAdminPartnerAdmin(OLD)));
call deleteRole(findRoleId(hsAdminPartnerTenant(OLD)));
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
return old;
end; $$;
/*
An BEFORE DELETE TRIGGER which deletes the role structure of a partner.
*/
create trigger deleteRbacRulesForTestPartner_Trigger
before delete
on hs_admin_partner
for each row
execute procedure deleteRbacRulesForHsAdminPartner();
--//
-- ============================================================================
--changeset hs-admin-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@ -95,9 +95,9 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
public void createsAndGrantsRoles() {
// given
context("alex@hostsharing.net");
final var initialRoleCount = rawRoleRepo.findAll().size();
final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
final var initialGrantCount = rawGrantRepo.findAll().size();
final var initialGrantsDisplayNames = grantDisplaysOf(rawGrantRepo.findAll());
final var initialGrantsDisplayNames = grantDisplaysOf(rawGrantRepo.findAll()); // TODO
// when
attempt(em, () -> {
@ -112,12 +112,11 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
});
// then
assertThat(roleNamesOf(rawRoleRepo.findAll())).containsAll(List.of(
assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
initialRoleNames,
"hs_admin_partner#ErbenBesslerMelBessler-forthcontact.admin",
"hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner",
"hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant"))
.as("invalid number of roles created")
.hasSize(initialRoleCount + 3);
"hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant"));
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsAll(List.of(
"{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.owner to role global#global.admin by system and assume }",
"{ grant role hs_admin_partner#ErbenBesslerMelBessler-forthcontact.tenant to role hs_admin_contact#forthcontact.admin by system and assume }",
@ -245,11 +244,20 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
final var result = jpaAttempt.transacted(() -> {
context("alex@hostsharing.net");
partnerRepo.deleteByUuid(givenPartner.getUuid());
}).assertSuccessful();
});
// then
final var roles = rawRoleRepo.findAll();
assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder(initialRoleNames);
result.assertSuccessful();
jpaAttempt.transacted(() -> {
final var remainingPartner = em.createNativeQuery("select p.uuid from hs_admin_partner p where p.uuid=?1")
.setParameter(1, givenPartner.getUuid()).getResultList();
assertThat(remainingPartner).isEmpty();
final var remainingObject = em.createNativeQuery("select o.uuid from RbacObject o where o.uuid=?1")
.setParameter(1, givenPartner.getUuid())
.getResultList();
assertThat(remainingObject).isEmpty();
assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(initialRoleNames);
context("customer-admin@forthcontact.example.com");
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).doesNotContain(
@ -258,6 +266,7 @@ class HsAdminPartnerRepositoryIntegrationTest extends ContextBasedTest {
context("person-ErbenBesslerMelBessler@example.com");
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).doesNotContain(
"{ grant assumed role hs_admin_person#ErbenBesslerMelBessler.owner to user person-ErbenBesslerMelBessl@example.com by role global#global.admin }");
}).assertSuccessful();
}
}

View File

@ -71,7 +71,6 @@ public class JpaAttempt {
});
return JpaResult.forVoidValue();
} catch (final RuntimeException exc) {
return new JpaResult<>(null, exc);
}
}