From 708064142f759d3fa36c31eb3fb2f923c02d5ff2 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 26 Apr 2024 10:41:56 +0200 Subject: [PATCH] fixes for generated multiple insert permission grants, hs_booking_item and hs_hosting_asset green --- .../hosting/asset/HsHostingAssetEntity.java | 5 +- .../rbac/rbacdef/InsertTriggerGenerator.java | 95 ++-- .../rbacdef/RbacIdentityViewGenerator.java | 9 +- .../hsadminng/rbac/rbacdef/RbacView.java | 3 +- .../hsadminng/rbac/rbacdef/StringWriter.java | 10 +- .../7013-hs-hosting-asset-rbac.md | 469 ++++++++++++++++++ .../7013-hs-hosting-asset-rbac.sql | 3 +- 7 files changed, 547 insertions(+), 47 deletions(-) create mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java index f915646e..29ad7288 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java @@ -37,6 +37,7 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOU import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inCaseOf; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inOtherCases; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; @@ -157,7 +158,9 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject { directlyFetchedByDependsOnColumn(), NULLABLE) .toRole("parentServer", ADMIN).grantPermission(INSERT) - ) + .toRole("bookingItem", AGENT).grantPermission(INSERT) + ), + inOtherCases(then -> {}) ) .createRole(OWNER, (with) -> { diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java index 03e1516f..18bada8e 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java @@ -64,27 +64,28 @@ public class InsertTriggerGenerator { */ do language plpgsql $$ declare - preExistingRow ${rawSuperTable}; + row ${rawSuperTable}; begin call defineContext('create INSERT INTO ${rawSubTable} permissions for pre-exising ${rawSuperTable} rows'); - FOR preExistingRow IN SELECT * FROM ${rawSuperTable} + FOR row IN SELECT * FROM ${rawSuperTable} ${whenCondition} LOOP call grantPermissionToRole( - createPermission(preExistingRow.uuid, 'INSERT', '${rawSubTable}'), - hsBookingItemAGENT(preExistingRow)); + createPermission(row.uuid, 'INSERT', '${rawSubTable}'), + ${superRoleRef}); END LOOP; end; $$; """, with("whenCondition", g.getSuperRoleDef().getEntityAlias().isCaseDependent() - // TODO.impl: .type needs to be dynamically generated - ? "WHERE preExistingRow.type = '${value}'" + // TODO.impl: 'type' needs to be dynamically generated + ? "WHERE type = '${value}'" .replace("${value}", g.getSuperRoleDef().getEntityAlias().usingCase().value) : "-- unconditional for all rows in that table"), with("rawSuperTable", g.getSuperRoleDef().getEntityAlias().getRawTableName()), - with("rawSubTable", g.getPermDef().getEntityAlias().getRawTableName())); + with("rawSubTable", g.getPermDef().getEntityAlias().getRawTableName()), + with("superRoleRef", toRoleDescriptor(g.getSuperRoleDef(), "row"))); } else { plPgSql.writeLn(""" -- Granting INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_hosting_asset rows slipped, @@ -166,46 +167,64 @@ public class InsertTriggerGenerator { -- ============================================================================ --changeset ${rawSubTable}-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - + /** - Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}, - where the check is performed by a direct role. - - A direct role is a role depending on a foreign key directly available in the NEW row. + Checks if the user respectively the assumed roles are allowed to insert a row to ${rawSubTable}. */ - create or replace function ${rawSubTable}_insert_permission_missing_tf() + create or replace function ${rawSubTable}_insert_permission_check_tf() returns trigger language plpgsql as $$ + declare + superObjectUuid uuid; begin - raise exception '[403] insert into ${rawSubTable} not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); - end; $$; - - create trigger ${rawSubTable}_insert_permission_check_tg - before insert on ${rawSubTable} - for each row - when ( not ( """, - with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); + with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); plPgSql.chopEmptyLines(); - plPgSql.indented(3, () -> { + plPgSql.indented(1, () -> { getInsertGrants().forEach(g -> { final RbacView.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias(); - final RbacView.EntityAlias permissionEntityAlias = g.getPermDef().entityAlias; - final var caseCondition = superRoleEntityAlias.isCaseDependent() - ? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ") - : ""; - if ( g.getSuperRoleDef().isGlobalAdmin() ) { - plPgSql.writeLn( - "${caseCondition}isGlobalAdmin() or", + + if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) { + final var caseCondition = g.isConditional() + ? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ") + : ""; + if (g.getSuperRoleDef().isGlobalAdmin()) { + plPgSql.writeLn( + """ + -- check INSERT INSERT permission via isGlobalAdmin + if ${caseCondition}isGlobalAdmin() then + return NEW; + end if; + """, with("caseCondition", caseCondition)); - } else { - plPgSql.writeLn( - "${caseCondition}hasInsertPermission(NEW.${refColumn}, '${rawSubTable}') or", + } else { + plPgSql.writeLn( + """ + -- check INSERT permission via direct foreign key: NEW.${refColumn} + if ${caseCondition}hasInsertPermission(NEW.${refColumn}, '${rawSubTable}') then + return NEW; + end if; + """, with("caseCondition", caseCondition), with("refColumn", superRoleEntityAlias.dependsOnColumName()), with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); + } + } else { + plPgSql.writeLn( + """ + -- check INSERT permission via indirect foreign key: NEW.${refColumn} + superObjectUuid := (${fetchSql}); + assert superObjectUuid is not null, 'object uuid fetched depending on ${rawSubTable}.${refColumn} must not be null, also check fetchSql in RBAC DSL'; + if hasInsertPermission(superObjectUuid, '${rawSubTable}') then + return NEW; + end if; + """, + with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()), + with("refColumn", superRoleEntityAlias.dependsOnColumName()), + with("fetchSql", g.getSuperRoleDef().getEntityAlias().fetchSql().sql), + with("columns", g.getSuperRoleDef().getEntityAlias().aliasName() + ".uuid"), + with("ref", NEW.name())); } }); plPgSql.chopTail(" or\n"); @@ -213,8 +232,14 @@ public class InsertTriggerGenerator { plPgSql.writeLn(); plPgSql.writeLn(""" - ) ) - execute procedure ${rawSubTable}_insert_permission_missing_tf(); + raise exception '[403] insert into ${rawSubTable} not allowed for current subjects % (%)', + currentSubjects(), currentSubjectsUuids(); + end; $$; + + create trigger ${rawSubTable}_insert_permission_check_tg + before insert on ${rawSubTable} + for each row + execute procedure ${rawSubTable}_insert_permission_check_tf(); --// """, with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacIdentityViewGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacIdentityViewGenerator.java index 066acba2..50b404eb 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacIdentityViewGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacIdentityViewGenerator.java @@ -32,10 +32,10 @@ public class RbacIdentityViewGenerator { $idName$); """; case SQL_QUERY -> """ - call generateRbacIdentityViewFromQuery('${rawTableName}', - $idName$ - ${identityViewSqlPart} - $idName$); + call generateRbacIdentityViewFromQuery('${rawTableName}', + $idName$ + ${identityViewSqlPart} + $idName$); """; default -> throw new IllegalStateException("illegal SQL part given"); }, @@ -43,5 +43,6 @@ public class RbacIdentityViewGenerator { with("rawTableName", rawTableName)); plPgSql.writeLn("--//"); + plPgSql.writeLn(); } } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index 718ee146..757c862d 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -535,7 +535,7 @@ public class RbacView { private final RbacPermissionDefinition permDef; private boolean assumed = true; private boolean toCreate = false; - private Set forCases = new HashSet<>(); + private Set forCases = new LinkedHashSet<>(); @Override public String toString() { @@ -860,6 +860,7 @@ public class RbacView { return grantDefs.stream() .filter(g -> g.permDef == permDef && g.superRoleDef == roleDef) .findFirst() + .map(g -> g.forCase(processingCase)) .orElseGet(() -> new RbacGrantDefinition(permDef, roleDef, processingCase)); } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/StringWriter.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/StringWriter.java index fe4b0548..d78e9a3b 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/StringWriter.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/StringWriter.java @@ -2,8 +2,6 @@ package net.hostsharing.hsadminng.rbac.rbacdef; import org.apache.commons.lang3.StringUtils; -import java.util.regex.Pattern; - import static java.util.Arrays.stream; import static java.util.stream.Collectors.joining; @@ -111,9 +109,11 @@ public class StringWriter { String apply(final String textToAppend) { text = textToAppend; stream(varDefs).forEach(varDef -> { - final var pattern = Pattern.compile("\\$\\{" + varDef.name() + "}", Pattern.CASE_INSENSITIVE); - final var matcher = pattern.matcher(text); - text = matcher.replaceAll(varDef.value()); + // TODO.impl: I actually want a case-independent search+replace but ... + // for which the substitution String can contain sequences of "${...}" to be replaced by further varDefs. + text = text.replace("${" + varDef.name() + "}", varDef.value()); + text = text.replace("${" + varDef.name().toUpperCase() + "}", varDef.value()); + text = text.replace("${" + varDef.name().toLowerCase() + "}", varDef.value()); }); return text; } diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md new file mode 100644 index 00000000..f8886b7b --- /dev/null +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md @@ -0,0 +1,469 @@ +### rbac asset inOtherCases + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph parentServer.bookingItem["`**parentServer.bookingItem**`"] + direction TB + style parentServer.bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem:roles[ ] + style parentServer.bookingItem:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem:OWNER[[parentServer.bookingItem:OWNER]] + role:parentServer.bookingItem:ADMIN[[parentServer.bookingItem:ADMIN]] + role:parentServer.bookingItem:AGENT[[parentServer.bookingItem:AGENT]] + role:parentServer.bookingItem:TENANT[[parentServer.bookingItem:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitorRel.anchorPerson["`**parentServer.bookingItem.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.holderPerson["`**parentServer.bookingItem.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer["`**parentServer**`"] + direction TB + style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer:roles[ ] + style parentServer:roles fill:#99bcdb,stroke:white + + role:parentServer:ADMIN[[parentServer:ADMIN]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson["`**parentServer.bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson["`**parentServer.bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel.anchorPerson["`**bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.anchorPerson:OWNER[[bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.contact["`**parentServer.bookingItem.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.contact:OWNER[[parentServer.bookingItem.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel["`**bookingItem.debitor.partnerRel**`"] + direction TB + style bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel:roles[ ] + style bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel:OWNER[[bookingItem.debitor.partnerRel:OWNER]] + role:bookingItem.debitor.partnerRel:ADMIN[[bookingItem.debitor.partnerRel:ADMIN]] + role:bookingItem.debitor.partnerRel:AGENT[[bookingItem.debitor.partnerRel:AGENT]] + role:bookingItem.debitor.partnerRel:TENANT[[bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.partnerRel.anchorPerson["`**bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.anchorPerson:OWNER[[bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel["`**bookingItem.debitorRel**`"] + direction TB + style bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel:roles[ ] + style bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel:OWNER[[bookingItem.debitorRel:OWNER]] + role:bookingItem.debitorRel:ADMIN[[bookingItem.debitorRel:ADMIN]] + role:bookingItem.debitorRel:AGENT[[bookingItem.debitorRel:AGENT]] + role:bookingItem.debitorRel:TENANT[[bookingItem.debitorRel:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.contact["`**parentServer.bookingItem.debitor.partnerRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.contact:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.contact:OWNER[[parentServer.bookingItem.debitor.partnerRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.contact:ADMIN[[parentServer.bookingItem.debitor.partnerRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.contact:REFERRER[[parentServer.bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.anchorPerson["`**bookingItem.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.anchorPerson:OWNER[[bookingItem.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitorRel.anchorPerson:ADMIN[[bookingItem.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitorRel.anchorPerson:REFERRER[[bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.debitorRel["`**parentServer.bookingItem.debitor.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel:roles[ ] + style parentServer.bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel:OWNER[[parentServer.bookingItem.debitor.debitorRel:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel:ADMIN[[parentServer.bookingItem.debitor.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel:AGENT[[parentServer.bookingItem.debitor.debitorRel:AGENT]] + role:parentServer.bookingItem.debitor.debitorRel:TENANT[[parentServer.bookingItem.debitor.debitorRel:TENANT]] + end +end + +subgraph bookingItem.debitorRel.holderPerson["`**bookingItem.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.holderPerson:roles[ ] + style bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.holderPerson:OWNER[[bookingItem.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitorRel.holderPerson:ADMIN[[bookingItem.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitorRel.holderPerson:REFERRER[[bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.refundBankAccount["`**bookingItem.debitor.refundBankAccount**`"] + direction TB + style bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.refundBankAccount:roles[ ] + style bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.refundBankAccount:OWNER[[bookingItem.debitor.refundBankAccount:OWNER]] + role:bookingItem.debitor.refundBankAccount:ADMIN[[bookingItem.debitor.refundBankAccount:ADMIN]] + role:bookingItem.debitor.refundBankAccount:REFERRER[[bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel["`**parentServer.bookingItem.debitor.partnerRel**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel:roles[ ] + style parentServer.bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel:OWNER[[parentServer.bookingItem.debitor.partnerRel:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel:ADMIN[[parentServer.bookingItem.debitor.partnerRel:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel:AGENT[[parentServer.bookingItem.debitor.partnerRel:AGENT]] + role:parentServer.bookingItem.debitor.partnerRel:TENANT[[parentServer.bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.debitorRel.contact["`**bookingItem.debitor.debitorRel.contact**`"] + direction TB + style bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.contact:roles[ ] + style bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.contact:OWNER[[bookingItem.debitor.debitorRel.contact:OWNER]] + role:bookingItem.debitor.debitorRel.contact:ADMIN[[bookingItem.debitor.debitorRel.contact:ADMIN]] + role:bookingItem.debitor.debitorRel.contact:REFERRER[[bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor["`**parentServer.bookingItem.debitor**`"] + direction TB + style parentServer.bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson["`**parentServer.bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.contact["`**bookingItem.debitor.partnerRel.contact**`"] + direction TB + style bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.contact:roles[ ] + style bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.contact:OWNER[[bookingItem.debitor.partnerRel.contact:OWNER]] + role:bookingItem.debitor.partnerRel.contact:ADMIN[[bookingItem.debitor.partnerRel.contact:ADMIN]] + role:bookingItem.debitor.partnerRel.contact:REFERRER[[bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel["`**parentServer.bookingItem.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel:roles[ ] + style parentServer.bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel:OWNER[[parentServer.bookingItem.debitorRel:OWNER]] + role:parentServer.bookingItem.debitorRel:ADMIN[[parentServer.bookingItem.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitorRel:AGENT[[parentServer.bookingItem.debitorRel:AGENT]] + role:parentServer.bookingItem.debitorRel:TENANT[[parentServer.bookingItem.debitorRel:TENANT]] + end +end + +subgraph bookingItem["`**bookingItem**`"] + direction TB + style bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem:roles[ ] + style bookingItem:roles fill:#99bcdb,stroke:white + + role:bookingItem:OWNER[[bookingItem:OWNER]] + role:bookingItem:ADMIN[[bookingItem:ADMIN]] + role:bookingItem:AGENT[[bookingItem:AGENT]] + role:bookingItem:TENANT[[bookingItem:TENANT]] + end +end + +subgraph parentServer.parentServer["`**parentServer.parentServer**`"] + direction TB + style parentServer.parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.contact["`**parentServer.bookingItem.debitor.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.contact:OWNER[[parentServer.bookingItem.debitor.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitor.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.holderPerson["`**bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.holderPerson:OWNER[[bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:bookingItem.debitor.partnerRel.holderPerson:ADMIN[[bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.holderPerson:REFERRER[[bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.contact["`**bookingItem.debitorRel.contact**`"] + direction TB + style bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.contact:roles[ ] + style bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.contact:OWNER[[bookingItem.debitorRel.contact:OWNER]] + role:bookingItem.debitorRel.contact:ADMIN[[bookingItem.debitorRel.contact:ADMIN]] + role:bookingItem.debitorRel.contact:REFERRER[[bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.refundBankAccount["`**parentServer.bookingItem.debitor.refundBankAccount**`"] + direction TB + style parentServer.bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.refundBankAccount:roles[ ] + style parentServer.bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.refundBankAccount:OWNER[[parentServer.bookingItem.debitor.refundBankAccount:OWNER]] + role:parentServer.bookingItem.debitor.refundBankAccount:ADMIN[[parentServer.bookingItem.debitor.refundBankAccount:ADMIN]] + role:parentServer.bookingItem.debitor.refundBankAccount:REFERRER[[parentServer.bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph bookingItem.debitor["`**bookingItem.debitor**`"] + direction TB + style bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph bookingItem.debitor.debitorRel.holderPerson["`**bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.holderPerson:OWNER[[bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitor.debitorRel.holderPerson:ADMIN[[bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.holderPerson:REFERRER[[bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel["`**bookingItem.debitor.debitorRel**`"] + direction TB + style bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel:roles[ ] + style bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel:OWNER[[bookingItem.debitor.debitorRel:OWNER]] + role:bookingItem.debitor.debitorRel:ADMIN[[bookingItem.debitor.debitorRel:ADMIN]] + role:bookingItem.debitor.debitorRel:AGENT[[bookingItem.debitor.debitorRel:AGENT]] + role:bookingItem.debitor.debitorRel:TENANT[[bookingItem.debitor.debitorRel:TENANT]] + end +end + +subgraph asset["`**asset**`"] + direction TB + style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph asset:roles[ ] + style asset:roles fill:#dd4901,stroke:white + + role:asset:OWNER[[asset:OWNER]] + role:asset:ADMIN[[asset:ADMIN]] + role:asset:TENANT[[asset:TENANT]] + end + + subgraph asset:permissions[ ] + style asset:permissions fill:#dd4901,stroke:white + + perm:asset:INSERT{{asset:INSERT}} + perm:asset:DELETE{{asset:DELETE}} + perm:asset:UPDATE{{asset:UPDATE}} + perm:asset:SELECT{{asset:SELECT}} + end +end + +subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +%% granting roles to roles +role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER +role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER +role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER +role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN +role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER +role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN +role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER +role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN +role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER +role:bookingItem:OWNER -.-> role:bookingItem:ADMIN +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN +role:bookingItem:ADMIN -.-> role:bookingItem:AGENT +role:bookingItem:AGENT -.-> role:bookingItem:TENANT +role:bookingItem:TENANT -.-> role:bookingItem.debitorRel:TENANT +role:bookingItem:ADMIN ==> role:asset:OWNER +role:asset:OWNER ==> role:asset:ADMIN +role:asset:ADMIN ==> role:asset:TENANT +role:asset:TENANT ==> role:bookingItem:TENANT + +%% granting permissions to roles +role:bookingItem:AGENT ==> perm:asset:INSERT +role:parentServer:ADMIN ==> perm:asset:INSERT +role:asset:OWNER ==> perm:asset:DELETE +role:asset:ADMIN ==> perm:asset:UPDATE +role:asset:TENANT ==> perm:asset:SELECT + +``` diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql index 8c689526..4924f25e 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql @@ -64,6 +64,7 @@ begin IF NEW.type = 'CLOUD_SERVER' THEN ELSIF NEW.type = 'MANAGED_SERVER' THEN ELSIF NEW.type = 'MANAGED_WEBSPACE' THEN + ELSE END IF; call leaveTriggerForObjectUuid(NEW.uuid); @@ -178,7 +179,7 @@ declare superObjectUuid uuid; begin -- check INSERT permission via direct foreign key: NEW.bookingItemUuid - if NEW.type in ('CLOUD_SERVER', 'MANAGED_SERVER', 'MANAGED_WEBSPACE') and hasInsertPermission(NEW.bookingItemUuid, 'hs_hosting_asset') then + if NEW.type in ('MANAGED_SERVER', 'CLOUD_SERVER', 'MANAGED_WEBSPACE') and hasInsertPermission(NEW.bookingItemUuid, 'hs_hosting_asset') then return NEW; end if; -- check INSERT permission via direct foreign key: NEW.parentAssetUuid