diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index c3b14e9c..87a730a3 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -91,6 +91,37 @@ class RolesGrantsAndPermissionsGenerator { plPgSql.writeLn(); } + + private void generateSimplifiedUpdateTriggerFunction(final StringWriter plPgSql) { + + final var updateConditions = updatableEntityAliases() + .map(RbacView.EntityAlias::dependsOnColumName) + .distinct() + .map(columnName -> "NEW." + columnName + " is distinct from OLD." + columnName) + .collect(joining( "\n or ")); + plPgSql.writeLn(""" + /* + Called from the AFTER UPDATE TRIGGER to re-wire the grants. + */ + + create or replace procedure updateRbacRulesFor${simpleEntityName}( + OLD ${rawTableName}, + NEW ${rawTableName} + ) + language plpgsql as $$ + begin + + if ${updateConditions} then + delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; + call buildRbacSystemFor${simpleEntityName}(NEW); + end if; + end; $$; + """, + with("simpleEntityName", simpleEntityName), + with("rawTableName", rawTableName), + with("updateConditions", updateConditions)); + } + private void generateUpdateTriggerFunction(final StringWriter plPgSql) { plPgSql.writeLn(""" /* @@ -134,6 +165,12 @@ class RolesGrantsAndPermissionsGenerator { return updatableEntityAliases().anyMatch(e -> true); } + private boolean hasAnyUpdatableAndNullableEntityAliases() { + return updatableEntityAliases() + .filter(ea -> ea.nullable() == RbacView.Nullable.NULLABLE) + .anyMatch(e -> true); + } + private void generateCreateRolesAndGrantsAfterInsert(final StringWriter plPgSql) { referencedEntityAliases() .forEach((ea) -> { @@ -465,7 +502,11 @@ class RolesGrantsAndPermissionsGenerator { private void generateUpdateTrigger(final StringWriter plPgSql) { generateHeader(plPgSql, "update"); - generateUpdateTriggerFunction(plPgSql); + if ( hasAnyUpdatableAndNullableEntityAliases() ) { + generateSimplifiedUpdateTriggerFunction(plPgSql); + } else { + generateUpdateTriggerFunction(plPgSql); + } plPgSql.writeLn(""" /* diff --git a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql b/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql index 64aaeb53..01e43081 100644 --- a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql +++ b/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql @@ -1,5 +1,5 @@ --liquibase formatted sql --- This code generated was by RbacViewPostgresGenerator at 2024-03-16T13:52:18.491882945. +-- This code generated was by RbacViewPostgresGenerator at 2024-03-20T13:55:16.722860098. -- ============================================================================ @@ -54,7 +54,7 @@ begin SELECT * FROM hs_office_bankaccount AS b - WHERE b.uuid = NEW.refundbankaccountuuid + WHERE b.uuid = NEW.refundBankAccountUuid INTO newRefundBankAccount; call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationshipAgent(newDebitorRel)); @@ -103,18 +103,10 @@ create or replace procedure updateRbacRulesForHsOfficeDebitor( NEW hs_office_debitor ) language plpgsql as $$ - -declare - oldPartnerRel hs_office_relationship; - newPartnerRel hs_office_relationship; - oldDebitorRel hs_office_relationship; - newDebitorRel hs_office_relationship; - oldRefundBankAccount hs_office_bankaccount; - newRefundBankAccount hs_office_bankaccount; - begin - if NEW.refundbankaccountuuid <> OLD.refundbankaccountuuid - or NEW.debitorreluuid <> OLD.debitorreluuid then + + if NEW.debitorRelUuid is distinct from OLD.debitorRelUuid + or NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; call buildRbacSystemForHsOfficeDebitor(NEW); end if;