diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java index 3d948ef2..8bdb5c8b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java @@ -179,7 +179,9 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject { .createSubRole(TENANT, (with) -> { with.outgoingSubRole("debitorRel", TENANT); with.permission(SELECT); - }); + }) + + .limitDiagramTo("bookingItem", "debitorRel", "global"); } public static void main(String[] args) throws IOException { 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 0d7678e9..199e0e7b 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; @@ -156,9 +157,10 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject { dependsOnColumn("parentAssetUuid"), directlyFetchedByDependsOnColumn(), NULLABLE) - // TODO.rbac: implement multiple INSERT-rules, e.g. for Asset.bookingItem + Asset.parentAsset - //.toRole("parentServer", AGENT).grantPermission(INSERT) - ) + .toRole("parentServer", ADMIN).grantPermission(INSERT) + .toRole("bookingItem", AGENT).grantPermission(INSERT) + ), + inOtherCases(then -> {}) ) .createRole(OWNER, (with) -> { @@ -171,7 +173,9 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject { .createSubRole(TENANT, (with) -> { with.outgoingSubRole("bookingItem", TENANT); with.permission(SELECT); - }); + }) + + .limitDiagramTo("asset", "bookingItem", "bookingItem.debitorRel", "parentServer", "global"); } public static void main(String[] args) throws IOException { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index e8e90702..581e6bb7 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -19,7 +19,6 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.*; 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; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; 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 66ef1481..b3c37bad 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java @@ -1,12 +1,16 @@ package net.hostsharing.hsadminng.rbac.rbacdef; import java.util.Optional; +import java.util.Set; import java.util.function.BinaryOperator; import java.util.stream.Stream; +import static java.util.stream.Collectors.joining; import static net.hostsharing.hsadminng.rbac.rbacdef.PostgresTriggerReference.NEW; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.GUEST; import static net.hostsharing.hsadminng.rbac.rbacdef.StringWriter.with; import static org.apache.commons.lang3.StringUtils.capitalize; import static org.apache.commons.lang3.StringUtils.uncapitalize; @@ -22,194 +26,121 @@ public class InsertTriggerGenerator { } void generateTo(final StringWriter plPgSql) { - generateLiquibaseChangesetHeader(plPgSql); - generateGrantInsertRoleToExistingObjects(plPgSql); - generateInsertPermissionGrantTrigger(plPgSql); - generateInsertCheckTrigger(plPgSql); - plPgSql.writeLn("--//"); + if (isInsertPermissionGrantedToGlobalGuest()) { + // any user is allowed to insert new rows => no insert check needed + return; + } + + generateInsertGrants(plPgSql); + generateInsertPermissionChecks(plPgSql); } - private void generateLiquibaseChangesetHeader(final StringWriter plPgSql) { + private void generateInsertGrants(final StringWriter plPgSql) { + if (isInsertPermissionIsNotGrantedAtAll()) { + generateInsertPermissionTriggerAlwaysDisallow(plPgSql); + } else { + generateInsertPermissionGrants(plPgSql); + } + } + + private void generateInsertPermissionGrants(final StringWriter plPgSql) { plPgSql.writeLn(""" - -- ============================================================================ - --changeset ${liquibaseTagPrefix}-rbac-INSERT:1 endDelimiter:--// - -- ---------------------------------------------------------------------------- - """, + -- ============================================================================ + --changeset ${liquibaseTagPrefix}-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// + -- ---------------------------------------------------------------------------- + """, with("liquibaseTagPrefix", liquibaseTagPrefix)); - } - private void generateGrantInsertRoleToExistingObjects(final StringWriter plPgSql) { - getOptionalInsertSuperRole().ifPresent( superRoleDef -> { + getInsertGrants().forEach( g -> { plPgSql.writeLn(""" - /* - Creates INSERT INTO ${rawSubTableName} permissions for the related ${rawSuperTableName} rows. - */ - do language plpgsql $$ - declare - row ${rawSuperTableName}; - begin - call defineContext('create INSERT INTO ${rawSubTableName} permissions for the related ${rawSuperTableName} rows'); - - FOR row IN SELECT * FROM ${rawSuperTableName}${typeCondition} - LOOP - call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', '${rawSubTableName}'), - ${rawSuperRoleDescriptor}); - END LOOP; - END; - $$; - """, - with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()), - with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()), - with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, "row")), - with("typeCondition", superRoleDef.getEntityAlias().isCaseDependent() - ? "\n\t\t\tWHERE type = '${case}'".replace("${case}", superRoleDef.getEntityAlias().usingCase().value) - : "") - ); - }); - } + -- granting INSERT permission to ${rawSubTable} ---------------------------- + """, + with("rawSubTable", g.getSuperRoleDef().getEntityAlias().getRawTableName())); - private void generateInsertPermissionGrantTrigger(final StringWriter plPgSql) { - getOptionalInsertSuperRole().ifPresent( superRoleDef -> { - plPgSql.writeLn(""" + if (isGrantToADifferentTable(g)) { + plPgSql.writeLn( + """ + /* + Grants INSERT INTO ${rawSubTable} permissions to specified role of pre-existing ${rawSuperTable} rows. + */ + do language plpgsql $$ + declare + row ${rawSuperTable}; + begin + call defineContext('create INSERT INTO ${rawSubTable} permissions for pre-exising ${rawSuperTable} rows'); + + FOR row IN SELECT * FROM ${rawSuperTable} + ${whenCondition} + LOOP + call grantPermissionToRole( + createPermission(row.uuid, 'INSERT', '${rawSubTable}'), + ${superRoleRef}); + END LOOP; + end; + $$; + """, + with("whenCondition", g.getSuperRoleDef().getEntityAlias().isCaseDependent() + // 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("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, + -- because there cannot yet be any pre-existing rows in the same table yet. + """, + with("rawSuperTable", g.getSuperRoleDef().getEntityAlias().getRawTableName()), + with("rawSubTable", g.getPermDef().getEntityAlias().getRawTableName())); + } + + plPgSql.writeLn(""" /** - Adds ${rawSubTableName} INSERT permission to specified role of new ${rawSuperTableName} rows. + Grants ${rawSubTable} INSERT permission to specified role of new ${rawSuperTable} rows. */ - create or replace function ${rawSubTableName}_${rawSuperTableName}_insert_tf() + create or replace function new_${rawSubTable}_grants_insert_to_${rawSuperTable}_tf() returns trigger language plpgsql strict as $$ begin - ${typeConditionIf}call grantPermissionToRole( - createPermission(NEW.uuid, 'INSERT', '${rawSubTableName}'), - ${rawSuperRoleDescriptor});${typeConditionEndIf} + ${ifConditionThen} + call grantPermissionToRole( + createPermission(NEW.uuid, 'INSERT', '${rawSubTable}'), + ${superRoleRef}); + ${ifConditionEnd} return NEW; end; $$; - - -- z_... is to put it at the end of after insert triggers, to make sure the roles exist - create trigger z_${rawSubTableName}_${rawSuperTableName}_insert_tg - after insert on ${rawSuperTableName} + + -- z_... is to put it at the end of after insert triggers, to make sure the roles exist + create trigger z_new_${rawSubTable}_grants_insert_to_${rawSuperTable}_tg + after insert on ${rawSuperTable} for each row - execute procedure ${rawSubTableName}_${rawSuperTableName}_insert_tf(); + execute procedure new_${rawSubTable}_grants_insert_to_${rawSuperTable}_tf(); """, - with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()), - with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()), - with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, NEW.name())), - with("typeConditionIf", - superRoleDef.getEntityAlias().isCaseDependent() - ? "if NEW.type = '${case}' then\n\t\t".replace("${case}", superRoleDef.getEntityAlias().usingCase().value) - : ""), - with("typeConditionEndIf", superRoleDef.getEntityAlias().isCaseDependent() - ? "\n\tend if;" - : "") - ); + with("ifConditionThen", g.getSuperRoleDef().getEntityAlias().isCaseDependent() + // TODO.impl: .type needs to be dynamically generated + ? "if NEW.type = '" + g.getSuperRoleDef().getEntityAlias().usingCase().value + "' then" + : "-- unconditional for all rows in that table"), + with("ifConditionEnd", g.getSuperRoleDef().getEntityAlias().isCaseDependent() + ? "end if;" + : "-- end."), + with("superRoleRef", toRoleDescriptor(g.getSuperRoleDef(), NEW.name())), + with("rawSuperTable", g.getSuperRoleDef().getEntityAlias().getRawTableName()), + with("rawSubTable", g.getPermDef().getEntityAlias().getRawTableName())); + }); } - private void generateInsertCheckTrigger(final StringWriter plPgSql) { - getOptionalInsertGrant().ifPresentOrElse(g -> { - if (g.getSuperRoleDef().getEntityAlias().isGlobal()) { - switch (g.getSuperRoleDef().getRole()) { - case ADMIN -> { - generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql); - } - case GUEST -> { - // no permission check trigger generated, as anybody can insert rows into this table - } - default -> { - throw new IllegalArgumentException( - "invalid global role for INSERT permission: " + g.getSuperRoleDef().getRole()); - } - } - } else { - if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) { - generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(plPgSql, g); - } else { - generateInsertPermissionTriggerAllowByRoleOfIndirectForeignKey(plPgSql, g); - } - } - }, - () -> { - System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global:ADMIN"); - generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql); - }); - } - - private void generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) { + private void generateInsertPermissionTriggerAlwaysDisallow(final StringWriter plPgSql) { plPgSql.writeLn(""" - /** - 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. - */ - create or replace function ${rawSubTable}_insert_permission_missing_tf() - returns trigger - language plpgsql as $$ - begin - raise exception '[403] insert into ${rawSubTable} not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); - end; $$; + -- ============================================================================ + --changeset ${liquibaseTagPrefix}-rbac-ALWAYS-DISALLOW-INSERT:1 endDelimiter:--// + -- ---------------------------------------------------------------------------- + """, + with("liquibaseTagPrefix", liquibaseTagPrefix)); - create trigger ${rawSubTable}_insert_permission_check_tg - before insert on ${rawSubTable} - for each row - when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') ) - execute procedure ${rawSubTable}_insert_permission_missing_tf(); - """, - with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()), - with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName())); - } - - private void generateInsertPermissionTriggerAllowByRoleOfIndirectForeignKey( - final StringWriter plPgSql, - final RbacView.RbacGrantDefinition g) { - plPgSql.writeLn(""" - /** - Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}, - where the check is performed by an indirect role. - - An indirect role is a role which depends on an object uuid which is not a direct foreign key - of the source entity, but needs to be fetched via joined tables. - */ - create or replace function ${rawSubTable}_insert_permission_check_tf() - returns trigger - language plpgsql as $$ - - declare - superRoleObjectUuid uuid; - - begin - """, - with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); - plPgSql.chopEmptyLines(); - plPgSql.indented(2, () -> { - plPgSql.writeLn( - "superRoleObjectUuid := (" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ");\n" + - "assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null';", - with("columns", g.getSuperRoleDef().getEntityAlias().aliasName() + ".uuid"), - with("ref", NEW.name())); - }); - plPgSql.writeLn(); - plPgSql.writeLn(""" - if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', '${rawSubTable}') ) then - raise exception - '[403] insert into ${rawSubTable} not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); - end if; - return NEW; - 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())); - } - - private void generateInsertPermissionTriggerAllowOnlyGlobalAdmin(final StringWriter plPgSql) { plPgSql.writeLn(""" /** Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}, @@ -219,17 +150,129 @@ public class InsertTriggerGenerator { returns trigger language plpgsql as $$ begin - raise exception '[403] insert into ${rawSubTable} not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + raise exception '[403] insert into ${rawSubTable} not allowed regardless of current subject, no insert permissions grated at all'; end; $$; create trigger ${rawSubTable}_insert_permission_check_tg before insert on ${rawSubTable} for each row - when ( not isGlobalAdmin() ) execute procedure ${rawSubTable}_insert_permission_missing_tf(); """, with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); + + plPgSql.writeLn("--//"); + } + + private void generateInsertPermissionChecks(final StringWriter plPgSql) { + generateInsertPermissionsCheckHeader(plPgSql); + + plPgSql.indented(1, () -> { + getInsertGrants().forEach(g -> { + generateInsertPermissionChecksForSingleGrant(plPgSql, g); + }); + plPgSql.chopTail(" or\n"); + }); + + generateInsertPermissionsChecksFooter(plPgSql); + } + + private void generateInsertPermissionsCheckHeader(final StringWriter plPgSql) { + plPgSql.writeLn(""" + -- ============================================================================ + --changeset ${rawSubTable}-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// + -- ---------------------------------------------------------------------------- + + /** + Checks if the user respectively the assumed roles are allowed to insert a row to ${rawSubTable}. + */ + create or replace function ${rawSubTable}_insert_permission_check_tf() + returns trigger + language plpgsql as $$ + declare + superObjectUuid uuid; + begin + """, + with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); + plPgSql.chopEmptyLines(); + } + + private void generateInsertPermissionChecksForSingleGrant(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) { + final RbacView.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias(); + + final var caseCondition = g.isConditional() + ? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ") + : ""; + + if (g.getSuperRoleDef().isGlobal(GUEST)) { + plPgSql.writeLn( + """ + -- check INSERT INSERT permission for global anyone + if ${caseCondition}true then + return NEW; + end if; + """, + with("caseCondition", caseCondition)); + } else if (g.getSuperRoleDef().isGlobal(ADMIN)) { + plPgSql.writeLn( + """ + -- check INSERT INSERT if global ADMIN + if ${caseCondition}isGlobalAdmin() then + return NEW; + end if; + """, + with("caseCondition", caseCondition)); + } else if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) { + 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 ${caseCondition}hasInsertPermission(superObjectUuid, '${rawSubTable}') then + return NEW; + end if; + """, + with("caseCondition", caseCondition), + 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())); + } + } + + private void generateInsertPermissionsChecksFooter(final StringWriter plPgSql) { + plPgSql.writeLn(); + plPgSql.writeLn(""" + 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())); + } + + private String toStringList(final Set cases) { + return cases.stream().map(c -> "'" + c.value + "'").collect(joining(", ")); + } + + private boolean isGrantToADifferentTable(final RbacView.RbacGrantDefinition g) { + return !rbacDef.getRootEntityAlias().getRawTableName().equals(g.getSuperRoleDef().getEntityAlias().getRawTableName()); } private Stream getInsertGrants() { @@ -238,6 +281,15 @@ public class InsertTriggerGenerator { .filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT); } + private boolean isInsertPermissionIsNotGrantedAtAll() { + return getInsertGrants().findAny().isEmpty(); + } + + private boolean isInsertPermissionGrantedToGlobalGuest() { + return getInsertGrants().anyMatch(g -> + g.getSuperRoleDef().getEntityAlias().isGlobal() && g.getSuperRoleDef().getRole() == GUEST); + } + private Optional getOptionalInsertGrant() { return getInsertGrants() .reduce(singleton()); @@ -252,7 +304,8 @@ public class InsertTriggerGenerator { private static BinaryOperator singleton() { return (x, y) -> { if ( !x.equals(y) ) { - throw new IllegalStateException("only a single INSERT permission grant allowed"); + return x; + // throw new IllegalStateException("only a single INSERT permission grant allowed"); } return x; }; 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 b9b556a9..9b4d2bbb 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -25,6 +25,7 @@ import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.ROLE_TO_ROLE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH; import static org.apache.commons.collections4.SetUtils.hashSet; @@ -62,6 +63,7 @@ public class RbacView { private SQL orderBySqlExpression; private EntityAlias rootEntityAliasProxy; private RbacRoleDefinition previousRoleDef; + private Set limitDiagramToAliasNames; private final Map cases = new LinkedHashMap<>() { @Override public CaseDef put(final String key, final CaseDef value) { @@ -396,8 +398,7 @@ public class RbacView { new RbacRoleDefinition(findEntityAlias(mapper.map(roleDef.entityAlias.aliasName)), roleDef.role); }); copyOf(importedRbacView.getGrantDefs()).forEach(grantDef -> { - if ( grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE && - (grantDef.forCases == null || grantDef.matchesCase(forCase)) ) { + if ( grantDef.grantType() == ROLE_TO_ROLE && grantDef.matchesCase(forCase) ) { final var importedGrantDef = findOrCreateGrantDef( findRbacRole( mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName), @@ -499,6 +500,29 @@ public class RbacView { new RbacViewPostgresGenerator(this).generateToChangeLog(Path.of(OUTPUT_BASEDIR, baseFileName + ".sql")); } + public RbacView limitDiagramTo(final String... aliasNames) { + this.limitDiagramToAliasNames = Set.of(aliasNames); + return this; + } + + public boolean renderInDiagram(final EntityAlias ea) { + return limitDiagramToAliasNames == null || limitDiagramToAliasNames.contains(ea.aliasName()); + } + + public boolean renderInDiagram(final RbacGrantDefinition g) { + if ( limitDiagramToAliasNames == null ) { + return true; + } + return switch (g.grantType()) { + case ROLE_TO_USER -> + renderInDiagram(g.getSubRoleDef().getEntityAlias()); + case ROLE_TO_ROLE -> + renderInDiagram(g.getSuperRoleDef().getEntityAlias()) && renderInDiagram(g.getSubRoleDef().getEntityAlias()); + case PERM_TO_ROLE -> + renderInDiagram(g.getSuperRoleDef().getEntityAlias()) && renderInDiagram(g.getPermDef().getEntityAlias()); + }; + } + public class RbacGrantBuilder { private final RbacRoleDefinition superRoleDef; @@ -535,7 +559,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() { @@ -560,11 +584,13 @@ public class RbacView { register(this); } - public RbacGrantDefinition(final RbacPermissionDefinition permDef, final RbacRoleDefinition roleDef) { + public RbacGrantDefinition(final RbacPermissionDefinition permDef, final RbacRoleDefinition roleDef, + final CaseDef forCase) { this.userDef = null; this.subRoleDef = null; this.superRoleDef = roleDef; this.permDef = permDef; + this.forCases = forCase != null ? hashSet(forCase) : null; register(this); } @@ -584,7 +610,7 @@ public class RbacView { GrantType grantType() { return permDef != null ? PERM_TO_ROLE : userDef != null ? GrantType.ROLE_TO_USER - : GrantType.ROLE_TO_ROLE; + : ROLE_TO_ROLE; } boolean isAssumed() { @@ -602,9 +628,10 @@ public class RbacView { } boolean matchesCase(final ColumnValue requestedCase) { - final var noCasesDefined = forCases.isEmpty(); + final var noCasesDefined = forCases == null; final var generateForAllCases = requestedCase == null; - final boolean isGrantedForRequestedCase = forCases.stream().anyMatch(c -> c.isCase(requestedCase)); + final boolean isGrantedForRequestedCase = forCases == null || forCases.stream().anyMatch(c -> c.isCase(requestedCase)) + || forCases.stream().anyMatch(CaseDef::isDefaultCase) && !allCases.stream().anyMatch(c -> c.isCase(requestedCase)); return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; } @@ -676,7 +703,8 @@ public class RbacView { final String tableName; final boolean toCreate; - private RbacPermissionDefinition(final EntityAlias entityAlias, final Permission permission, final String tableName, final boolean toCreate) { + private RbacPermissionDefinition(final EntityAlias entityAlias, final Permission permission, final String tableName, + final boolean toCreate) { this.entityAlias = entityAlias; this.permission = permission; this.tableName = tableName; @@ -788,6 +816,10 @@ public class RbacView { public String toString() { return "role:" + entityAlias.aliasName + role; } + + public boolean isGlobal(final Role role) { + return entityAlias.isGlobal() && this.role == role; + } } public RbacUserReference findUserRef(final RbacUserReference.UserRole userRole) { @@ -842,19 +874,6 @@ public class RbacView { .orElseGet(() -> new RbacPermissionDefinition(entityAlias, perm, tableName, true)); // TODO: true => toCreate } - - RbacPermissionDefinition findRbacPerm(final EntityAlias entityAlias, final Permission perm) { - return findRbacPerm(entityAlias, perm, null); - } - - public RbacPermissionDefinition findRbacPerm(final String entityAliasName, final Permission perm, String tableName) { - return findRbacPerm(findEntityAlias(entityAliasName), perm, tableName); - } - - public RbacPermissionDefinition findRbacPerm(final String entityAliasName, final Permission perm) { - return findRbacPerm(findEntityAlias(entityAliasName), perm); - } - private RbacGrantDefinition findOrCreateGrantDef(final RbacRoleDefinition roleDefinition, final RbacUserReference user) { return grantDefs.stream() .filter(g -> g.subRoleDef == roleDefinition && g.userDef == user) @@ -866,7 +885,8 @@ public class RbacView { return grantDefs.stream() .filter(g -> g.permDef == permDef && g.superRoleDef == roleDef) .findFirst() - .orElseGet(() -> new RbacGrantDefinition(permDef, roleDef)); + .map(g -> g.forCase(processingCase)) + .orElseGet(() -> new RbacGrantDefinition(permDef, roleDef, processingCase)); } private RbacGrantDefinition findOrCreateGrantDef( diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index 3522a629..a820ad6a 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -5,7 +5,12 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef; import org.apache.commons.lang3.StringUtils; import java.nio.file.*; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static java.util.Comparator.comparing; import static java.util.stream.Collectors.joining; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.*; @@ -15,17 +20,28 @@ public class RbacViewMermaidFlowchartGenerator { public static final String HOSTSHARING_LIGHT_ORANGE = "#feb28c"; public static final String HOSTSHARING_DARK_BLUE = "#274d6e"; public static final String HOSTSHARING_LIGHT_BLUE = "#99bcdb"; - - // TODO.rbac: implement level limit for all renderable items and remove items which not part of a grant - private static final long MAX_LEVEL_TO_RENDER = 3; private final RbacView rbacDef; + private final List usedEntityAliases; + private final CaseDef forCase; private final StringWriter flowchart = new StringWriter(); public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef, final CaseDef forCase) { this.rbacDef = rbacDef; this.forCase = forCase; + + usedEntityAliases = rbacDef.getGrantDefs().stream() + .flatMap(g -> Stream.of( + g.getSuperRoleDef() != null ? g.getSuperRoleDef().getEntityAlias() : null, + g.getSubRoleDef() != null ? g.getSubRoleDef().getEntityAlias() : null, + g.getPermDef() != null ? g.getPermDef().getEntityAlias() : null)) + .filter(Objects::nonNull) + .sorted(comparing(RbacView.EntityAlias::aliasName)) + .distinct() + .filter(rbacDef::renderInDiagram) + .collect(Collectors.toList()); + flowchart.writeLn(""" %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB @@ -38,13 +54,18 @@ public class RbacViewMermaidFlowchartGenerator { this(rbacDef, null); } private void renderEntitySubgraphs() { - rbacDef.getEntityAliases().values().stream() + usedEntityAliases.stream() .filter(entityAlias -> !rbacDef.isEntityAliasProxy(entityAlias)) .filter(entityAlias -> !entityAlias.isPlaceholder()) + .filter(rbacDef::renderInDiagram) .forEach(this::renderEntitySubgraph); } private void renderEntitySubgraph(final RbacView.EntityAlias entity) { + if (!rbacDef.renderInDiagram(entity)) { + return; + } + final var color = rbacDef.isRootEntityAlias(entity) ? HOSTSHARING_DARK_ORANGE : entity.isSubEntity() ? HOSTSHARING_LIGHT_ORANGE : HOSTSHARING_LIGHT_BLUE; @@ -58,8 +79,7 @@ public class RbacViewMermaidFlowchartGenerator { .replace("%{strokeColor}", HOSTSHARING_DARK_BLUE )); flowchart.indented( () -> { - rbacDef.getEntityAliases().values().stream() - .filter(e -> e.level() <= MAX_LEVEL_TO_RENDER) + usedEntityAliases.stream() .filter(e -> e.aliasName().startsWith(entity.aliasName() + ":")) .forEach(this::renderEntitySubgraph); @@ -110,9 +130,9 @@ public class RbacViewMermaidFlowchartGenerator { private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) { final var grantsOfRequestedType = rbacDef.getGrantDefs().stream() - .filter(g -> g.level() <= MAX_LEVEL_TO_RENDER) .filter(g -> g.grantType() == grantType) - .filter(this::isToBeRenderedInThisGraph) + .filter(rbacDef::renderInDiagram) + .filter(this::isToBeRenderedForThisCase) .toList(); if ( !grantsOfRequestedType.isEmpty()) { flowchart.ensureSingleEmptyLine(); @@ -121,8 +141,8 @@ public class RbacViewMermaidFlowchartGenerator { } } - private boolean isToBeRenderedInThisGraph(final RbacView.RbacGrantDefinition g) { - if ( g.grantType() != ROLE_TO_ROLE ) + private boolean isToBeRenderedForThisCase(final RbacView.RbacGrantDefinition g) { + if ( g.grantType() == ROLE_TO_USER ) return true; if ( forCase == null && !g.isConditional() ) return true; 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/0-basis/008-raise-functions.sql b/src/main/resources/db/changelog/0-basis/008-raise-functions.sql new file mode 100644 index 00000000..15b34d7d --- /dev/null +++ b/src/main/resources/db/changelog/0-basis/008-raise-functions.sql @@ -0,0 +1,16 @@ +--liquibase formatted sql + +-- ============================================================================ +-- RAISE-FUNCTIONS +--changeset RAISE-FUNCTIONS:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +/* + Like RAISE EXCEPTION ... just as an expression instead of a statement. + */ +create or replace function raiseException(msg text) + returns varchar + language plpgsql as $$ +begin + raise exception using message = msg; +end; $$; +--// diff --git a/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql index 2b3147c9..cf49baee 100644 --- a/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql +++ b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql @@ -569,14 +569,14 @@ select exists( ); $$; -create or replace function hasInsertPermission(objectUuid uuid, forOp RbacOp, tableName text ) +create or replace function hasInsertPermission(objectUuid uuid, tableName text ) returns BOOL stable -- leakproof language plpgsql as $$ declare permissionUuid uuid; begin - permissionUuid = findPermissionId(objectUuid, forOp, tableName); + permissionUuid = findPermissionId(objectUuid, 'INSERT'::RbacOp, tableName); return permissionUuid is not null; end; $$; diff --git a/src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql b/src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql index 2f9ea4de..14767c4b 100644 --- a/src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql +++ b/src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql @@ -77,66 +77,82 @@ execute procedure insertTriggerForTestCustomer_tf(); -- ============================================================================ ---changeset test-customer-rbac-INSERT:1 endDelimiter:--// +--changeset test-customer-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to global ---------------------------- + /* - Creates INSERT INTO test_customer permissions for the related global rows. + Grants INSERT INTO test_customer permissions to specified role of pre-existing global rows. */ do language plpgsql $$ declare row global; begin - call defineContext('create INSERT INTO test_customer permissions for the related global rows'); + call defineContext('create INSERT INTO test_customer permissions for pre-exising global rows'); FOR row IN SELECT * FROM global + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'test_customer'), - globalADMIN()); + createPermission(row.uuid, 'INSERT', 'test_customer'), + globalADMIN()); END LOOP; - END; + end; $$; /** - Adds test_customer INSERT permission to specified role of new global rows. + Grants test_customer INSERT permission to specified role of new global rows. */ -create or replace function test_customer_global_insert_tf() +create or replace function new_test_customer_grants_insert_to_global_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'test_customer'), globalADMIN()); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_test_customer_global_insert_tg +create trigger z_new_test_customer_grants_insert_to_global_tg after insert on global for each row -execute procedure test_customer_global_insert_tf(); +execute procedure new_test_customer_grants_insert_to_global_tf(); + + +-- ============================================================================ +--changeset test_customer-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to test_customer, - where only global-admin has that permission. + Checks if the user respectively the assumed roles are allowed to insert a row to test_customer. */ -create or replace function test_customer_insert_permission_missing_tf() +create or replace function test_customer_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT INSERT if global ADMIN + if isGlobalAdmin() then + return NEW; + end if; + raise exception '[403] insert into test_customer not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger test_customer_insert_permission_check_tg before insert on test_customer for each row - when ( not isGlobalAdmin() ) - execute procedure test_customer_insert_permission_missing_tf(); + execute procedure test_customer_insert_permission_check_tf(); --// + -- ============================================================================ --changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -147,6 +163,7 @@ call generateRbacIdentityViewFromProjection('test_customer', $idName$); --// + -- ============================================================================ --changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.md b/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.md index 368cfe2f..af3a5f84 100644 --- a/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.md +++ b/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.md @@ -6,6 +6,19 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB +subgraph customer["`**customer**`"] + direction TB + style customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph customer:roles[ ] + style customer:roles fill:#99bcdb,stroke:white + + role:customer:OWNER[[customer:OWNER]] + role:customer:ADMIN[[customer:ADMIN]] + role:customer:TENANT[[customer:TENANT]] + end +end + subgraph package["`**package**`"] direction TB style package fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -28,19 +41,6 @@ subgraph package["`**package**`"] end end -subgraph customer["`**customer**`"] - direction TB - style customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph customer:roles[ ] - style customer:roles fill:#99bcdb,stroke:white - - role:customer:OWNER[[customer:OWNER]] - role:customer:ADMIN[[customer:ADMIN]] - role:customer:TENANT[[customer:TENANT]] - end -end - %% granting roles to roles role:global:ADMIN -.->|XX| role:customer:OWNER role:customer:OWNER -.-> role:customer:ADMIN diff --git a/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.sql b/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.sql index 3a4d5d8b..fd832ccf 100644 --- a/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.sql +++ b/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.sql @@ -142,68 +142,82 @@ execute procedure updateTriggerForTestPackage_tf(); -- ============================================================================ ---changeset test-package-rbac-INSERT:1 endDelimiter:--// +--changeset test-package-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to test_customer ---------------------------- + /* - Creates INSERT INTO test_package permissions for the related test_customer rows. + Grants INSERT INTO test_package permissions to specified role of pre-existing test_customer rows. */ do language plpgsql $$ declare row test_customer; begin - call defineContext('create INSERT INTO test_package permissions for the related test_customer rows'); + call defineContext('create INSERT INTO test_package permissions for pre-exising test_customer rows'); FOR row IN SELECT * FROM test_customer + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'test_package'), - testCustomerADMIN(row)); + createPermission(row.uuid, 'INSERT', 'test_package'), + testCustomerADMIN(row)); END LOOP; - END; + end; $$; /** - Adds test_package INSERT permission to specified role of new test_customer rows. + Grants test_package INSERT permission to specified role of new test_customer rows. */ -create or replace function test_package_test_customer_insert_tf() +create or replace function new_test_package_grants_insert_to_test_customer_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'test_package'), testCustomerADMIN(NEW)); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_test_package_test_customer_insert_tg +create trigger z_new_test_package_grants_insert_to_test_customer_tg after insert on test_customer for each row -execute procedure test_package_test_customer_insert_tf(); +execute procedure new_test_package_grants_insert_to_test_customer_tf(); + + +-- ============================================================================ +--changeset test_package-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to test_package, - 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 test_package. */ -create or replace function test_package_insert_permission_missing_tf() +create or replace function test_package_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT permission via direct foreign key: NEW.customerUuid + if hasInsertPermission(NEW.customerUuid, 'test_package') then + return NEW; + end if; + raise exception '[403] insert into test_package not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger test_package_insert_permission_check_tg before insert on test_package for each row - when ( not hasInsertPermission(NEW.customerUuid, 'INSERT', 'test_package') ) - execute procedure test_package_insert_permission_missing_tf(); + execute procedure test_package_insert_permission_check_tf(); --// + -- ============================================================================ --changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -214,6 +228,7 @@ call generateRbacIdentityViewFromProjection('test_package', $idName$); --// + -- ============================================================================ --changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.md b/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.md index d9b3748c..72693972 100644 --- a/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.md +++ b/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.md @@ -6,32 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph package.customer["`**package.customer**`"] - direction TB - style package.customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph package.customer:roles[ ] - style package.customer:roles fill:#99bcdb,stroke:white - - role:package.customer:OWNER[[package.customer:OWNER]] - role:package.customer:ADMIN[[package.customer:ADMIN]] - role:package.customer:TENANT[[package.customer:TENANT]] - end -end - -subgraph package["`**package**`"] - direction TB - style package fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph package:roles[ ] - style package:roles fill:#99bcdb,stroke:white - - role:package:OWNER[[package:OWNER]] - role:package:ADMIN[[package:ADMIN]] - role:package:TENANT[[package:TENANT]] - end -end - subgraph domain["`**domain**`"] direction TB style domain fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -53,6 +27,32 @@ subgraph domain["`**domain**`"] end end +subgraph package["`**package**`"] + direction TB + style package fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph package:roles[ ] + style package:roles fill:#99bcdb,stroke:white + + role:package:OWNER[[package:OWNER]] + role:package:ADMIN[[package:ADMIN]] + role:package:TENANT[[package:TENANT]] + end +end + +subgraph package.customer["`**package.customer**`"] + direction TB + style package.customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph package.customer:roles[ ] + style package.customer:roles fill:#99bcdb,stroke:white + + role:package.customer:OWNER[[package.customer:OWNER]] + role:package.customer:ADMIN[[package.customer:ADMIN]] + role:package.customer:TENANT[[package.customer:TENANT]] + end +end + %% granting roles to roles role:global:ADMIN -.->|XX| role:package.customer:OWNER role:package.customer:OWNER -.-> role:package.customer:ADMIN diff --git a/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql b/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql index de5faa78..d6f32001 100644 --- a/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql +++ b/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql @@ -141,68 +141,82 @@ execute procedure updateTriggerForTestDomain_tf(); -- ============================================================================ ---changeset test-domain-rbac-INSERT:1 endDelimiter:--// +--changeset test-domain-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to test_package ---------------------------- + /* - Creates INSERT INTO test_domain permissions for the related test_package rows. + Grants INSERT INTO test_domain permissions to specified role of pre-existing test_package rows. */ do language plpgsql $$ declare row test_package; begin - call defineContext('create INSERT INTO test_domain permissions for the related test_package rows'); + call defineContext('create INSERT INTO test_domain permissions for pre-exising test_package rows'); FOR row IN SELECT * FROM test_package + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'test_domain'), - testPackageADMIN(row)); + createPermission(row.uuid, 'INSERT', 'test_domain'), + testPackageADMIN(row)); END LOOP; - END; + end; $$; /** - Adds test_domain INSERT permission to specified role of new test_package rows. + Grants test_domain INSERT permission to specified role of new test_package rows. */ -create or replace function test_domain_test_package_insert_tf() +create or replace function new_test_domain_grants_insert_to_test_package_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'test_domain'), testPackageADMIN(NEW)); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_test_domain_test_package_insert_tg +create trigger z_new_test_domain_grants_insert_to_test_package_tg after insert on test_package for each row -execute procedure test_domain_test_package_insert_tf(); +execute procedure new_test_domain_grants_insert_to_test_package_tf(); + + +-- ============================================================================ +--changeset test_domain-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to test_domain, - 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 test_domain. */ -create or replace function test_domain_insert_permission_missing_tf() +create or replace function test_domain_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT permission via direct foreign key: NEW.packageUuid + if hasInsertPermission(NEW.packageUuid, 'test_domain') then + return NEW; + end if; + raise exception '[403] insert into test_domain not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger test_domain_insert_permission_check_tg before insert on test_domain for each row - when ( not hasInsertPermission(NEW.packageUuid, 'INSERT', 'test_domain') ) - execute procedure test_domain_insert_permission_missing_tf(); + execute procedure test_domain_insert_permission_check_tf(); --// + -- ============================================================================ --changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -213,6 +227,7 @@ call generateRbacIdentityViewFromProjection('test_domain', $idName$); --// + -- ============================================================================ --changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql b/src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql index 0f53b167..3bbf3ca2 100644 --- a/src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql @@ -76,49 +76,6 @@ execute procedure insertTriggerForHsOfficeContact_tf(); --// --- ============================================================================ ---changeset hs-office-contact-rbac-INSERT:1 endDelimiter:--// --- ---------------------------------------------------------------------------- - -/* - Creates INSERT INTO hs_office_contact permissions for the related global rows. - */ -do language plpgsql $$ - declare - row global; - begin - call defineContext('create INSERT INTO hs_office_contact permissions for the related global rows'); - - FOR row IN SELECT * FROM global - LOOP - call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_contact'), - globalGUEST()); - END LOOP; - END; -$$; - -/** - Adds hs_office_contact INSERT permission to specified role of new global rows. -*/ -create or replace function hs_office_contact_global_insert_tf() - returns trigger - language plpgsql - strict as $$ -begin - call grantPermissionToRole( - createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'), - globalGUEST()); - return NEW; -end; $$; - --- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_contact_global_insert_tg - after insert on global - for each row -execute procedure hs_office_contact_global_insert_tf(); ---// - -- ============================================================================ --changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -129,6 +86,7 @@ call generateRbacIdentityViewFromProjection('hs_office_contact', $idName$); --// + -- ============================================================================ --changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql b/src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql index 0d983725..bdaca63c 100644 --- a/src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql @@ -76,49 +76,6 @@ execute procedure insertTriggerForHsOfficePerson_tf(); --// --- ============================================================================ ---changeset hs-office-person-rbac-INSERT:1 endDelimiter:--// --- ---------------------------------------------------------------------------- - -/* - Creates INSERT INTO hs_office_person permissions for the related global rows. - */ -do language plpgsql $$ - declare - row global; - begin - call defineContext('create INSERT INTO hs_office_person permissions for the related global rows'); - - FOR row IN SELECT * FROM global - LOOP - call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_person'), - globalGUEST()); - END LOOP; - END; -$$; - -/** - Adds hs_office_person INSERT permission to specified role of new global rows. -*/ -create or replace function hs_office_person_global_insert_tf() - returns trigger - language plpgsql - strict as $$ -begin - call grantPermissionToRole( - createPermission(NEW.uuid, 'INSERT', 'hs_office_person'), - globalGUEST()); - return NEW; -end; $$; - --- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_person_global_insert_tg - after insert on global - for each row -execute procedure hs_office_person_global_insert_tf(); ---// - -- ============================================================================ --changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -129,6 +86,7 @@ call generateRbacIdentityViewFromProjection('hs_office_person', $idName$); --// + -- ============================================================================ --changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md index e5f608e8..0d944401 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md @@ -6,19 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph holderPerson["`**holderPerson**`"] - direction TB - style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph holderPerson:roles[ ] - style holderPerson:roles fill:#99bcdb,stroke:white - - role:holderPerson:OWNER[[holderPerson:OWNER]] - role:holderPerson:ADMIN[[holderPerson:ADMIN]] - role:holderPerson:REFERRER[[holderPerson:REFERRER]] - end -end - subgraph anchorPerson["`**anchorPerson**`"] direction TB style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -45,6 +32,19 @@ subgraph contact["`**contact**`"] end end +subgraph holderPerson["`**holderPerson**`"] + direction TB + style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph holderPerson:roles[ ] + style holderPerson:roles fill:#99bcdb,stroke:white + + role:holderPerson:OWNER[[holderPerson:OWNER]] + role:holderPerson:ADMIN[[holderPerson:ADMIN]] + role:holderPerson:REFERRER[[holderPerson:REFERRER]] + end +end + subgraph relation["`**relation**`"] direction TB style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index 4ff19e79..47d4d220 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -6,19 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph holderPerson["`**holderPerson**`"] - direction TB - style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph holderPerson:roles[ ] - style holderPerson:roles fill:#99bcdb,stroke:white - - role:holderPerson:OWNER[[holderPerson:OWNER]] - role:holderPerson:ADMIN[[holderPerson:ADMIN]] - role:holderPerson:REFERRER[[holderPerson:REFERRER]] - end -end - subgraph anchorPerson["`**anchorPerson**`"] direction TB style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -45,6 +32,19 @@ subgraph contact["`**contact**`"] end end +subgraph holderPerson["`**holderPerson**`"] + direction TB + style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph holderPerson:roles[ ] + style holderPerson:roles fill:#99bcdb,stroke:white + + role:holderPerson:OWNER[[holderPerson:OWNER]] + role:holderPerson:ADMIN[[holderPerson:ADMIN]] + role:holderPerson:REFERRER[[holderPerson:REFERRER]] + end +end + subgraph relation["`**relation**`"] direction TB style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index 15114d03..63c2061a 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -151,68 +151,82 @@ execute procedure updateTriggerForHsOfficeRelation_tf(); -- ============================================================================ ---changeset hs-office-relation-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-relation-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to hs_office_person ---------------------------- + /* - Creates INSERT INTO hs_office_relation permissions for the related hs_office_person rows. + Grants INSERT INTO hs_office_relation permissions to specified role of pre-existing hs_office_person rows. */ do language plpgsql $$ declare row hs_office_person; begin - call defineContext('create INSERT INTO hs_office_relation permissions for the related hs_office_person rows'); + call defineContext('create INSERT INTO hs_office_relation permissions for pre-exising hs_office_person rows'); FOR row IN SELECT * FROM hs_office_person + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_relation'), - hsOfficePersonADMIN(row)); + createPermission(row.uuid, 'INSERT', 'hs_office_relation'), + hsOfficePersonADMIN(row)); END LOOP; - END; + end; $$; /** - Adds hs_office_relation INSERT permission to specified role of new hs_office_person rows. + Grants hs_office_relation INSERT permission to specified role of new hs_office_person rows. */ -create or replace function hs_office_relation_hs_office_person_insert_tf() +create or replace function new_hs_office_relation_grants_insert_to_hs_office_person_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'), hsOfficePersonADMIN(NEW)); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_relation_hs_office_person_insert_tg +create trigger z_new_hs_office_relation_grants_insert_to_hs_office_person_tg after insert on hs_office_person for each row -execute procedure hs_office_relation_hs_office_person_insert_tf(); +execute procedure new_hs_office_relation_grants_insert_to_hs_office_person_tf(); + + +-- ============================================================================ +--changeset hs_office_relation-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_relation, - 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 hs_office_relation. */ -create or replace function hs_office_relation_insert_permission_missing_tf() +create or replace function hs_office_relation_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT permission via direct foreign key: NEW.anchorUuid + if hasInsertPermission(NEW.anchorUuid, 'hs_office_relation') then + return NEW; + end if; + raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_relation_insert_permission_check_tg before insert on hs_office_relation for each row - when ( not hasInsertPermission(NEW.anchorUuid, 'INSERT', 'hs_office_relation') ) - execute procedure hs_office_relation_insert_permission_missing_tf(); + execute procedure hs_office_relation_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -225,6 +239,7 @@ call generateRbacIdentityViewFromProjection('hs_office_relation', $idName$); --// + -- ============================================================================ --changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md index 3522b5a3..ecbe29de 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md @@ -6,19 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph partnerRel.contact["`**partnerRel.contact**`"] - direction TB - style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.contact:roles[ ] - style partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] - role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] - role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] - end -end - subgraph partner["`**partner**`"] direction TB style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -73,6 +60,19 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] end end +subgraph partnerRel.contact["`**partnerRel.contact**`"] + direction TB + style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph partnerRel.contact:roles[ ] + style partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] + role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] + role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] + end +end + subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] direction TB style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql index 7d263dbd..520ef180 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql @@ -154,66 +154,82 @@ execute procedure updateTriggerForHsOfficePartner_tf(); -- ============================================================================ ---changeset hs-office-partner-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-partner-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to global ---------------------------- + /* - Creates INSERT INTO hs_office_partner permissions for the related global rows. + Grants INSERT INTO hs_office_partner permissions to specified role of pre-existing global rows. */ do language plpgsql $$ declare row global; begin - call defineContext('create INSERT INTO hs_office_partner permissions for the related global rows'); + call defineContext('create INSERT INTO hs_office_partner permissions for pre-exising global rows'); FOR row IN SELECT * FROM global + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_partner'), - globalADMIN()); + createPermission(row.uuid, 'INSERT', 'hs_office_partner'), + globalADMIN()); END LOOP; - END; + end; $$; /** - Adds hs_office_partner INSERT permission to specified role of new global rows. + Grants hs_office_partner INSERT permission to specified role of new global rows. */ -create or replace function hs_office_partner_global_insert_tf() +create or replace function new_hs_office_partner_grants_insert_to_global_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'), globalADMIN()); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_partner_global_insert_tg +create trigger z_new_hs_office_partner_grants_insert_to_global_tg after insert on global for each row -execute procedure hs_office_partner_global_insert_tf(); +execute procedure new_hs_office_partner_grants_insert_to_global_tf(); + + +-- ============================================================================ +--changeset hs_office_partner-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_partner, - where only global-admin has that permission. + Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_partner. */ -create or replace function hs_office_partner_insert_permission_missing_tf() +create or replace function hs_office_partner_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT INSERT if global ADMIN + if isGlobalAdmin() then + return NEW; + end if; + raise exception '[403] insert into hs_office_partner not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + 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(); + execute procedure hs_office_partner_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -224,6 +240,7 @@ call generateRbacIdentityViewFromProjection('hs_office_partner', $idName$); --// + -- ============================================================================ --changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql index c99639bb..bf0fe164 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql @@ -58,79 +58,96 @@ execute procedure insertTriggerForHsOfficePartnerDetails_tf(); -- ============================================================================ ---changeset hs-office-partner-details-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-partner-details-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to global ---------------------------- + /* - Creates INSERT INTO hs_office_partner_details permissions for the related global rows. + Grants INSERT INTO hs_office_partner_details permissions to specified role of pre-existing global rows. */ do language plpgsql $$ declare row global; begin - call defineContext('create INSERT INTO hs_office_partner_details permissions for the related global rows'); + call defineContext('create INSERT INTO hs_office_partner_details permissions for pre-exising global rows'); FOR row IN SELECT * FROM global + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'), - globalADMIN()); + createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'), + globalADMIN()); END LOOP; - END; + end; $$; /** - Adds hs_office_partner_details INSERT permission to specified role of new global rows. + Grants hs_office_partner_details INSERT permission to specified role of new global rows. */ -create or replace function hs_office_partner_details_global_insert_tf() +create or replace function new_hs_office_partner_details_grants_insert_to_global_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'), globalADMIN()); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_partner_details_global_insert_tg +create trigger z_new_hs_office_partner_details_grants_insert_to_global_tg after insert on global for each row -execute procedure hs_office_partner_details_global_insert_tf(); +execute procedure new_hs_office_partner_details_grants_insert_to_global_tf(); + + +-- ============================================================================ +--changeset hs_office_partner_details-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details, - where only global-admin has that permission. + Checks if the user respectively the 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() +create or replace function hs_office_partner_details_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT INSERT if global ADMIN + if isGlobalAdmin() then + return NEW; + end if; + raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + 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(); + execute procedure hs_office_partner_details_insert_permission_check_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 as idName +call generateRbacIdentityViewFromQuery('hs_office_partner_details', + $idName$ + SELECT partnerDetails.uuid as uuid, partner_iv.idName 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$); + $idName$); --// + -- ============================================================================ --changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql index c12c4c88..724dd658 100644 --- a/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql @@ -76,49 +76,6 @@ execute procedure insertTriggerForHsOfficeBankAccount_tf(); --// --- ============================================================================ ---changeset hs-office-bankaccount-rbac-INSERT:1 endDelimiter:--// --- ---------------------------------------------------------------------------- - -/* - Creates INSERT INTO hs_office_bankaccount permissions for the related global rows. - */ -do language plpgsql $$ - declare - row global; - begin - call defineContext('create INSERT INTO hs_office_bankaccount permissions for the related global rows'); - - FOR row IN SELECT * FROM global - LOOP - call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_bankaccount'), - globalGUEST()); - END LOOP; - END; -$$; - -/** - Adds hs_office_bankaccount INSERT permission to specified role of new global rows. -*/ -create or replace function hs_office_bankaccount_global_insert_tf() - returns trigger - language plpgsql - strict as $$ -begin - call grantPermissionToRole( - createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'), - globalGUEST()); - return NEW; -end; $$; - --- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_bankaccount_global_insert_tg - after insert on global - for each row -execute procedure hs_office_bankaccount_global_insert_tf(); ---// - -- ============================================================================ --changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -129,6 +86,7 @@ call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$); --// + -- ============================================================================ --changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md index d6e546cf..ef8bc404 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md @@ -6,45 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] - direction TB - style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.anchorPerson:roles[ ] - style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]] - role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]] - role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]] - end -end - -subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] - direction TB - style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.holderPerson:roles[ ] - style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]] - role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]] - role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]] - end -end - -subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] - direction TB - style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.holderPerson:roles[ ] - style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]] - role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]] - role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]] - end -end - subgraph debitor["`**debitor**`"] direction TB style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -73,30 +34,16 @@ subgraph debitor["`**debitor**`"] end end -subgraph partnerRel["`**partnerRel**`"] +subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] direction TB - style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph partnerRel:roles[ ] - style partnerRel:roles fill:#99bcdb,stroke:white + subgraph debitorRel.anchorPerson:roles[ ] + style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - role:partnerRel:OWNER[[partnerRel:OWNER]] - role:partnerRel:ADMIN[[partnerRel:ADMIN]] - role:partnerRel:AGENT[[partnerRel:AGENT]] - role:partnerRel:TENANT[[partnerRel:TENANT]] - end -end - -subgraph partnerRel.contact["`**partnerRel.contact**`"] - direction TB - style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.contact:roles[ ] - style partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] - role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] - role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] + role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]] + role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]] + role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]] end end @@ -113,6 +60,33 @@ subgraph debitorRel.contact["`**debitorRel.contact**`"] end end +subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] + direction TB + style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph debitorRel.holderPerson:roles[ ] + style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]] + role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]] + role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]] + end +end + +subgraph partnerRel["`**partnerRel**`"] + direction TB + style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph partnerRel:roles[ ] + style partnerRel:roles fill:#99bcdb,stroke:white + + role:partnerRel:OWNER[[partnerRel:OWNER]] + role:partnerRel:ADMIN[[partnerRel:ADMIN]] + role:partnerRel:AGENT[[partnerRel:AGENT]] + role:partnerRel:TENANT[[partnerRel:TENANT]] + end +end + subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] direction TB style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -126,6 +100,32 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] end end +subgraph partnerRel.contact["`**partnerRel.contact**`"] + direction TB + style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph partnerRel.contact:roles[ ] + style partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] + role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] + role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] + end +end + +subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] + direction TB + style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph partnerRel.holderPerson:roles[ ] + style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]] + role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]] + role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]] + end +end + subgraph refundBankAccount["`**refundBankAccount**`"] direction TB style refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -149,6 +149,16 @@ role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER role:global:ADMIN -.-> role:debitorRel.contact:OWNER role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel:OWNER -.-> role:debitorRel:ADMIN +role:debitorRel:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:global:ADMIN -.-> role:refundBankAccount:OWNER role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql index 59ac43e8..12f4f09d 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql @@ -127,73 +127,89 @@ execute procedure updateTriggerForHsOfficeDebitor_tf(); -- ============================================================================ ---changeset hs-office-debitor-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-debitor-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to global ---------------------------- + /* - Creates INSERT INTO hs_office_debitor permissions for the related global rows. + Grants INSERT INTO hs_office_debitor permissions to specified role of pre-existing global rows. */ do language plpgsql $$ declare row global; begin - call defineContext('create INSERT INTO hs_office_debitor permissions for the related global rows'); + call defineContext('create INSERT INTO hs_office_debitor permissions for pre-exising global rows'); FOR row IN SELECT * FROM global + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_debitor'), - globalADMIN()); + createPermission(row.uuid, 'INSERT', 'hs_office_debitor'), + globalADMIN()); END LOOP; - END; + end; $$; /** - Adds hs_office_debitor INSERT permission to specified role of new global rows. + Grants hs_office_debitor INSERT permission to specified role of new global rows. */ -create or replace function hs_office_debitor_global_insert_tf() +create or replace function new_hs_office_debitor_grants_insert_to_global_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'), globalADMIN()); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_debitor_global_insert_tg +create trigger z_new_hs_office_debitor_grants_insert_to_global_tg after insert on global for each row -execute procedure hs_office_debitor_global_insert_tf(); +execute procedure new_hs_office_debitor_grants_insert_to_global_tf(); + + +-- ============================================================================ +--changeset hs_office_debitor-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_debitor, - where only global-admin has that permission. + Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_debitor. */ -create or replace function hs_office_debitor_insert_permission_missing_tf() +create or replace function hs_office_debitor_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT INSERT if global ADMIN + if isGlobalAdmin() then + return NEW; + end if; + raise exception '[403] insert into hs_office_debitor not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_debitor_insert_permission_check_tg before insert on hs_office_debitor for each row - when ( not isGlobalAdmin() ) - execute procedure hs_office_debitor_insert_permission_missing_tf(); + execute procedure hs_office_debitor_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call generateRbacIdentityViewFromQuery('hs_office_debitor', - $idName$ - SELECT debitor.uuid AS uuid, +call generateRbacIdentityViewFromQuery('hs_office_debitor', + $idName$ + SELECT debitor.uuid AS uuid, 'D-' || (SELECT partner.partnerNumber FROM hs_office_partner partner JOIN hs_office_relation partnerRel @@ -203,9 +219,10 @@ create trigger hs_office_debitor_insert_permission_check_tg WHERE debitorRel.uuid = debitor.debitorRelUuid) || debitorNumberSuffix as idName FROM hs_office_debitor AS debitor - $idName$); + $idName$); --// + -- ============================================================================ --changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md index 7791348c..d6b47c0e 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md @@ -19,16 +19,17 @@ subgraph bankAccount["`**bankAccount**`"] end end -subgraph debitorRel.contact["`**debitorRel.contact**`"] +subgraph debitorRel["`**debitorRel**`"] direction TB - style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph debitorRel.contact:roles[ ] - style debitorRel.contact:roles fill:#99bcdb,stroke:white + subgraph debitorRel:roles[ ] + style debitorRel:roles fill:#99bcdb,stroke:white - role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]] - role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]] - role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]] + role:debitorRel:OWNER[[debitorRel:OWNER]] + role:debitorRel:ADMIN[[debitorRel:ADMIN]] + role:debitorRel:AGENT[[debitorRel:AGENT]] + role:debitorRel:TENANT[[debitorRel:TENANT]] end end @@ -45,6 +46,19 @@ subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] end end +subgraph debitorRel.contact["`**debitorRel.contact**`"] + direction TB + style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph debitorRel.contact:roles[ ] + style debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]] + role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]] + role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]] + end +end + subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] direction TB style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -81,20 +95,6 @@ subgraph sepaMandate["`**sepaMandate**`"] end end -subgraph debitorRel["`**debitorRel**`"] - direction TB - style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel:roles[ ] - style debitorRel:roles fill:#99bcdb,stroke:white - - role:debitorRel:OWNER[[debitorRel:OWNER]] - role:debitorRel:ADMIN[[debitorRel:ADMIN]] - role:debitorRel:AGENT[[debitorRel:AGENT]] - role:debitorRel:TENANT[[debitorRel:TENANT]] - end -end - %% granting roles to users user:creator ==> role:sepaMandate:OWNER @@ -108,6 +108,16 @@ role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER role:global:ADMIN -.-> role:debitorRel.contact:OWNER role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel:OWNER -.-> role:debitorRel:ADMIN +role:debitorRel:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:global:ADMIN -.-> role:bankAccount:OWNER role:bankAccount:OWNER -.-> role:bankAccount:ADMIN role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql index 839c29f6..3fb20baf 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql @@ -102,78 +102,79 @@ execute procedure insertTriggerForHsOfficeSepaMandate_tf(); -- ============================================================================ ---changeset hs-office-sepamandate-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-sepamandate-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to hs_office_relation ---------------------------- + /* - Creates INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows. + Grants INSERT INTO hs_office_sepamandate permissions to specified role of pre-existing hs_office_relation rows. */ do language plpgsql $$ declare row hs_office_relation; begin - call defineContext('create INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows'); + call defineContext('create INSERT INTO hs_office_sepamandate permissions for pre-exising hs_office_relation rows'); FOR row IN SELECT * FROM hs_office_relation - WHERE type = 'DEBITOR' + WHERE type = 'DEBITOR' LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'), - hsOfficeRelationADMIN(row)); + createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'), + hsOfficeRelationADMIN(row)); END LOOP; - END; + end; $$; /** - Adds hs_office_sepamandate INSERT permission to specified role of new hs_office_relation rows. + Grants hs_office_sepamandate INSERT permission to specified role of new hs_office_relation rows. */ -create or replace function hs_office_sepamandate_hs_office_relation_insert_tf() +create or replace function new_hs_office_sepamandate_grants_insert_to_hs_office_relation_tf() returns trigger language plpgsql strict as $$ begin if NEW.type = 'DEBITOR' then - call grantPermissionToRole( + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_sepamandate'), hsOfficeRelationADMIN(NEW)); - end if; + end if; return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_sepamandate_hs_office_relation_insert_tg +create trigger z_new_hs_office_sepamandate_grants_insert_to_hs_office_relation_tg after insert on hs_office_relation for each row -execute procedure hs_office_sepamandate_hs_office_relation_insert_tf(); +execute procedure new_hs_office_sepamandate_grants_insert_to_hs_office_relation_tf(); + + +-- ============================================================================ +--changeset hs_office_sepamandate-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate, - where the check is performed by an indirect role. - - An indirect role is a role which depends on an object uuid which is not a direct foreign key - of the source entity, but needs to be fetched via joined tables. + Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_sepamandate. */ create or replace function hs_office_sepamandate_insert_permission_check_tf() returns trigger language plpgsql as $$ - declare - superRoleObjectUuid uuid; - + superObjectUuid uuid; begin - superRoleObjectUuid := (SELECT debitorRel.uuid - FROM hs_office_relation debitorRel - JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid - WHERE debitor.uuid = NEW.debitorUuid - ); - assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null'; - - if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_office_sepamandate') ) then - raise exception - '[403] insert into hs_office_sepamandate not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + -- check INSERT permission via indirect foreign key: NEW.debitorUuid + superObjectUuid := (SELECT debitorRel.uuid + FROM hs_office_relation debitorRel + JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid + WHERE debitor.uuid = NEW.debitorUuid + ); + assert superObjectUuid is not null, 'object uuid fetched depending on hs_office_sepamandate.debitorUuid must not be null, also check fetchSql in RBAC DSL'; + if hasInsertPermission(superObjectUuid, 'hs_office_sepamandate') then + return NEW; end if; - return NEW; + + raise exception '[403] insert into hs_office_sepamandate not allowed for current subjects % (%)', + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_sepamandate_insert_permission_check_tg @@ -182,18 +183,20 @@ create trigger hs_office_sepamandate_insert_permission_check_tg execute procedure hs_office_sepamandate_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call generateRbacIdentityViewFromQuery('hs_office_sepamandate', - $idName$ - select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName +call generateRbacIdentityViewFromQuery('hs_office_sepamandate', + $idName$ + select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName from hs_office_sepamandate sm join hs_office_bankaccount ba on ba.uuid = sm.bankAccountUuid - $idName$); + $idName$); --// + -- ============================================================================ --changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md index 9e5752b8..083e244e 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md @@ -6,33 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph partnerRel["`**partnerRel**`"] - direction TB - style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel:roles[ ] - style partnerRel:roles fill:#99bcdb,stroke:white - - role:partnerRel:OWNER[[partnerRel:OWNER]] - role:partnerRel:ADMIN[[partnerRel:ADMIN]] - role:partnerRel:AGENT[[partnerRel:AGENT]] - role:partnerRel:TENANT[[partnerRel:TENANT]] - end -end - -subgraph partnerRel.contact["`**partnerRel.contact**`"] - direction TB - style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.contact:roles[ ] - style partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] - role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] - role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] - end -end - subgraph membership["`**membership**`"] direction TB style membership fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -55,6 +28,20 @@ subgraph membership["`**membership**`"] end end +subgraph partnerRel["`**partnerRel**`"] + direction TB + style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph partnerRel:roles[ ] + style partnerRel:roles fill:#99bcdb,stroke:white + + role:partnerRel:OWNER[[partnerRel:OWNER]] + role:partnerRel:ADMIN[[partnerRel:ADMIN]] + role:partnerRel:AGENT[[partnerRel:AGENT]] + role:partnerRel:TENANT[[partnerRel:TENANT]] + end +end + subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] direction TB style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -68,6 +55,19 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] end end +subgraph partnerRel.contact["`**partnerRel.contact**`"] + direction TB + style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph partnerRel.contact:roles[ ] + style partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] + role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] + role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] + end +end + subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] direction TB style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql index 139a2294..bc998fa3 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql @@ -89,79 +89,96 @@ execute procedure insertTriggerForHsOfficeMembership_tf(); -- ============================================================================ ---changeset hs-office-membership-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-membership-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to global ---------------------------- + /* - Creates INSERT INTO hs_office_membership permissions for the related global rows. + Grants INSERT INTO hs_office_membership permissions to specified role of pre-existing global rows. */ do language plpgsql $$ declare row global; begin - call defineContext('create INSERT INTO hs_office_membership permissions for the related global rows'); + call defineContext('create INSERT INTO hs_office_membership permissions for pre-exising global rows'); FOR row IN SELECT * FROM global + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_membership'), - globalADMIN()); + createPermission(row.uuid, 'INSERT', 'hs_office_membership'), + globalADMIN()); END LOOP; - END; + end; $$; /** - Adds hs_office_membership INSERT permission to specified role of new global rows. + Grants hs_office_membership INSERT permission to specified role of new global rows. */ -create or replace function hs_office_membership_global_insert_tf() +create or replace function new_hs_office_membership_grants_insert_to_global_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'), globalADMIN()); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_membership_global_insert_tg +create trigger z_new_hs_office_membership_grants_insert_to_global_tg after insert on global for each row -execute procedure hs_office_membership_global_insert_tf(); +execute procedure new_hs_office_membership_grants_insert_to_global_tf(); + + +-- ============================================================================ +--changeset hs_office_membership-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_membership, - where only global-admin has that permission. + Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_membership. */ -create or replace function hs_office_membership_insert_permission_missing_tf() +create or replace function hs_office_membership_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT INSERT if global ADMIN + if isGlobalAdmin() then + return NEW; + end if; + raise exception '[403] insert into hs_office_membership not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_membership_insert_permission_check_tg before insert on hs_office_membership for each row - when ( not isGlobalAdmin() ) - execute procedure hs_office_membership_insert_permission_missing_tf(); + execute procedure hs_office_membership_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call generateRbacIdentityViewFromQuery('hs_office_membership', - $idName$ - SELECT m.uuid AS uuid, +call generateRbacIdentityViewFromQuery('hs_office_membership', + $idName$ + SELECT m.uuid AS uuid, 'M-' || p.partnerNumber || m.memberNumberSuffix as idName FROM hs_office_membership AS m JOIN hs_office_partner AS p ON p.uuid = m.partnerUuid - $idName$); + $idName$); --// + -- ============================================================================ --changeset hs-office-membership-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md index b38ad4a0..23103840 100644 --- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md @@ -6,32 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]] - role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]] - role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]] - end -end - -subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]] - role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]] - role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]] - end -end - subgraph coopSharesTransaction["`**coopSharesTransaction**`"] direction TB style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -72,6 +46,19 @@ subgraph membership.partnerRel["`**membership.partnerRel**`"] end end +subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]] + role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]] + role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]] + end +end + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] direction TB style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -85,6 +72,19 @@ subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] end end +subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]] + role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]] + role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]] + end +end + %% granting roles to roles role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql index f4856f0a..1270fd69 100644 --- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql @@ -65,68 +65,82 @@ execute procedure insertTriggerForHsOfficeCoopSharesTransaction_tf(); -- ============================================================================ ---changeset hs-office-coopsharestransaction-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-coopsharestransaction-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to hs_office_membership ---------------------------- + /* - Creates INSERT INTO hs_office_coopsharestransaction permissions for the related hs_office_membership rows. + Grants INSERT INTO hs_office_coopsharestransaction permissions to specified role of pre-existing hs_office_membership rows. */ do language plpgsql $$ declare row hs_office_membership; begin - call defineContext('create INSERT INTO hs_office_coopsharestransaction permissions for the related hs_office_membership rows'); + call defineContext('create INSERT INTO hs_office_coopsharestransaction permissions for pre-exising hs_office_membership rows'); FOR row IN SELECT * FROM hs_office_membership + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'), - hsOfficeMembershipADMIN(row)); + createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'), + hsOfficeMembershipADMIN(row)); END LOOP; - END; + end; $$; /** - Adds hs_office_coopsharestransaction INSERT permission to specified role of new hs_office_membership rows. + Grants hs_office_coopsharestransaction INSERT permission to specified role of new hs_office_membership rows. */ -create or replace function hs_office_coopsharestransaction_hs_office_membership_insert_tf() +create or replace function new_hs_office_coopsharestransaction_grants_insert_to_hs_office_membership_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_coopsharestransaction'), hsOfficeMembershipADMIN(NEW)); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_coopsharestransaction_hs_office_membership_insert_tg +create trigger z_new_hs_office_coopsharestransaction_grants_insert_to_hs_office_membership_tg after insert on hs_office_membership for each row -execute procedure hs_office_coopsharestransaction_hs_office_membership_insert_tf(); +execute procedure new_hs_office_coopsharestransaction_grants_insert_to_hs_office_membership_tf(); + + +-- ============================================================================ +--changeset hs_office_coopsharestransaction-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_coopsharestransaction, - 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 hs_office_coopsharestransaction. */ -create or replace function hs_office_coopsharestransaction_insert_permission_missing_tf() +create or replace function hs_office_coopsharestransaction_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT permission via direct foreign key: NEW.membershipUuid + if hasInsertPermission(NEW.membershipUuid, 'hs_office_coopsharestransaction') then + return NEW; + end if; + raise exception '[403] insert into hs_office_coopsharestransaction not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_coopsharestransaction_insert_permission_check_tg before insert on hs_office_coopsharestransaction for each row - when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopsharestransaction') ) - execute procedure hs_office_coopsharestransaction_insert_permission_missing_tf(); + execute procedure hs_office_coopsharestransaction_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-coopsharestransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -137,6 +151,7 @@ call generateRbacIdentityViewFromProjection('hs_office_coopsharestransaction', $idName$); --// + -- ============================================================================ --changeset hs-office-coopsharestransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md index 77de3dc2..de30185b 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md @@ -6,32 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]] - role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]] - role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]] - end -end - -subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]] - role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]] - role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]] - end -end - subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"] direction TB style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -72,6 +46,19 @@ subgraph membership.partnerRel["`**membership.partnerRel**`"] end end +subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]] + role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]] + role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]] + end +end + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] direction TB style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -85,6 +72,19 @@ subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] end end +subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]] + role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]] + role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]] + end +end + %% granting roles to roles role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql index df1fdd3b..ce9926b2 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql @@ -65,68 +65,82 @@ execute procedure insertTriggerForHsOfficeCoopAssetsTransaction_tf(); -- ============================================================================ ---changeset hs-office-coopassetstransaction-rbac-INSERT:1 endDelimiter:--// +--changeset hs-office-coopassetstransaction-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to hs_office_membership ---------------------------- + /* - Creates INSERT INTO hs_office_coopassetstransaction permissions for the related hs_office_membership rows. + Grants INSERT INTO hs_office_coopassetstransaction permissions to specified role of pre-existing hs_office_membership rows. */ do language plpgsql $$ declare row hs_office_membership; begin - call defineContext('create INSERT INTO hs_office_coopassetstransaction permissions for the related hs_office_membership rows'); + call defineContext('create INSERT INTO hs_office_coopassetstransaction permissions for pre-exising hs_office_membership rows'); FOR row IN SELECT * FROM hs_office_membership + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'), - hsOfficeMembershipADMIN(row)); + createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'), + hsOfficeMembershipADMIN(row)); END LOOP; - END; + end; $$; /** - Adds hs_office_coopassetstransaction INSERT permission to specified role of new hs_office_membership rows. + Grants hs_office_coopassetstransaction INSERT permission to specified role of new hs_office_membership rows. */ -create or replace function hs_office_coopassetstransaction_hs_office_membership_insert_tf() +create or replace function new_hs_office_coopassetstransaction_grants_insert_to_hs_office_membership_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_coopassetstransaction'), hsOfficeMembershipADMIN(NEW)); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_office_coopassetstransaction_hs_office_membership_insert_tg +create trigger z_new_hs_office_coopassetstransaction_grants_insert_to_hs_office_membership_tg after insert on hs_office_membership for each row -execute procedure hs_office_coopassetstransaction_hs_office_membership_insert_tf(); +execute procedure new_hs_office_coopassetstransaction_grants_insert_to_hs_office_membership_tf(); + + +-- ============================================================================ +--changeset hs_office_coopassetstransaction-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_office_coopassetstransaction, - 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 hs_office_coopassetstransaction. */ -create or replace function hs_office_coopassetstransaction_insert_permission_missing_tf() +create or replace function hs_office_coopassetstransaction_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT permission via direct foreign key: NEW.membershipUuid + if hasInsertPermission(NEW.membershipUuid, 'hs_office_coopassetstransaction') then + return NEW; + end if; + raise exception '[403] insert into hs_office_coopassetstransaction not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_coopassetstransaction_insert_permission_check_tg before insert on hs_office_coopassetstransaction for each row - when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopassetstransaction') ) - execute procedure hs_office_coopassetstransaction_insert_permission_missing_tf(); + execute procedure hs_office_coopassetstransaction_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-office-coopassetstransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- @@ -137,6 +151,7 @@ call generateRbacIdentityViewFromProjection('hs_office_coopassetstransaction', $idName$); --// + -- ============================================================================ --changeset hs-office-coopassetstransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.md b/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.md index 9f94aaa5..7ba21f5c 100644 --- a/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.md +++ b/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.md @@ -6,86 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph debitor.debitorRel.anchorPerson["`**debitor.debitorRel.anchorPerson**`"] - direction TB - style debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.debitorRel.anchorPerson:roles[ ] - style debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:debitor.debitorRel.anchorPerson:OWNER[[debitor.debitorRel.anchorPerson:OWNER]] - role:debitor.debitorRel.anchorPerson:ADMIN[[debitor.debitorRel.anchorPerson:ADMIN]] - role:debitor.debitorRel.anchorPerson:REFERRER[[debitor.debitorRel.anchorPerson:REFERRER]] - end -end - -subgraph debitor.debitorRel.holderPerson["`**debitor.debitorRel.holderPerson**`"] - direction TB - style debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.debitorRel.holderPerson:roles[ ] - style debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:debitor.debitorRel.holderPerson:OWNER[[debitor.debitorRel.holderPerson:OWNER]] - role:debitor.debitorRel.holderPerson:ADMIN[[debitor.debitorRel.holderPerson:ADMIN]] - role:debitor.debitorRel.holderPerson:REFERRER[[debitor.debitorRel.holderPerson:REFERRER]] - end -end - -subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] - direction TB - style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.anchorPerson:roles[ ] - style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]] - role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]] - role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]] - end -end - -subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] - direction TB - style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.holderPerson:roles[ ] - style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]] - role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]] - role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]] - end -end - -subgraph debitor.debitorRel["`**debitor.debitorRel**`"] - direction TB - style debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.debitorRel:roles[ ] - style debitor.debitorRel:roles fill:#99bcdb,stroke:white - - role:debitor.debitorRel:OWNER[[debitor.debitorRel:OWNER]] - role:debitor.debitorRel:ADMIN[[debitor.debitorRel:ADMIN]] - role:debitor.debitorRel:AGENT[[debitor.debitorRel:AGENT]] - role:debitor.debitorRel:TENANT[[debitor.debitorRel:TENANT]] - end -end - -subgraph debitor.partnerRel["`**debitor.partnerRel**`"] - direction TB - style debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.partnerRel:roles[ ] - style debitor.partnerRel:roles fill:#99bcdb,stroke:white - - role:debitor.partnerRel:OWNER[[debitor.partnerRel:OWNER]] - role:debitor.partnerRel:ADMIN[[debitor.partnerRel:ADMIN]] - role:debitor.partnerRel:AGENT[[debitor.partnerRel:AGENT]] - role:debitor.partnerRel:TENANT[[debitor.partnerRel:TENANT]] - end -end - subgraph bookingItem["`**bookingItem**`"] direction TB style bookingItem fill:#dd4901,stroke:#274d6e,stroke-width:8px @@ -109,89 +29,6 @@ subgraph bookingItem["`**bookingItem**`"] end end -subgraph debitor.partnerRel.contact["`**debitor.partnerRel.contact**`"] - direction TB - style debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.partnerRel.contact:roles[ ] - style debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:debitor.partnerRel.contact:OWNER[[debitor.partnerRel.contact:OWNER]] - role:debitor.partnerRel.contact:ADMIN[[debitor.partnerRel.contact:ADMIN]] - role:debitor.partnerRel.contact:REFERRER[[debitor.partnerRel.contact:REFERRER]] - end -end - -subgraph debitor.partnerRel.holderPerson["`**debitor.partnerRel.holderPerson**`"] - direction TB - style debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.partnerRel.holderPerson:roles[ ] - style debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:debitor.partnerRel.holderPerson:OWNER[[debitor.partnerRel.holderPerson:OWNER]] - role:debitor.partnerRel.holderPerson:ADMIN[[debitor.partnerRel.holderPerson:ADMIN]] - role:debitor.partnerRel.holderPerson:REFERRER[[debitor.partnerRel.holderPerson:REFERRER]] - end -end - -subgraph debitor["`**debitor**`"] - direction TB - style debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px -end - -subgraph debitor.refundBankAccount["`**debitor.refundBankAccount**`"] - direction TB - style debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.refundBankAccount:roles[ ] - style debitor.refundBankAccount:roles fill:#99bcdb,stroke:white - - role:debitor.refundBankAccount:OWNER[[debitor.refundBankAccount:OWNER]] - role:debitor.refundBankAccount:ADMIN[[debitor.refundBankAccount:ADMIN]] - role:debitor.refundBankAccount:REFERRER[[debitor.refundBankAccount:REFERRER]] - end -end - -subgraph debitor.partnerRel.anchorPerson["`**debitor.partnerRel.anchorPerson**`"] - direction TB - style debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.partnerRel.anchorPerson:roles[ ] - style debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:debitor.partnerRel.anchorPerson:OWNER[[debitor.partnerRel.anchorPerson:OWNER]] - role:debitor.partnerRel.anchorPerson:ADMIN[[debitor.partnerRel.anchorPerson:ADMIN]] - role:debitor.partnerRel.anchorPerson:REFERRER[[debitor.partnerRel.anchorPerson:REFERRER]] - end -end - -subgraph debitorRel.contact["`**debitorRel.contact**`"] - direction TB - style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.contact:roles[ ] - style debitorRel.contact:roles fill:#99bcdb,stroke:white - - role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]] - role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]] - role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]] - end -end - -subgraph debitor.debitorRel.contact["`**debitor.debitorRel.contact**`"] - direction TB - style debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitor.debitorRel.contact:roles[ ] - style debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white - - role:debitor.debitorRel.contact:OWNER[[debitor.debitorRel.contact:OWNER]] - role:debitor.debitorRel.contact:ADMIN[[debitor.debitorRel.contact:ADMIN]] - role:debitor.debitorRel.contact:REFERRER[[debitor.debitorRel.contact:REFERRER]] - end -end - subgraph debitorRel["`**debitorRel**`"] direction TB style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -207,51 +44,10 @@ subgraph debitorRel["`**debitorRel**`"] end %% granting roles to roles -role:global:ADMIN -.-> role:debitor.debitorRel.anchorPerson:OWNER -role:debitor.debitorRel.anchorPerson:OWNER -.-> role:debitor.debitorRel.anchorPerson:ADMIN -role:debitor.debitorRel.anchorPerson:ADMIN -.-> role:debitor.debitorRel.anchorPerson:REFERRER -role:global:ADMIN -.-> role:debitor.debitorRel.holderPerson:OWNER -role:debitor.debitorRel.holderPerson:OWNER -.-> role:debitor.debitorRel.holderPerson:ADMIN -role:debitor.debitorRel.holderPerson:ADMIN -.-> role:debitor.debitorRel.holderPerson:REFERRER -role:global:ADMIN -.-> role:debitor.debitorRel.contact:OWNER -role:debitor.debitorRel.contact:OWNER -.-> role:debitor.debitorRel.contact:ADMIN -role:debitor.debitorRel.contact:ADMIN -.-> role:debitor.debitorRel.contact:REFERRER -role:global:ADMIN -.-> role:debitor.refundBankAccount:OWNER -role:debitor.refundBankAccount:OWNER -.-> role:debitor.refundBankAccount:ADMIN -role:debitor.refundBankAccount:ADMIN -.-> role:debitor.refundBankAccount:REFERRER -role:debitor.refundBankAccount:ADMIN -.-> role:debitor.debitorRel:AGENT -role:debitor.debitorRel:AGENT -.-> role:debitor.refundBankAccount:REFERRER -role:global:ADMIN -.-> role:debitor.partnerRel.anchorPerson:OWNER -role:debitor.partnerRel.anchorPerson:OWNER -.-> role:debitor.partnerRel.anchorPerson:ADMIN -role:debitor.partnerRel.anchorPerson:ADMIN -.-> role:debitor.partnerRel.anchorPerson:REFERRER -role:global:ADMIN -.-> role:debitor.partnerRel.holderPerson:OWNER -role:debitor.partnerRel.holderPerson:OWNER -.-> role:debitor.partnerRel.holderPerson:ADMIN -role:debitor.partnerRel.holderPerson:ADMIN -.-> role:debitor.partnerRel.holderPerson:REFERRER -role:global:ADMIN -.-> role:debitor.partnerRel.contact:OWNER -role:debitor.partnerRel.contact:OWNER -.-> role:debitor.partnerRel.contact:ADMIN -role:debitor.partnerRel.contact:ADMIN -.-> role:debitor.partnerRel.contact:REFERRER -role:global:ADMIN -.-> role:debitor.partnerRel:OWNER -role:debitor.partnerRel:OWNER -.-> role:debitor.partnerRel:ADMIN -role:debitor.partnerRel:ADMIN -.-> role:debitor.partnerRel:AGENT -role:debitor.partnerRel:AGENT -.-> role:debitor.partnerRel:TENANT -role:debitor.partnerRel.contact:ADMIN -.-> role:debitor.partnerRel:TENANT -role:debitor.partnerRel:TENANT -.-> role:debitor.partnerRel.anchorPerson:REFERRER -role:debitor.partnerRel:TENANT -.-> role:debitor.partnerRel.holderPerson:REFERRER -role:debitor.partnerRel:TENANT -.-> role:debitor.partnerRel.contact:REFERRER -role:debitor.partnerRel.anchorPerson:ADMIN -.-> role:debitor.partnerRel:OWNER -role:debitor.partnerRel.holderPerson:ADMIN -.-> role:debitor.partnerRel:AGENT -role:debitor.partnerRel:ADMIN -.-> role:debitor.debitorRel:ADMIN -role:debitor.partnerRel:AGENT -.-> role:debitor.debitorRel:AGENT -role:debitor.debitorRel:AGENT -.-> role:debitor.partnerRel:TENANT -role:global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER -role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN -role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER -role:global:ADMIN -.-> role:debitorRel.holderPerson:OWNER -role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER -role:global:ADMIN -.-> role:debitorRel.contact:OWNER -role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN -role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel:OWNER -.-> role:debitorRel:ADMIN +role:debitorRel:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel:AGENT -.-> role:debitorRel:TENANT role:debitorRel:AGENT ==> role:bookingItem:OWNER role:bookingItem:OWNER ==> role:bookingItem:ADMIN role:debitorRel:AGENT ==> role:bookingItem:ADMIN diff --git a/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.sql b/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.sql index 5b40e779..e26edbbb 100644 --- a/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.sql +++ b/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.sql @@ -98,78 +98,79 @@ execute procedure insertTriggerForHsBookingItem_tf(); -- ============================================================================ ---changeset hs-booking-item-rbac-INSERT:1 endDelimiter:--// +--changeset hs-booking-item-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to hs_office_relation ---------------------------- + /* - Creates INSERT INTO hs_booking_item permissions for the related hs_office_relation rows. + Grants INSERT INTO hs_booking_item permissions to specified role of pre-existing hs_office_relation rows. */ do language plpgsql $$ declare row hs_office_relation; begin - call defineContext('create INSERT INTO hs_booking_item permissions for the related hs_office_relation rows'); + call defineContext('create INSERT INTO hs_booking_item permissions for pre-exising hs_office_relation rows'); FOR row IN SELECT * FROM hs_office_relation - WHERE type = 'DEBITOR' + WHERE type = 'DEBITOR' LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_booking_item'), - hsOfficeRelationADMIN(row)); + createPermission(row.uuid, 'INSERT', 'hs_booking_item'), + hsOfficeRelationADMIN(row)); END LOOP; - END; + end; $$; /** - Adds hs_booking_item INSERT permission to specified role of new hs_office_relation rows. + Grants hs_booking_item INSERT permission to specified role of new hs_office_relation rows. */ -create or replace function hs_booking_item_hs_office_relation_insert_tf() +create or replace function new_hs_booking_item_grants_insert_to_hs_office_relation_tf() returns trigger language plpgsql strict as $$ begin if NEW.type = 'DEBITOR' then - call grantPermissionToRole( + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'), hsOfficeRelationADMIN(NEW)); - end if; + end if; return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_booking_item_hs_office_relation_insert_tg +create trigger z_new_hs_booking_item_grants_insert_to_hs_office_relation_tg after insert on hs_office_relation for each row -execute procedure hs_booking_item_hs_office_relation_insert_tf(); +execute procedure new_hs_booking_item_grants_insert_to_hs_office_relation_tf(); + + +-- ============================================================================ +--changeset hs_booking_item-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- /** - Checks if the user or assumed roles are allowed to insert a row to hs_booking_item, - where the check is performed by an indirect role. - - An indirect role is a role which depends on an object uuid which is not a direct foreign key - of the source entity, but needs to be fetched via joined tables. + Checks if the user respectively the assumed roles are allowed to insert a row to hs_booking_item. */ create or replace function hs_booking_item_insert_permission_check_tf() returns trigger language plpgsql as $$ - declare - superRoleObjectUuid uuid; - + superObjectUuid uuid; begin - superRoleObjectUuid := (SELECT debitorRel.uuid - FROM hs_office_relation debitorRel - JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid - WHERE debitor.uuid = NEW.debitorUuid - ); - assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null'; - - if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_booking_item') ) then - raise exception - '[403] insert into hs_booking_item not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + -- check INSERT permission via indirect foreign key: NEW.debitorUuid + superObjectUuid := (SELECT debitorRel.uuid + FROM hs_office_relation debitorRel + JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid + WHERE debitor.uuid = NEW.debitorUuid + ); + assert superObjectUuid is not null, 'object uuid fetched depending on hs_booking_item.debitorUuid must not be null, also check fetchSql in RBAC DSL'; + if hasInsertPermission(superObjectUuid, 'hs_booking_item') then + return NEW; end if; - return NEW; + + raise exception '[403] insert into hs_booking_item not allowed for current subjects % (%)', + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_booking_item_insert_permission_check_tg @@ -178,18 +179,20 @@ create trigger hs_booking_item_insert_permission_check_tg execute procedure hs_booking_item_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-booking-item-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call generateRbacIdentityViewFromQuery('hs_booking_item', - $idName$ - SELECT bookingItem.uuid as uuid, debitorIV.idName || '-' || cleanIdentifier(bookingItem.caption) as idName +call generateRbacIdentityViewFromQuery('hs_booking_item', + $idName$ + SELECT bookingItem.uuid as uuid, debitorIV.idName || '-' || cleanIdentifier(bookingItem.caption) as idName FROM hs_booking_item bookingItem JOIN hs_office_debitor_iv debitorIV ON debitorIV.uuid = bookingItem.debitorUuid - $idName$); + $idName$); --// + -- ============================================================================ --changeset hs-booking-item-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql index b827eea8..496c953c 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql @@ -34,6 +34,55 @@ create table if not exists hs_hosting_asset --// +-- ============================================================================ +--changeset hosting-asset-HIERARCHY-CHECK:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +create or replace function hs_hosting_asset_type_hierarchy_check_tf() + returns trigger + language plpgsql as $$ +declare + actualParentType HsHostingAssetType; + expectedParentType HsHostingAssetType; +begin + if NEW.parentAssetUuid is not null then + actualParentType := (select type + from hs_hosting_asset + where NEW.parentAssetUuid = uuid); + end if; + + expectedParentType := (select case NEW.type + when 'CLOUD_SERVER' then null + when 'MANAGED_SERVER' then null + when 'MANAGED_WEBSPACE' then 'MANAGED_SERVER' + when 'UNIX_USER' then 'MANAGED_WEBSPACE' + when 'DOMAIN_SETUP' then 'UNIX_USER' + when 'EMAIL_ALIAS' then 'MANAGED_WEBSPACE' + when 'EMAIL_ADDRESS' then 'DOMAIN_SETUP' + when 'PGSQL_USER' then 'MANAGED_WEBSPACE' + when 'PGSQL_DATABASE' then 'MANAGED_WEBSPACE' + when 'MARIADB_USER' then 'MANAGED_WEBSPACE' + when 'MARIADB_DATABASE' then 'MANAGED_WEBSPACE' + else raiseException(format('[400] unknown asset type %s', NEW.type::text)) + end); + + if expectedParentType is not null and actualParentType is null then + raise exception '[400] % must have % as parent, but got ', + NEW.type, expectedParentType; + elsif expectedParentType is not null and actualParentType <> expectedParentType then + raise exception '[400] % must have % as parent, but got %s', + NEW.type, expectedParentType, actualParentType; + end if; + return NEW; +end; $$; + +create trigger hs_hosting_asset_type_hierarchy_check_tg + before insert on hs_hosting_asset + for each row + execute procedure hs_hosting_asset_type_hierarchy_check_tf(); +--// + + -- ============================================================================ --changeset hs-hosting-asset-MAIN-TABLE-JOURNAL:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md index 3bc75f3b..65ae6608 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md @@ -6,385 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{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 -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 @@ -407,41 +28,50 @@ subgraph asset["`**asset**`"] end end -subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] +subgraph bookingItem["`**bookingItem**`"] direction TB - style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + style bookingItem 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 + subgraph bookingItem:roles[ ] + style bookingItem: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]] + role:bookingItem:OWNER[[bookingItem:OWNER]] + role:bookingItem:ADMIN[[bookingItem:ADMIN]] + role:bookingItem:AGENT[[bookingItem:AGENT]] + role:bookingItem:TENANT[[bookingItem:TENANT]] + 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["`**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 %% 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:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER +role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN +role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER role:bookingItem:OWNER -.-> role:bookingItem:ADMIN role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md index aa856ea9..773ae411 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md @@ -6,385 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{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 -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 @@ -407,41 +28,50 @@ subgraph asset["`**asset**`"] end end -subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] +subgraph bookingItem["`**bookingItem**`"] direction TB - style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + style bookingItem 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 + subgraph bookingItem:roles[ ] + style bookingItem: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]] + role:bookingItem:OWNER[[bookingItem:OWNER]] + role:bookingItem:ADMIN[[bookingItem:ADMIN]] + role:bookingItem:AGENT[[bookingItem:AGENT]] + role:bookingItem:TENANT[[bookingItem:TENANT]] + 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["`**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 %% 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:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER +role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN +role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER role:bookingItem:OWNER -.-> role:bookingItem:ADMIN role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md index 1b01c8ff..e9b929a9 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md @@ -6,385 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua %%{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 -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 @@ -407,53 +28,56 @@ subgraph asset["`**asset**`"] end end -subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] +subgraph bookingItem["`**bookingItem**`"] direction TB - style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + style bookingItem 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 + subgraph bookingItem:roles[ ] + style bookingItem: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]] + role:bookingItem:OWNER[[bookingItem:OWNER]] + role:bookingItem:ADMIN[[bookingItem:ADMIN]] + role:bookingItem:AGENT[[bookingItem:AGENT]] + role:bookingItem:TENANT[[bookingItem:TENANT]] + 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["`**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 %% 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:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER +role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN +role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT 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:parentServer.bookingItem.debitorRel:AGENT -.-> role:parentServer.bookingItem:OWNER -role:parentServer.bookingItem:OWNER -.-> role:parentServer.bookingItem:ADMIN -role:parentServer.bookingItem.debitorRel:AGENT -.-> role:parentServer.bookingItem:ADMIN -role:parentServer.bookingItem:ADMIN -.-> role:parentServer.bookingItem:AGENT -role:parentServer.bookingItem:AGENT -.-> role:parentServer.bookingItem:TENANT -role:parentServer.bookingItem:TENANT -.-> role:parentServer.bookingItem.debitorRel:TENANT role:bookingItem:ADMIN ==> role:asset:OWNER role:asset:OWNER ==> role:asset:ADMIN role:asset:ADMIN ==> role:asset:TENANT @@ -461,6 +85,7 @@ 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.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..cbbd80c0 --- /dev/null +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md @@ -0,0 +1,91 @@ +### rbac asset inOtherCases + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +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 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 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["`**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 + +%% granting roles to roles +role:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER +role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN +role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT +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: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 bc6939db..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); @@ -90,80 +91,126 @@ execute procedure insertTriggerForHsHostingAsset_tf(); -- ============================================================================ ---changeset hs-hosting-asset-rbac-INSERT:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--// -- ---------------------------------------------------------------------------- +-- granting INSERT permission to hs_booking_item ---------------------------- + /* - Creates INSERT INTO hs_hosting_asset permissions for the related hs_booking_item rows. + Grants INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_booking_item rows. */ do language plpgsql $$ declare row hs_booking_item; begin - call defineContext('create INSERT INTO hs_hosting_asset permissions for the related hs_booking_item rows'); + call defineContext('create INSERT INTO hs_hosting_asset permissions for pre-exising hs_booking_item rows'); FOR row IN SELECT * FROM hs_booking_item + -- unconditional for all rows in that table LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_hosting_asset'), - hsBookingItemAGENT(row)); + createPermission(row.uuid, 'INSERT', 'hs_hosting_asset'), + hsBookingItemAGENT(row)); END LOOP; - END; + end; $$; /** - Adds hs_hosting_asset INSERT permission to specified role of new hs_booking_item rows. + Grants hs_hosting_asset INSERT permission to specified role of new hs_booking_item rows. */ -create or replace function hs_hosting_asset_hs_booking_item_insert_tf() +create or replace function new_hs_hosting_asset_grants_insert_to_hs_booking_item_tf() returns trigger language plpgsql strict as $$ begin - call grantPermissionToRole( + -- unconditional for all rows in that table + call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_hosting_asset'), hsBookingItemAGENT(NEW)); + -- end. return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_hosting_asset_hs_booking_item_insert_tg +create trigger z_new_hs_hosting_asset_grants_insert_to_hs_booking_item_tg after insert on hs_booking_item for each row -execute procedure hs_hosting_asset_hs_booking_item_insert_tf(); +execute procedure new_hs_hosting_asset_grants_insert_to_hs_booking_item_tf(); + +-- granting INSERT permission to hs_hosting_asset ---------------------------- + +-- Granting INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_hosting_asset rows slipped, +-- because there cannot yet be any pre-existing rows in the same table yet. /** - Checks if the user or assumed roles are allowed to insert a row to hs_hosting_asset, - 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. + Grants hs_hosting_asset INSERT permission to specified role of new hs_hosting_asset rows. */ -create or replace function hs_hosting_asset_insert_permission_missing_tf() +create or replace function new_hs_hosting_asset_grants_insert_to_hs_hosting_asset_tf() + returns trigger + language plpgsql + strict as $$ +begin + if NEW.type = 'MANAGED_SERVER' then + call grantPermissionToRole( + createPermission(NEW.uuid, 'INSERT', 'hs_hosting_asset'), + hsHostingAssetADMIN(NEW)); + end if; + return NEW; +end; $$; + +-- z_... is to put it at the end of after insert triggers, to make sure the roles exist +create trigger z_new_hs_hosting_asset_grants_insert_to_hs_hosting_asset_tg + after insert on hs_hosting_asset + for each row +execute procedure new_hs_hosting_asset_grants_insert_to_hs_hosting_asset_tf(); + + +-- ============================================================================ +--changeset hs_hosting_asset-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +/** + Checks if the user respectively the assumed roles are allowed to insert a row to hs_hosting_asset. +*/ +create or replace function hs_hosting_asset_insert_permission_check_tf() returns trigger language plpgsql as $$ +declare + superObjectUuid uuid; begin + -- check INSERT permission via direct foreign key: NEW.bookingItemUuid + 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 + if NEW.type in ('MANAGED_WEBSPACE') and hasInsertPermission(NEW.parentAssetUuid, 'hs_hosting_asset') then + return NEW; + end if; + raise exception '[403] insert into hs_hosting_asset not allowed for current subjects % (%)', - currentSubjects(), currentSubjectsUuids(); + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_hosting_asset_insert_permission_check_tg before insert on hs_hosting_asset for each row - when ( not hasInsertPermission(NEW.bookingItemUuid, 'INSERT', 'hs_hosting_asset') ) - execute procedure hs_hosting_asset_insert_permission_missing_tf(); + execute procedure hs_hosting_asset_insert_permission_check_tf(); --// + -- ============================================================================ --changeset hs-hosting-asset-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call generateRbacIdentityViewFromQuery('hs_hosting_asset', - $idName$ - SELECT asset.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(asset.identifier) as idName +call generateRbacIdentityViewFromQuery('hs_hosting_asset', + $idName$ + SELECT asset.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(asset.identifier) as idName FROM hs_hosting_asset asset JOIN hs_booking_item_iv bookingItemIV ON bookingItemIV.uuid = asset.bookingItemUuid - $idName$); + $idName$); --// + -- ============================================================================ --changeset hs-hosting-asset-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql index 1e840acd..519ef395 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql @@ -18,6 +18,7 @@ declare currentTask varchar; relatedDebitor hs_office_debitor; relatedBookingItem hs_booking_item; + managedServerUuid uuid; begin currentTask := 'creating hosting-asset test-data ' || givenPartnerNumber::text || givenDebitorSuffix; call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); @@ -33,14 +34,15 @@ begin from hs_booking_item item where item.debitoruuid = relatedDebitor.uuid and item.caption = 'some PrivateCloud'; + select uuid_generate_v4() into managedServerUuid; raise notice 'creating test hosting-asset: %', givenPartnerNumber::text || givenDebitorSuffix::text; raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; insert - into hs_hosting_asset (uuid, bookingitemuuid, type, identifier, caption, config) - values (uuid_generate_v4(), relatedBookingItem.uuid, 'MANAGED_SERVER'::HsHostingAssetType, 'vm10' || givenDebitorSuffix, 'some ManagedServer', '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedBookingItem.uuid, 'CLOUD_SERVER'::HsHostingAssetType, 'vm20' || givenDebitorSuffix, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedBookingItem.uuid, 'MANAGED_WEBSPACE'::HsHostingAssetType, givenWebspacePrefix || '01', 'some Webspace', '{ "RAM": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb); + into hs_hosting_asset (uuid, bookingitemuuid, type, parentAssetUuid, identifier, caption, config) + values (managedServerUuid, relatedBookingItem.uuid, 'MANAGED_SERVER', null, 'vm10' || givenDebitorSuffix, 'some ManagedServer', '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), + (uuid_generate_v4(), relatedBookingItem.uuid, 'CLOUD_SERVER', null, 'vm20' || givenDebitorSuffix, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), + (uuid_generate_v4(), relatedBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, givenWebspacePrefix || '01', 'some Webspace', '{ "RAM": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb); end; $$; --// diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 7be8f944..90cbdcc2 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -13,6 +13,8 @@ databaseChangeLog: file: db/changelog/0-basis/006-numeric-hash-functions.sql - include: file: db/changelog/0-basis/007-table-columns.sql + - include: + file: db/changelog/0-basis/008-raise-functions.sql - include: file: db/changelog/0-basis/009-check-environment.sql - include: diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java index 3124ac39..6f992726 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java @@ -68,12 +68,13 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu // given context("superuser-alex@hostsharing.net"); final var count = assetRepo.count(); - final var givenBookingItem = givenBookingItem("First", "some CloudServer"); + final var givenManagedServer = givenManagedServer("First", "some ManagedServer"); // when final var result = attempt(em, () -> { final var newAsset = HsHostingAssetEntity.builder() - .bookingItem(givenBookingItem) + .bookingItem(givenManagedServer.getBookingItem()) + .parentAsset(givenManagedServer) .caption("some new managed webspace") .type(HsHostingAssetType.MANAGED_WEBSPACE) .identifier("xyz90") @@ -96,14 +97,14 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream() .map(s -> s.replace("hs_office_", "")) .toList(); - final var givenBookingItem = givenBookingItem("First", "some CloudServer"); + final var givenBookingItem = givenBookingItem("First", "some PrivateCloud"); // when final var result = attempt(em, () -> { final var newAsset = HsHostingAssetEntity.builder() .bookingItem(givenBookingItem) - .type(HsHostingAssetType.MANAGED_WEBSPACE) - .identifier("xyz91") + .type(HsHostingAssetType.MANAGED_SERVER) + .identifier("vm9000") .caption("some new managed webspace") .build(); return toCleanup(assetRepo.save(newAsset)); @@ -114,27 +115,27 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu final var all = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN", - "hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER", - "hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT")); + "hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN", + "hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:OWNER", + "hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(fromFormatted( initialGrantNames, - // global-admin // owner - "{ grant perm:hs_hosting_asset#D-1000111-someCloudServer-xyz91:DELETE to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:DELETE to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:OWNER by system and assume }", + "{ grant role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:OWNER to role:hs_booking_item#D-1000111-somePrivateCloud:ADMIN by system and assume }", // admin - "{ grant perm:hs_hosting_asset#D-1000111-someCloudServer-xyz91:UPDATE to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN by system and assume }", - "{ grant role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER by system and assume }", - "{ grant role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER to role:hs_booking_item#D-1000111-someCloudServer:ADMIN by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:INSERT>hs_hosting_asset to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:UPDATE to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN by system and assume }", + "{ grant role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:OWNER by system and assume }", // tenant - "{ grant perm:hs_hosting_asset#D-1000111-someCloudServer-xyz91:SELECT to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT by system and assume }", - "{ grant role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN by system and assume }", - "{ grant role:hs_booking_item#D-1000111-someCloudServer:TENANT to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:SELECT to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT by system and assume }", + "{ grant role:hs_booking_item#D-1000111-somePrivateCloud:TENANT to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT by system and assume }", + "{ grant role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN by system and assume }", null)); } @@ -161,7 +162,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu // then allTheseServersAreReturned( result, - "HsHostingAssetEntity(D-1000212:some PrivateCloud, MANAGED_WEBSPACE, bbb01, some Webspace, { HDD: 2048, RAM: 1, SDD: 512, extra: 42 })", + "HsHostingAssetEntity(D-1000212:some PrivateCloud, MANAGED_WEBSPACE, D-1000212:some PrivateCloud:vm1012, bbb01, some Webspace, { HDD: 2048, RAM: 1, SDD: 512, extra: 42 })", "HsHostingAssetEntity(D-1000212:some PrivateCloud, MANAGED_SERVER, vm1012, some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", "HsHostingAssetEntity(D-1000212:some PrivateCloud, CLOUD_SERVER, vm2012, another CloudServer, { CPU: 2, HDD: 1024, extra: 42 })"); } @@ -178,7 +179,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu // then: exactlyTheseAssetsAreReturned( result, - "HsHostingAssetEntity(D-1000111:some PrivateCloud, MANAGED_WEBSPACE, aaa01, some Webspace, { HDD: 2048, RAM: 1, SDD: 512, extra: 42 })", + "HsHostingAssetEntity(D-1000111:some PrivateCloud, MANAGED_WEBSPACE, D-1000111:some PrivateCloud:vm1011, aaa01, some Webspace, { HDD: 2048, RAM: 1, SDD: 512, extra: 42 })", "HsHostingAssetEntity(D-1000111:some PrivateCloud, MANAGED_SERVER, vm1011, some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", "HsHostingAssetEntity(D-1000111:some PrivateCloud, CLOUD_SERVER, vm2011, another CloudServer, { CPU: 2, HDD: 1024, extra: 42 })"); } @@ -352,6 +353,13 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu .findAny().orElseThrow(); } + HsHostingAssetEntity givenManagedServer(final String debitorName, final String hostingAssetCaption) { + final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike(debitorName).stream().findAny().orElseThrow(); + return assetRepo.findAllByDebitorUuid(givenDebitor.getUuid()).stream() + .filter(i -> i.getCaption().equals(hostingAssetCaption)) + .findAny().orElseThrow(); + } + void exactlyTheseAssetsAreReturned( final List actualResult, final String... serverNames) {