allow-multiple-insert-permission-grants #49

Merged
hsh-michaelhoennig merged 15 commits from allow-multiple-insert-permission-grants into master 2024-04-29 11:43:49 +02:00
45 changed files with 1387 additions and 2332 deletions

View File

@ -179,7 +179,9 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject {
.createSubRole(TENANT, (with) -> { .createSubRole(TENANT, (with) -> {
with.outgoingSubRole("debitorRel", TENANT); with.outgoingSubRole("debitorRel", TENANT);
with.permission(SELECT); with.permission(SELECT);
}); })
.limitDiagramTo("bookingItem", "debitorRel", "global");
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {

View File

@ -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_SERVER;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; 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.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.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingCase; 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.ColumnValue.usingDefaultCase;
@ -156,9 +157,10 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
dependsOnColumn("parentAssetUuid"), dependsOnColumn("parentAssetUuid"),
directlyFetchedByDependsOnColumn(), directlyFetchedByDependsOnColumn(),
NULLABLE) NULLABLE)
// TODO.rbac: implement multiple INSERT-rules, e.g. for Asset.bookingItem + Asset.parentAsset .toRole("parentServer", ADMIN).grantPermission(INSERT)
//.toRole("parentServer", AGENT).grantPermission(INSERT) .toRole("bookingItem", AGENT).grantPermission(INSERT)
) ),
inOtherCases(then -> {})
) )
.createRole(OWNER, (with) -> { .createRole(OWNER, (with) -> {
@ -171,7 +173,9 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
.createSubRole(TENANT, (with) -> { .createSubRole(TENANT, (with) -> {
with.outgoingSubRole("bookingItem", TENANT); with.outgoingSubRole("bookingItem", TENANT);
with.permission(SELECT); with.permission(SELECT);
}); })
.limitDiagramTo("asset", "bookingItem", "bookingItem.debitorRel", "parentServer", "global");
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {

View File

@ -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.inCaseOf;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inOtherCases; 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.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.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;

View File

@ -1,12 +1,16 @@
package net.hostsharing.hsadminng.rbac.rbacdef; package net.hostsharing.hsadminng.rbac.rbacdef;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.function.BinaryOperator; import java.util.function.BinaryOperator;
import java.util.stream.Stream; 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.PostgresTriggerReference.NEW;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; 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.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 net.hostsharing.hsadminng.rbac.rbacdef.StringWriter.with;
import static org.apache.commons.lang3.StringUtils.capitalize; import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.uncapitalize; import static org.apache.commons.lang3.StringUtils.uncapitalize;
@ -22,194 +26,121 @@ public class InsertTriggerGenerator {
} }
void generateTo(final StringWriter plPgSql) { void generateTo(final StringWriter plPgSql) {
generateLiquibaseChangesetHeader(plPgSql); if (isInsertPermissionGrantedToGlobalGuest()) {
generateGrantInsertRoleToExistingObjects(plPgSql); // any user is allowed to insert new rows => no insert check needed
generateInsertPermissionGrantTrigger(plPgSql); return;
generateInsertCheckTrigger(plPgSql);
plPgSql.writeLn("--//");
} }
private void generateLiquibaseChangesetHeader(final StringWriter plPgSql) { generateInsertGrants(plPgSql);
generateInsertPermissionChecks(plPgSql);
}
private void generateInsertGrants(final StringWriter plPgSql) {
if (isInsertPermissionIsNotGrantedAtAll()) {
generateInsertPermissionTriggerAlwaysDisallow(plPgSql);
} else {
generateInsertPermissionGrants(plPgSql);
}
}
private void generateInsertPermissionGrants(final StringWriter plPgSql) {
plPgSql.writeLn(""" plPgSql.writeLn("""
-- ============================================================================ -- ============================================================================
--changeset ${liquibaseTagPrefix}-rbac-INSERT:1 endDelimiter:--// --changeset ${liquibaseTagPrefix}-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
""", """,
with("liquibaseTagPrefix", liquibaseTagPrefix)); with("liquibaseTagPrefix", liquibaseTagPrefix));
}
private void generateGrantInsertRoleToExistingObjects(final StringWriter plPgSql) { getInsertGrants().forEach( g -> {
getOptionalInsertSuperRole().ifPresent( superRoleDef -> {
plPgSql.writeLn(""" plPgSql.writeLn("""
-- granting INSERT permission to ${rawSubTable} ----------------------------
""",
with("rawSubTable", g.getSuperRoleDef().getEntityAlias().getRawTableName()));
if (isGrantToADifferentTable(g)) {
plPgSql.writeLn(
"""
/* /*
Creates INSERT INTO ${rawSubTableName} permissions for the related ${rawSuperTableName} rows. Grants INSERT INTO ${rawSubTable} permissions to specified role of pre-existing ${rawSuperTable} rows.
*/ */
do language plpgsql $$ do language plpgsql $$
declare declare
row ${rawSuperTableName}; row ${rawSuperTable};
begin begin
call defineContext('create INSERT INTO ${rawSubTableName} permissions for the related ${rawSuperTableName} rows'); call defineContext('create INSERT INTO ${rawSubTable} permissions for pre-exising ${rawSuperTable} rows');
FOR row IN SELECT * FROM ${rawSuperTableName}${typeCondition} FOR row IN SELECT * FROM ${rawSuperTable}
${whenCondition}
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', '${rawSubTableName}'), createPermission(row.uuid, 'INSERT', '${rawSubTable}'),
${rawSuperRoleDescriptor}); ${superRoleRef});
END LOOP; END LOOP;
END; end;
$$; $$;
""", """,
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()), with("whenCondition", g.getSuperRoleDef().getEntityAlias().isCaseDependent()
with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()), // TODO.impl: 'type' needs to be dynamically generated
with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, "row")), ? "WHERE type = '${value}'"
with("typeCondition", superRoleDef.getEntityAlias().isCaseDependent() .replace("${value}", g.getSuperRoleDef().getEntityAlias().usingCase().value)
? "\n\t\t\tWHERE type = '${case}'".replace("${case}", superRoleDef.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()));
} }
private void generateInsertPermissionGrantTrigger(final StringWriter plPgSql) {
getOptionalInsertSuperRole().ifPresent( superRoleDef -> {
plPgSql.writeLn(""" 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
${typeConditionIf}call grantPermissionToRole( ${ifConditionThen}
createPermission(NEW.uuid, 'INSERT', '${rawSubTableName}'), call grantPermissionToRole(
${rawSuperRoleDescriptor});${typeConditionEndIf} createPermission(NEW.uuid, 'INSERT', '${rawSubTable}'),
${superRoleRef});
${ifConditionEnd}
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 create trigger z_new_${rawSubTable}_grants_insert_to_${rawSuperTable}_tg
after insert on ${rawSuperTableName} after insert on ${rawSuperTable}
for each row for each row
execute procedure ${rawSubTableName}_${rawSuperTableName}_insert_tf(); execute procedure new_${rawSubTable}_grants_insert_to_${rawSuperTable}_tf();
""", """,
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()), with("ifConditionThen", g.getSuperRoleDef().getEntityAlias().isCaseDependent()
with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()), // TODO.impl: .type needs to be dynamically generated
with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, NEW.name())), ? "if NEW.type = '" + g.getSuperRoleDef().getEntityAlias().usingCase().value + "' then"
with("typeConditionIf", : "-- unconditional for all rows in that table"),
superRoleDef.getEntityAlias().isCaseDependent() with("ifConditionEnd", g.getSuperRoleDef().getEntityAlias().isCaseDependent()
? "if NEW.type = '${case}' then\n\t\t".replace("${case}", superRoleDef.getEntityAlias().usingCase().value) ? "end if;"
: ""), : "-- end."),
with("typeConditionEndIf", superRoleDef.getEntityAlias().isCaseDependent() with("superRoleRef", toRoleDescriptor(g.getSuperRoleDef(), NEW.name())),
? "\n\tend if;" with("rawSuperTable", g.getSuperRoleDef().getEntityAlias().getRawTableName()),
: "") with("rawSubTable", g.getPermDef().getEntityAlias().getRawTableName()));
);
}); });
} }
private void generateInsertCheckTrigger(final StringWriter plPgSql) { private void generateInsertPermissionTriggerAlwaysDisallow(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) {
plPgSql.writeLn(""" plPgSql.writeLn("""
/** -- ============================================================================
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}, --changeset ${liquibaseTagPrefix}-rbac-ALWAYS-DISALLOW-INSERT:1 endDelimiter:--//
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; $$;
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("liquibaseTagPrefix", liquibaseTagPrefix));
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(""" plPgSql.writeLn("""
/** /**
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}, Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
@ -219,6 +150,110 @@ public class InsertTriggerGenerator {
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
begin begin
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
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 % (%)', raise exception '[403] insert into ${rawSubTable} not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -226,18 +261,35 @@ public class InsertTriggerGenerator {
create trigger ${rawSubTable}_insert_permission_check_tg create trigger ${rawSubTable}_insert_permission_check_tg
before insert on ${rawSubTable} before insert on ${rawSubTable}
for each row for each row
when ( not isGlobalAdmin() ) execute procedure ${rawSubTable}_insert_permission_check_tf();
execute procedure ${rawSubTable}_insert_permission_missing_tf(); --//
""", """,
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
} }
private String toStringList(final Set<RbacView.CaseDef> 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<RbacView.RbacGrantDefinition> getInsertGrants() { private Stream<RbacView.RbacGrantDefinition> getInsertGrants() {
return rbacDef.getGrantDefs().stream() return rbacDef.getGrantDefs().stream()
.filter(g -> g.grantType() == PERM_TO_ROLE) .filter(g -> g.grantType() == PERM_TO_ROLE)
.filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT); .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<RbacView.RbacGrantDefinition> getOptionalInsertGrant() { private Optional<RbacView.RbacGrantDefinition> getOptionalInsertGrant() {
return getInsertGrants() return getInsertGrants()
.reduce(singleton()); .reduce(singleton());
@ -252,7 +304,8 @@ public class InsertTriggerGenerator {
private static <T> BinaryOperator<T> singleton() { private static <T> BinaryOperator<T> singleton() {
return (x, y) -> { return (x, y) -> {
if ( !x.equals(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; return x;
}; };

View File

@ -43,5 +43,6 @@ public class RbacIdentityViewGenerator {
with("rawTableName", rawTableName)); with("rawTableName", rawTableName));
plPgSql.writeLn("--//"); plPgSql.writeLn("--//");
plPgSql.writeLn();
} }
} }

View File

@ -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.ColumnValue.usingDefaultCase;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; 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.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.RbacUserReference.UserRole.CREATOR;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH;
import static org.apache.commons.collections4.SetUtils.hashSet; import static org.apache.commons.collections4.SetUtils.hashSet;
@ -62,6 +63,7 @@ public class RbacView {
private SQL orderBySqlExpression; private SQL orderBySqlExpression;
private EntityAlias rootEntityAliasProxy; private EntityAlias rootEntityAliasProxy;
private RbacRoleDefinition previousRoleDef; private RbacRoleDefinition previousRoleDef;
private Set<String> limitDiagramToAliasNames;
private final Map<String, CaseDef> cases = new LinkedHashMap<>() { private final Map<String, CaseDef> cases = new LinkedHashMap<>() {
@Override @Override
public CaseDef put(final String key, final CaseDef value) { 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); new RbacRoleDefinition(findEntityAlias(mapper.map(roleDef.entityAlias.aliasName)), roleDef.role);
}); });
copyOf(importedRbacView.getGrantDefs()).forEach(grantDef -> { copyOf(importedRbacView.getGrantDefs()).forEach(grantDef -> {
if ( grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE && if ( grantDef.grantType() == ROLE_TO_ROLE && grantDef.matchesCase(forCase) ) {
(grantDef.forCases == null || grantDef.matchesCase(forCase)) ) {
final var importedGrantDef = findOrCreateGrantDef( final var importedGrantDef = findOrCreateGrantDef(
findRbacRole( findRbacRole(
mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName), mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName),
@ -499,6 +500,29 @@ public class RbacView {
new RbacViewPostgresGenerator(this).generateToChangeLog(Path.of(OUTPUT_BASEDIR, baseFileName + ".sql")); 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 { public class RbacGrantBuilder {
private final RbacRoleDefinition superRoleDef; private final RbacRoleDefinition superRoleDef;
@ -535,7 +559,7 @@ public class RbacView {
private final RbacPermissionDefinition permDef; private final RbacPermissionDefinition permDef;
private boolean assumed = true; private boolean assumed = true;
private boolean toCreate = false; private boolean toCreate = false;
private Set<CaseDef> forCases = new HashSet<>(); private Set<CaseDef> forCases = new LinkedHashSet<>();
@Override @Override
public String toString() { public String toString() {
@ -560,11 +584,13 @@ public class RbacView {
register(this); 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.userDef = null;
this.subRoleDef = null; this.subRoleDef = null;
this.superRoleDef = roleDef; this.superRoleDef = roleDef;
this.permDef = permDef; this.permDef = permDef;
this.forCases = forCase != null ? hashSet(forCase) : null;
register(this); register(this);
} }
@ -584,7 +610,7 @@ public class RbacView {
GrantType grantType() { GrantType grantType() {
return permDef != null ? PERM_TO_ROLE return permDef != null ? PERM_TO_ROLE
: userDef != null ? GrantType.ROLE_TO_USER : userDef != null ? GrantType.ROLE_TO_USER
: GrantType.ROLE_TO_ROLE; : ROLE_TO_ROLE;
} }
boolean isAssumed() { boolean isAssumed() {
@ -602,9 +628,10 @@ public class RbacView {
} }
boolean matchesCase(final ColumnValue requestedCase) { boolean matchesCase(final ColumnValue requestedCase) {
final var noCasesDefined = forCases.isEmpty(); final var noCasesDefined = forCases == null;
final var generateForAllCases = requestedCase == 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; return noCasesDefined || generateForAllCases || isGrantedForRequestedCase;
} }
@ -676,7 +703,8 @@ public class RbacView {
final String tableName; final String tableName;
final boolean toCreate; 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.entityAlias = entityAlias;
this.permission = permission; this.permission = permission;
this.tableName = tableName; this.tableName = tableName;
@ -788,6 +816,10 @@ public class RbacView {
public String toString() { public String toString() {
return "role:" + entityAlias.aliasName + role; return "role:" + entityAlias.aliasName + role;
} }
public boolean isGlobal(final Role role) {
return entityAlias.isGlobal() && this.role == role;
}
} }
public RbacUserReference findUserRef(final RbacUserReference.UserRole userRole) { public RbacUserReference findUserRef(final RbacUserReference.UserRole userRole) {
@ -842,19 +874,6 @@ public class RbacView {
.orElseGet(() -> new RbacPermissionDefinition(entityAlias, perm, tableName, true)); // TODO: true => toCreate .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) { private RbacGrantDefinition findOrCreateGrantDef(final RbacRoleDefinition roleDefinition, final RbacUserReference user) {
return grantDefs.stream() return grantDefs.stream()
.filter(g -> g.subRoleDef == roleDefinition && g.userDef == user) .filter(g -> g.subRoleDef == roleDefinition && g.userDef == user)
@ -866,7 +885,8 @@ public class RbacView {
return grantDefs.stream() return grantDefs.stream()
.filter(g -> g.permDef == permDef && g.superRoleDef == roleDef) .filter(g -> g.permDef == permDef && g.superRoleDef == roleDef)
.findFirst() .findFirst()
.orElseGet(() -> new RbacGrantDefinition(permDef, roleDef)); .map(g -> g.forCase(processingCase))
.orElseGet(() -> new RbacGrantDefinition(permDef, roleDef, processingCase));
} }
private RbacGrantDefinition findOrCreateGrantDef( private RbacGrantDefinition findOrCreateGrantDef(

View File

@ -5,7 +5,12 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.nio.file.*; 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 java.util.stream.Collectors.joining;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.*; 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_LIGHT_ORANGE = "#feb28c";
public static final String HOSTSHARING_DARK_BLUE = "#274d6e"; public static final String HOSTSHARING_DARK_BLUE = "#274d6e";
public static final String HOSTSHARING_LIGHT_BLUE = "#99bcdb"; 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 RbacView rbacDef;
private final List<RbacView.EntityAlias> usedEntityAliases;
private final CaseDef forCase; private final CaseDef forCase;
private final StringWriter flowchart = new StringWriter(); private final StringWriter flowchart = new StringWriter();
public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef, final CaseDef forCase) { public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef, final CaseDef forCase) {
this.rbacDef = rbacDef; this.rbacDef = rbacDef;
this.forCase = forCase; 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(""" flowchart.writeLn("""
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB flowchart TB
@ -38,13 +54,18 @@ public class RbacViewMermaidFlowchartGenerator {
this(rbacDef, null); this(rbacDef, null);
} }
private void renderEntitySubgraphs() { private void renderEntitySubgraphs() {
rbacDef.getEntityAliases().values().stream() usedEntityAliases.stream()
.filter(entityAlias -> !rbacDef.isEntityAliasProxy(entityAlias)) .filter(entityAlias -> !rbacDef.isEntityAliasProxy(entityAlias))
.filter(entityAlias -> !entityAlias.isPlaceholder()) .filter(entityAlias -> !entityAlias.isPlaceholder())
.filter(rbacDef::renderInDiagram)
.forEach(this::renderEntitySubgraph); .forEach(this::renderEntitySubgraph);
} }
private void renderEntitySubgraph(final RbacView.EntityAlias entity) { private void renderEntitySubgraph(final RbacView.EntityAlias entity) {
if (!rbacDef.renderInDiagram(entity)) {
return;
}
final var color = rbacDef.isRootEntityAlias(entity) ? HOSTSHARING_DARK_ORANGE final var color = rbacDef.isRootEntityAlias(entity) ? HOSTSHARING_DARK_ORANGE
: entity.isSubEntity() ? HOSTSHARING_LIGHT_ORANGE : entity.isSubEntity() ? HOSTSHARING_LIGHT_ORANGE
: HOSTSHARING_LIGHT_BLUE; : HOSTSHARING_LIGHT_BLUE;
@ -58,8 +79,7 @@ public class RbacViewMermaidFlowchartGenerator {
.replace("%{strokeColor}", HOSTSHARING_DARK_BLUE )); .replace("%{strokeColor}", HOSTSHARING_DARK_BLUE ));
flowchart.indented( () -> { flowchart.indented( () -> {
rbacDef.getEntityAliases().values().stream() usedEntityAliases.stream()
.filter(e -> e.level() <= MAX_LEVEL_TO_RENDER)
.filter(e -> e.aliasName().startsWith(entity.aliasName() + ":")) .filter(e -> e.aliasName().startsWith(entity.aliasName() + ":"))
.forEach(this::renderEntitySubgraph); .forEach(this::renderEntitySubgraph);
@ -110,9 +130,9 @@ public class RbacViewMermaidFlowchartGenerator {
private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) { private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) {
final var grantsOfRequestedType = rbacDef.getGrantDefs().stream() final var grantsOfRequestedType = rbacDef.getGrantDefs().stream()
.filter(g -> g.level() <= MAX_LEVEL_TO_RENDER)
.filter(g -> g.grantType() == grantType) .filter(g -> g.grantType() == grantType)
.filter(this::isToBeRenderedInThisGraph) .filter(rbacDef::renderInDiagram)
.filter(this::isToBeRenderedForThisCase)
.toList(); .toList();
if ( !grantsOfRequestedType.isEmpty()) { if ( !grantsOfRequestedType.isEmpty()) {
flowchart.ensureSingleEmptyLine(); flowchart.ensureSingleEmptyLine();
@ -121,8 +141,8 @@ public class RbacViewMermaidFlowchartGenerator {
} }
} }
private boolean isToBeRenderedInThisGraph(final RbacView.RbacGrantDefinition g) { private boolean isToBeRenderedForThisCase(final RbacView.RbacGrantDefinition g) {
if ( g.grantType() != ROLE_TO_ROLE ) if ( g.grantType() == ROLE_TO_USER )
return true; return true;
if ( forCase == null && !g.isConditional() ) if ( forCase == null && !g.isConditional() )
return true; return true;

View File

@ -2,8 +2,6 @@ package net.hostsharing.hsadminng.rbac.rbacdef;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.regex.Pattern;
import static java.util.Arrays.stream; import static java.util.Arrays.stream;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.joining;
@ -111,9 +109,11 @@ public class StringWriter {
String apply(final String textToAppend) { String apply(final String textToAppend) {
text = textToAppend; text = textToAppend;
stream(varDefs).forEach(varDef -> { stream(varDefs).forEach(varDef -> {
final var pattern = Pattern.compile("\\$\\{" + varDef.name() + "}", Pattern.CASE_INSENSITIVE); // TODO.impl: I actually want a case-independent search+replace but ...
final var matcher = pattern.matcher(text); // for which the substitution String can contain sequences of "${...}" to be replaced by further varDefs.
text = matcher.replaceAll(varDef.value()); 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; return text;
} }

View File

@ -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; $$;
--//

View File

@ -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 returns BOOL
stable -- leakproof stable -- leakproof
language plpgsql as $$ language plpgsql as $$
declare declare
permissionUuid uuid; permissionUuid uuid;
begin begin
permissionUuid = findPermissionId(objectUuid, forOp, tableName); permissionUuid = findPermissionId(objectUuid, 'INSERT'::RbacOp, tableName);
return permissionUuid is not null; return permissionUuid is not null;
end; end;
$$; $$;

View File

@ -77,55 +77,71 @@ 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 $$ do language plpgsql $$
declare declare
row global; row global;
begin 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 FOR row IN SELECT * FROM global
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'test_customer'), createPermission(row.uuid, 'INSERT', 'test_customer'),
globalADMIN()); globalADMIN());
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'test_customer'), createPermission(NEW.uuid, 'INSERT', 'test_customer'),
globalADMIN()); globalADMIN());
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on global
for each row 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, Checks if the user respectively the assumed roles are allowed to insert a row to test_customer.
where only global-admin has that permission.
*/ */
create or replace function test_customer_insert_permission_missing_tf() create or replace function test_customer_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into test_customer not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -133,10 +149,10 @@ end; $$;
create trigger test_customer_insert_permission_check_tg create trigger test_customer_insert_permission_check_tg
before insert on test_customer before insert on test_customer
for each row for each row
when ( not isGlobalAdmin() ) execute procedure test_customer_insert_permission_check_tf();
execute procedure test_customer_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -147,6 +163,7 @@ call generateRbacIdentityViewFromProjection('test_customer',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,6 +6,19 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph package["`**package**`"]
direction TB direction TB
style package fill:#dd4901,stroke:#274d6e,stroke-width:8px style package fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -28,19 +41,6 @@ subgraph package["`**package**`"]
end end
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 %% granting roles to roles
role:global:ADMIN -.->|XX| role:customer:OWNER role:global:ADMIN -.->|XX| role:customer:OWNER
role:customer:OWNER -.-> role:customer:ADMIN role:customer:OWNER -.-> role:customer:ADMIN

View File

@ -142,57 +142,71 @@ 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 $$ do language plpgsql $$
declare declare
row test_customer; row test_customer;
begin 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 FOR row IN SELECT * FROM test_customer
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'test_package'), createPermission(row.uuid, 'INSERT', 'test_package'),
testCustomerADMIN(row)); testCustomerADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'test_package'), createPermission(NEW.uuid, 'INSERT', 'test_package'),
testCustomerADMIN(NEW)); testCustomerADMIN(NEW));
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on test_customer
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function test_package_insert_permission_missing_tf() create or replace function test_package_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into test_package not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -200,10 +214,10 @@ end; $$;
create trigger test_package_insert_permission_check_tg create trigger test_package_insert_permission_check_tg
before insert on test_package before insert on test_package
for each row for each row
when ( not hasInsertPermission(NEW.customerUuid, 'INSERT', 'test_package') ) execute procedure test_package_insert_permission_check_tf();
execute procedure test_package_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -214,6 +228,7 @@ call generateRbacIdentityViewFromProjection('test_package',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,32 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph domain["`**domain**`"]
direction TB direction TB
style domain fill:#dd4901,stroke:#274d6e,stroke-width:8px style domain fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -53,6 +27,32 @@ subgraph domain["`**domain**`"]
end end
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 %% granting roles to roles
role:global:ADMIN -.->|XX| role:package.customer:OWNER role:global:ADMIN -.->|XX| role:package.customer:OWNER
role:package.customer:OWNER -.-> role:package.customer:ADMIN role:package.customer:OWNER -.-> role:package.customer:ADMIN

View File

@ -141,57 +141,71 @@ 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 $$ do language plpgsql $$
declare declare
row test_package; row test_package;
begin 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 FOR row IN SELECT * FROM test_package
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'test_domain'), createPermission(row.uuid, 'INSERT', 'test_domain'),
testPackageADMIN(row)); testPackageADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'test_domain'), createPermission(NEW.uuid, 'INSERT', 'test_domain'),
testPackageADMIN(NEW)); testPackageADMIN(NEW));
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on test_package
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function test_domain_insert_permission_missing_tf() create or replace function test_domain_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into test_domain not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -199,10 +213,10 @@ end; $$;
create trigger test_domain_insert_permission_check_tg create trigger test_domain_insert_permission_check_tg
before insert on test_domain before insert on test_domain
for each row for each row
when ( not hasInsertPermission(NEW.packageUuid, 'INSERT', 'test_domain') ) execute procedure test_domain_insert_permission_check_tf();
execute procedure test_domain_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -213,6 +227,7 @@ call generateRbacIdentityViewFromProjection('test_domain',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -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:--// --changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -129,6 +86,7 @@ call generateRbacIdentityViewFromProjection('hs_office_contact',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -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:--// --changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -129,6 +86,7 @@ call generateRbacIdentityViewFromProjection('hs_office_person',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,19 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph anchorPerson["`**anchorPerson**`"]
direction TB direction TB
style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -45,6 +32,19 @@ subgraph contact["`**contact**`"]
end end
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**`"] subgraph relation["`**relation**`"]
direction TB direction TB
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px

View File

@ -6,19 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph anchorPerson["`**anchorPerson**`"]
direction TB direction TB
style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -45,6 +32,19 @@ subgraph contact["`**contact**`"]
end end
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**`"] subgraph relation["`**relation**`"]
direction TB direction TB
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px

View File

@ -151,57 +151,71 @@ 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 $$ do language plpgsql $$
declare declare
row hs_office_person; row hs_office_person;
begin 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 FOR row IN SELECT * FROM hs_office_person
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_relation'), createPermission(row.uuid, 'INSERT', 'hs_office_relation'),
hsOfficePersonADMIN(row)); hsOfficePersonADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'), createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'),
hsOfficePersonADMIN(NEW)); hsOfficePersonADMIN(NEW));
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on hs_office_person
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function hs_office_relation_insert_permission_missing_tf() create or replace function hs_office_relation_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -209,10 +223,10 @@ end; $$;
create trigger hs_office_relation_insert_permission_check_tg create trigger hs_office_relation_insert_permission_check_tg
before insert on hs_office_relation before insert on hs_office_relation
for each row for each row
when ( not hasInsertPermission(NEW.anchorUuid, 'INSERT', 'hs_office_relation') ) execute procedure hs_office_relation_insert_permission_check_tf();
execute procedure hs_office_relation_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -225,6 +239,7 @@ call generateRbacIdentityViewFromProjection('hs_office_relation',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,19 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph partner["`**partner**`"]
direction TB direction TB
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -73,6 +60,19 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
end end
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**`"] subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px

View File

@ -154,55 +154,71 @@ 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 $$ do language plpgsql $$
declare declare
row global; row global;
begin 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 FOR row IN SELECT * FROM global
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_partner'), createPermission(row.uuid, 'INSERT', 'hs_office_partner'),
globalADMIN()); globalADMIN());
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'), createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'),
globalADMIN()); globalADMIN());
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on global
for each row 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, Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_partner.
where only global-admin has that permission.
*/ */
create or replace function hs_office_partner_insert_permission_missing_tf() create or replace function hs_office_partner_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_partner not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -210,10 +226,10 @@ end; $$;
create trigger hs_office_partner_insert_permission_check_tg create trigger hs_office_partner_insert_permission_check_tg
before insert on hs_office_partner before insert on hs_office_partner
for each row for each row
when ( not isGlobalAdmin() ) execute procedure hs_office_partner_insert_permission_check_tf();
execute procedure hs_office_partner_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -224,6 +240,7 @@ call generateRbacIdentityViewFromProjection('hs_office_partner',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -58,55 +58,71 @@ 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 $$ do language plpgsql $$
declare declare
row global; row global;
begin 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 FOR row IN SELECT * FROM global
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'), createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'),
globalADMIN()); globalADMIN());
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'), createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'),
globalADMIN()); globalADMIN());
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on global
for each row 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, Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_partner_details.
where only global-admin has that permission.
*/ */
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 returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -114,15 +130,15 @@ end; $$;
create trigger hs_office_partner_details_insert_permission_check_tg create trigger hs_office_partner_details_insert_permission_check_tg
before insert on hs_office_partner_details before insert on hs_office_partner_details
for each row for each row
when ( not isGlobalAdmin() ) execute procedure hs_office_partner_details_insert_permission_check_tf();
execute procedure hs_office_partner_details_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner_details', call generateRbacIdentityViewFromQuery('hs_office_partner_details',
$idName$ $idName$
SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName
FROM hs_office_partner_details AS partnerDetails FROM hs_office_partner_details AS partnerDetails
@ -131,6 +147,7 @@ create trigger hs_office_partner_details_insert_permission_check_tg
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -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:--// --changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -129,6 +86,7 @@ call generateRbacIdentityViewFromProjection('hs_office_bankaccount',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,45 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph debitor["`**debitor**`"]
direction TB direction TB
style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -73,30 +34,16 @@ subgraph debitor["`**debitor**`"]
end end
end end
subgraph partnerRel["`**partnerRel**`"] subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel:roles[ ] subgraph debitorRel.anchorPerson:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel:OWNER[[partnerRel:OWNER]] role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]]
role:partnerRel:ADMIN[[partnerRel:ADMIN]] role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]]
role:partnerRel:AGENT[[partnerRel:AGENT]] role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]]
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
end end
@ -113,6 +60,33 @@ subgraph debitorRel.contact["`**debitorRel.contact**`"]
end end
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**`"] subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -126,6 +100,32 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
end end
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**`"] subgraph refundBankAccount["`**refundBankAccount**`"]
direction TB direction TB
style refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px 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:global:ADMIN -.-> role:debitorRel.contact:OWNER
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER 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:global:ADMIN -.-> role:refundBankAccount:OWNER
role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN
role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER

View File

@ -127,55 +127,71 @@ 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 $$ do language plpgsql $$
declare declare
row global; row global;
begin 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 FOR row IN SELECT * FROM global
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_debitor'), createPermission(row.uuid, 'INSERT', 'hs_office_debitor'),
globalADMIN()); globalADMIN());
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'), createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'),
globalADMIN()); globalADMIN());
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on global
for each row 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, Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_debitor.
where only global-admin has that permission.
*/ */
create or replace function hs_office_debitor_insert_permission_missing_tf() create or replace function hs_office_debitor_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_debitor not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -183,15 +199,15 @@ end; $$;
create trigger hs_office_debitor_insert_permission_check_tg create trigger hs_office_debitor_insert_permission_check_tg
before insert on hs_office_debitor before insert on hs_office_debitor
for each row for each row
when ( not isGlobalAdmin() ) execute procedure hs_office_debitor_insert_permission_check_tf();
execute procedure hs_office_debitor_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_debitor', call generateRbacIdentityViewFromQuery('hs_office_debitor',
$idName$ $idName$
SELECT debitor.uuid AS uuid, SELECT debitor.uuid AS uuid,
'D-' || (SELECT partner.partnerNumber 'D-' || (SELECT partner.partnerNumber
@ -206,6 +222,7 @@ create trigger hs_office_debitor_insert_permission_check_tg
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -19,16 +19,17 @@ subgraph bankAccount["`**bankAccount**`"]
end end
end end
subgraph debitorRel.contact["`**debitorRel.contact**`"] subgraph debitorRel["`**debitorRel**`"]
direction TB 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[ ] subgraph debitorRel:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]] role:debitorRel:OWNER[[debitorRel:OWNER]]
role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]] role:debitorRel:ADMIN[[debitorRel:ADMIN]]
role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]] role:debitorRel:AGENT[[debitorRel:AGENT]]
role:debitorRel:TENANT[[debitorRel:TENANT]]
end end
end end
@ -45,6 +46,19 @@ subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
end end
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**`"] subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -81,20 +95,6 @@ subgraph sepaMandate["`**sepaMandate**`"]
end end
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 %% granting roles to users
user:creator ==> role:sepaMandate:OWNER 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:global:ADMIN -.-> role:debitorRel.contact:OWNER
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER 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:global:ADMIN -.-> role:bankAccount:OWNER
role:bankAccount:OWNER -.-> role:bankAccount:ADMIN role:bankAccount:OWNER -.-> role:bankAccount:ADMIN
role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER

View File

@ -102,17 +102,19 @@ 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 $$ do language plpgsql $$
declare declare
row hs_office_relation; row hs_office_relation;
begin 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 FOR row IN SELECT * FROM hs_office_relation
WHERE type = 'DEBITOR' WHERE type = 'DEBITOR'
@ -121,13 +123,13 @@ do language plpgsql $$
createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'), createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'),
hsOfficeRelationADMIN(row)); hsOfficeRelationADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
@ -141,39 +143,38 @@ begin
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on hs_office_relation
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function hs_office_sepamandate_insert_permission_check_tf() create or replace function hs_office_sepamandate_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare declare
superRoleObjectUuid uuid; superObjectUuid uuid;
begin begin
superRoleObjectUuid := (SELECT debitorRel.uuid -- check INSERT permission via indirect foreign key: NEW.debitorUuid
superObjectUuid := (SELECT debitorRel.uuid
FROM hs_office_relation debitorRel FROM hs_office_relation debitorRel
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid WHERE debitor.uuid = NEW.debitorUuid
); );
assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null'; 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
if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_office_sepamandate') ) then
raise exception
'[403] insert into hs_office_sepamandate not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end if;
return NEW; return NEW;
end if;
raise exception '[403] insert into hs_office_sepamandate not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
create trigger hs_office_sepamandate_insert_permission_check_tg create trigger hs_office_sepamandate_insert_permission_check_tg
@ -182,11 +183,12 @@ create trigger hs_office_sepamandate_insert_permission_check_tg
execute procedure hs_office_sepamandate_insert_permission_check_tf(); execute procedure hs_office_sepamandate_insert_permission_check_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_sepamandate', call generateRbacIdentityViewFromQuery('hs_office_sepamandate',
$idName$ $idName$
select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName
from hs_office_sepamandate sm from hs_office_sepamandate sm
@ -194,6 +196,7 @@ create trigger hs_office_sepamandate_insert_permission_check_tg
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,33 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph membership["`**membership**`"]
direction TB direction TB
style membership fill:#dd4901,stroke:#274d6e,stroke-width:8px style membership fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -55,6 +28,20 @@ subgraph membership["`**membership**`"]
end end
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**`"] subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -68,6 +55,19 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
end end
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**`"] subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px

View File

@ -89,55 +89,71 @@ 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 $$ do language plpgsql $$
declare declare
row global; row global;
begin 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 FOR row IN SELECT * FROM global
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_membership'), createPermission(row.uuid, 'INSERT', 'hs_office_membership'),
globalADMIN()); globalADMIN());
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'), createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'),
globalADMIN()); globalADMIN());
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on global
for each row 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, Checks if the user respectively the assumed roles are allowed to insert a row to hs_office_membership.
where only global-admin has that permission.
*/ */
create or replace function hs_office_membership_insert_permission_missing_tf() create or replace function hs_office_membership_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_membership not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -145,15 +161,15 @@ end; $$;
create trigger hs_office_membership_insert_permission_check_tg create trigger hs_office_membership_insert_permission_check_tg
before insert on hs_office_membership before insert on hs_office_membership
for each row for each row
when ( not isGlobalAdmin() ) execute procedure hs_office_membership_insert_permission_check_tf();
execute procedure hs_office_membership_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_membership', call generateRbacIdentityViewFromQuery('hs_office_membership',
$idName$ $idName$
SELECT m.uuid AS uuid, SELECT m.uuid AS uuid,
'M-' || p.partnerNumber || m.memberNumberSuffix as idName 'M-' || p.partnerNumber || m.memberNumberSuffix as idName
@ -162,6 +178,7 @@ create trigger hs_office_membership_insert_permission_check_tg
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-membership-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-membership-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,32 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph coopSharesTransaction["`**coopSharesTransaction**`"]
direction TB direction TB
style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -72,6 +46,19 @@ subgraph membership.partnerRel["`**membership.partnerRel**`"]
end end
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**`"] subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -85,6 +72,19 @@ subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
end end
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 %% granting roles to roles
role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER
role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN

View File

@ -65,57 +65,71 @@ 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 $$ do language plpgsql $$
declare declare
row hs_office_membership; row hs_office_membership;
begin 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 FOR row IN SELECT * FROM hs_office_membership
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'), createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'),
hsOfficeMembershipADMIN(row)); hsOfficeMembershipADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_coopsharestransaction'), createPermission(NEW.uuid, 'INSERT', 'hs_office_coopsharestransaction'),
hsOfficeMembershipADMIN(NEW)); hsOfficeMembershipADMIN(NEW));
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on hs_office_membership
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function hs_office_coopsharestransaction_insert_permission_missing_tf() create or replace function hs_office_coopsharestransaction_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_coopsharestransaction not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -123,10 +137,10 @@ end; $$;
create trigger hs_office_coopsharestransaction_insert_permission_check_tg create trigger hs_office_coopsharestransaction_insert_permission_check_tg
before insert on hs_office_coopsharestransaction before insert on hs_office_coopsharestransaction
for each row for each row
when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopsharestransaction') ) execute procedure hs_office_coopsharestransaction_insert_permission_check_tf();
execute procedure hs_office_coopsharestransaction_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopsharestransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-coopsharestransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -137,6 +151,7 @@ call generateRbacIdentityViewFromProjection('hs_office_coopsharestransaction',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopsharestransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-coopsharestransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,32 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"]
direction TB direction TB
style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -72,6 +46,19 @@ subgraph membership.partnerRel["`**membership.partnerRel**`"]
end end
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**`"] subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -85,6 +72,19 @@ subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
end end
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 %% granting roles to roles
role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER
role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN

View File

@ -65,57 +65,71 @@ 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 $$ do language plpgsql $$
declare declare
row hs_office_membership; row hs_office_membership;
begin 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 FOR row IN SELECT * FROM hs_office_membership
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'), createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'),
hsOfficeMembershipADMIN(row)); hsOfficeMembershipADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_coopassetstransaction'), createPermission(NEW.uuid, 'INSERT', 'hs_office_coopassetstransaction'),
hsOfficeMembershipADMIN(NEW)); hsOfficeMembershipADMIN(NEW));
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on hs_office_membership
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function hs_office_coopassetstransaction_insert_permission_missing_tf() create or replace function hs_office_coopassetstransaction_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_office_coopassetstransaction not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -123,10 +137,10 @@ end; $$;
create trigger hs_office_coopassetstransaction_insert_permission_check_tg create trigger hs_office_coopassetstransaction_insert_permission_check_tg
before insert on hs_office_coopassetstransaction before insert on hs_office_coopassetstransaction
for each row for each row
when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopassetstransaction') ) execute procedure hs_office_coopassetstransaction_insert_permission_check_tf();
execute procedure hs_office_coopassetstransaction_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopassetstransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-coopassetstransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -137,6 +151,7 @@ call generateRbacIdentityViewFromProjection('hs_office_coopassetstransaction',
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopassetstransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-office-coopassetstransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,86 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph bookingItem["`**bookingItem**`"]
direction TB direction TB
style bookingItem fill:#dd4901,stroke:#274d6e,stroke-width:8px style bookingItem fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -109,89 +29,6 @@ subgraph bookingItem["`**bookingItem**`"]
end end
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**`"] subgraph debitorRel["`**debitorRel**`"]
direction TB direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
@ -207,51 +44,10 @@ subgraph debitorRel["`**debitorRel**`"]
end end
%% granting roles to roles %% granting roles to roles
role:global:ADMIN -.-> role:debitor.debitorRel.anchorPerson:OWNER role:global:ADMIN -.-> role:debitorRel:OWNER
role:debitor.debitorRel.anchorPerson:OWNER -.-> role:debitor.debitorRel.anchorPerson:ADMIN role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
role:debitor.debitorRel.anchorPerson:ADMIN -.-> role:debitor.debitorRel.anchorPerson:REFERRER role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
role:global:ADMIN -.-> role:debitor.debitorRel.holderPerson:OWNER role:debitorRel:AGENT -.-> role:debitorRel:TENANT
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:debitorRel:AGENT ==> role:bookingItem:OWNER role:debitorRel:AGENT ==> role:bookingItem:OWNER
role:bookingItem:OWNER ==> role:bookingItem:ADMIN role:bookingItem:OWNER ==> role:bookingItem:ADMIN
role:debitorRel:AGENT ==> role:bookingItem:ADMIN role:debitorRel:AGENT ==> role:bookingItem:ADMIN

View File

@ -98,17 +98,19 @@ 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 $$ do language plpgsql $$
declare declare
row hs_office_relation; row hs_office_relation;
begin 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 FOR row IN SELECT * FROM hs_office_relation
WHERE type = 'DEBITOR' WHERE type = 'DEBITOR'
@ -117,13 +119,13 @@ do language plpgsql $$
createPermission(row.uuid, 'INSERT', 'hs_booking_item'), createPermission(row.uuid, 'INSERT', 'hs_booking_item'),
hsOfficeRelationADMIN(row)); hsOfficeRelationADMIN(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
@ -137,39 +139,38 @@ begin
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on hs_office_relation
for each row 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, Checks if the user respectively the 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.
*/ */
create or replace function hs_booking_item_insert_permission_check_tf() create or replace function hs_booking_item_insert_permission_check_tf()
returns trigger returns trigger
language plpgsql as $$ language plpgsql as $$
declare declare
superRoleObjectUuid uuid; superObjectUuid uuid;
begin begin
superRoleObjectUuid := (SELECT debitorRel.uuid -- check INSERT permission via indirect foreign key: NEW.debitorUuid
superObjectUuid := (SELECT debitorRel.uuid
FROM hs_office_relation debitorRel FROM hs_office_relation debitorRel
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid WHERE debitor.uuid = NEW.debitorUuid
); );
assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null'; 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
if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_booking_item') ) then
raise exception
'[403] insert into hs_booking_item not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end if;
return NEW; return NEW;
end if;
raise exception '[403] insert into hs_booking_item not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
create trigger hs_booking_item_insert_permission_check_tg create trigger hs_booking_item_insert_permission_check_tg
@ -178,11 +179,12 @@ create trigger hs_booking_item_insert_permission_check_tg
execute procedure hs_booking_item_insert_permission_check_tf(); execute procedure hs_booking_item_insert_permission_check_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-booking-item-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-booking-item-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_booking_item', call generateRbacIdentityViewFromQuery('hs_booking_item',
$idName$ $idName$
SELECT bookingItem.uuid as uuid, debitorIV.idName || '-' || cleanIdentifier(bookingItem.caption) as idName SELECT bookingItem.uuid as uuid, debitorIV.idName || '-' || cleanIdentifier(bookingItem.caption) as idName
FROM hs_booking_item bookingItem FROM hs_booking_item bookingItem
@ -190,6 +192,7 @@ create trigger hs_booking_item_insert_permission_check_tg
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-booking-item-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-booking-item-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -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 <NULL>',
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:--// --changeset hs-hosting-asset-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -6,385 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph asset["`**asset**`"]
direction TB direction TB
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -407,41 +28,50 @@ subgraph asset["`**asset**`"]
end end
end end
subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] subgraph bookingItem["`**bookingItem**`"]
direction TB 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[ ] subgraph bookingItem:roles[ ]
style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white style bookingItem:roles fill:#99bcdb,stroke:white
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] role:bookingItem:OWNER[[bookingItem:OWNER]]
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] role:bookingItem:ADMIN[[bookingItem:ADMIN]]
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] 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
end end
%% granting roles to roles %% granting roles to roles
role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER role:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER
role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN
role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT
role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT
role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER
role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN
role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT
role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT
role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN
role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT
role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT
role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER
role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN
role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER
role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN
role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER
role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN
role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER
role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN

View File

@ -6,385 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph asset["`**asset**`"]
direction TB direction TB
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -407,41 +28,50 @@ subgraph asset["`**asset**`"]
end end
end end
subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] subgraph bookingItem["`**bookingItem**`"]
direction TB 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[ ] subgraph bookingItem:roles[ ]
style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white style bookingItem:roles fill:#99bcdb,stroke:white
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] role:bookingItem:OWNER[[bookingItem:OWNER]]
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] role:bookingItem:ADMIN[[bookingItem:ADMIN]]
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] 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
end end
%% granting roles to roles %% granting roles to roles
role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER role:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER
role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN
role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT
role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT
role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER
role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN
role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT
role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT
role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN
role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT
role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT
role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER
role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN
role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER
role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN
role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER
role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN
role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER
role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN

View File

@ -6,385 +6,6 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
%%{init:{'flowchart':{'htmlLabels':false}}}%% %%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB 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**`"] subgraph asset["`**asset**`"]
direction TB direction TB
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
@ -407,53 +28,56 @@ subgraph asset["`**asset**`"]
end end
end end
subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] subgraph bookingItem["`**bookingItem**`"]
direction TB 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[ ] subgraph bookingItem:roles[ ]
style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white style bookingItem:roles fill:#99bcdb,stroke:white
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] role:bookingItem:OWNER[[bookingItem:OWNER]]
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] role:bookingItem:ADMIN[[bookingItem:ADMIN]]
role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] 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
end end
%% granting roles to roles %% granting roles to roles
role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER role:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER
role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN
role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT
role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT
role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER
role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN
role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT
role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT
role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN
role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT
role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT
role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER
role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN
role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER
role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN
role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER
role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER
role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN
role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER
role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN
role:bookingItem:ADMIN -.-> role:bookingItem:AGENT role:bookingItem:ADMIN -.-> role:bookingItem:AGENT
role:bookingItem:AGENT -.-> role:bookingItem:TENANT role:bookingItem:AGENT -.-> role:bookingItem:TENANT
role:bookingItem:TENANT -.-> role:bookingItem.debitorRel: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:bookingItem:ADMIN ==> role:asset:OWNER
role:asset:OWNER ==> role:asset:ADMIN role:asset:OWNER ==> role:asset:ADMIN
role:asset:ADMIN ==> role:asset:TENANT role:asset:ADMIN ==> role:asset:TENANT
@ -461,6 +85,7 @@ role:asset:TENANT ==> role:bookingItem:TENANT
%% granting permissions to roles %% granting permissions to roles
role:bookingItem:AGENT ==> perm:asset:INSERT role:bookingItem:AGENT ==> perm:asset:INSERT
role:parentServer:ADMIN ==> perm:asset:INSERT
role:asset:OWNER ==> perm:asset:DELETE role:asset:OWNER ==> perm:asset:DELETE
role:asset:ADMIN ==> perm:asset:UPDATE role:asset:ADMIN ==> perm:asset:UPDATE
role:asset:TENANT ==> perm:asset:SELECT role:asset:TENANT ==> perm:asset:SELECT

View File

@ -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
```

View File

@ -64,6 +64,7 @@ begin
IF NEW.type = 'CLOUD_SERVER' THEN IF NEW.type = 'CLOUD_SERVER' THEN
ELSIF NEW.type = 'MANAGED_SERVER' THEN ELSIF NEW.type = 'MANAGED_SERVER' THEN
ELSIF NEW.type = 'MANAGED_WEBSPACE' THEN ELSIF NEW.type = 'MANAGED_WEBSPACE' THEN
ELSE
END IF; END IF;
call leaveTriggerForObjectUuid(NEW.uuid); call leaveTriggerForObjectUuid(NEW.uuid);
@ -90,57 +91,102 @@ 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 $$ do language plpgsql $$
declare declare
row hs_booking_item; row hs_booking_item;
begin 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 FOR row IN SELECT * FROM hs_booking_item
-- unconditional for all rows in that table
LOOP LOOP
call grantPermissionToRole( call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_hosting_asset'), createPermission(row.uuid, 'INSERT', 'hs_hosting_asset'),
hsBookingItemAGENT(row)); hsBookingItemAGENT(row));
END LOOP; 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 returns trigger
language plpgsql language plpgsql
strict as $$ strict as $$
begin begin
-- unconditional for all rows in that table
call grantPermissionToRole( call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_hosting_asset'), createPermission(NEW.uuid, 'INSERT', 'hs_hosting_asset'),
hsBookingItemAGENT(NEW)); hsBookingItemAGENT(NEW));
-- end.
return NEW; return NEW;
end; $$; end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist -- 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 after insert on hs_booking_item
for each row 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, Grants hs_hosting_asset INSERT permission to specified role of new hs_hosting_asset rows.
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 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 returns trigger
language plpgsql as $$ language plpgsql as $$
declare
superObjectUuid uuid;
begin 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 % (%)', raise exception '[403] insert into hs_hosting_asset not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids(); currentSubjects(), currentSubjectsUuids();
end; $$; end; $$;
@ -148,15 +194,15 @@ end; $$;
create trigger hs_hosting_asset_insert_permission_check_tg create trigger hs_hosting_asset_insert_permission_check_tg
before insert on hs_hosting_asset before insert on hs_hosting_asset
for each row for each row
when ( not hasInsertPermission(NEW.bookingItemUuid, 'INSERT', 'hs_hosting_asset') ) execute procedure hs_hosting_asset_insert_permission_check_tf();
execute procedure hs_hosting_asset_insert_permission_missing_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-hosting-asset-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-hosting-asset-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_hosting_asset', call generateRbacIdentityViewFromQuery('hs_hosting_asset',
$idName$ $idName$
SELECT asset.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(asset.identifier) as idName SELECT asset.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(asset.identifier) as idName
FROM hs_hosting_asset asset FROM hs_hosting_asset asset
@ -164,6 +210,7 @@ create trigger hs_hosting_asset_insert_permission_check_tg
$idName$); $idName$);
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-hosting-asset-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --changeset hs-hosting-asset-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -18,6 +18,7 @@ declare
currentTask varchar; currentTask varchar;
relatedDebitor hs_office_debitor; relatedDebitor hs_office_debitor;
relatedBookingItem hs_booking_item; relatedBookingItem hs_booking_item;
managedServerUuid uuid;
begin begin
currentTask := 'creating hosting-asset test-data ' || givenPartnerNumber::text || givenDebitorSuffix; currentTask := 'creating hosting-asset test-data ' || givenPartnerNumber::text || givenDebitorSuffix;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
@ -33,14 +34,15 @@ begin
from hs_booking_item item from hs_booking_item item
where item.debitoruuid = relatedDebitor.uuid where item.debitoruuid = relatedDebitor.uuid
and item.caption = 'some PrivateCloud'; and item.caption = 'some PrivateCloud';
select uuid_generate_v4() into managedServerUuid;
raise notice 'creating test hosting-asset: %', givenPartnerNumber::text || givenDebitorSuffix::text; raise notice 'creating test hosting-asset: %', givenPartnerNumber::text || givenDebitorSuffix::text;
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
insert insert
into hs_hosting_asset (uuid, bookingitemuuid, type, identifier, caption, config) into hs_hosting_asset (uuid, bookingitemuuid, type, parentAssetUuid, identifier, caption, config)
values (uuid_generate_v4(), relatedBookingItem.uuid, 'MANAGED_SERVER'::HsHostingAssetType, 'vm10' || givenDebitorSuffix, 'some ManagedServer', '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), 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'::HsHostingAssetType, 'vm20' || givenDebitorSuffix, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "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'::HsHostingAssetType, givenWebspacePrefix || '01', 'some Webspace', '{ "RAM": 1, "SDD": 512, "HDD": 2048, "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; $$; end; $$;
--// --//

View File

@ -13,6 +13,8 @@ databaseChangeLog:
file: db/changelog/0-basis/006-numeric-hash-functions.sql file: db/changelog/0-basis/006-numeric-hash-functions.sql
- include: - include:
file: db/changelog/0-basis/007-table-columns.sql file: db/changelog/0-basis/007-table-columns.sql
- include:
file: db/changelog/0-basis/008-raise-functions.sql
- include: - include:
file: db/changelog/0-basis/009-check-environment.sql file: db/changelog/0-basis/009-check-environment.sql
- include: - include:

View File

@ -68,12 +68,13 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var count = assetRepo.count(); final var count = assetRepo.count();
final var givenBookingItem = givenBookingItem("First", "some CloudServer"); final var givenManagedServer = givenManagedServer("First", "some ManagedServer");
// when // when
final var result = attempt(em, () -> { final var result = attempt(em, () -> {
final var newAsset = HsHostingAssetEntity.builder() final var newAsset = HsHostingAssetEntity.builder()
.bookingItem(givenBookingItem) .bookingItem(givenManagedServer.getBookingItem())
.parentAsset(givenManagedServer)
.caption("some new managed webspace") .caption("some new managed webspace")
.type(HsHostingAssetType.MANAGED_WEBSPACE) .type(HsHostingAssetType.MANAGED_WEBSPACE)
.identifier("xyz90") .identifier("xyz90")
@ -96,14 +97,14 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream() final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream()
.map(s -> s.replace("hs_office_", "")) .map(s -> s.replace("hs_office_", ""))
.toList(); .toList();
final var givenBookingItem = givenBookingItem("First", "some CloudServer"); final var givenBookingItem = givenBookingItem("First", "some PrivateCloud");
// when // when
final var result = attempt(em, () -> { final var result = attempt(em, () -> {
final var newAsset = HsHostingAssetEntity.builder() final var newAsset = HsHostingAssetEntity.builder()
.bookingItem(givenBookingItem) .bookingItem(givenBookingItem)
.type(HsHostingAssetType.MANAGED_WEBSPACE) .type(HsHostingAssetType.MANAGED_SERVER)
.identifier("xyz91") .identifier("vm9000")
.caption("some new managed webspace") .caption("some new managed webspace")
.build(); .build();
return toCleanup(assetRepo.save(newAsset)); return toCleanup(assetRepo.save(newAsset));
@ -114,27 +115,27 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
final var all = rawRoleRepo.findAll(); final var all = rawRoleRepo.findAll();
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from( assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
initialRoleNames, initialRoleNames,
"hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN", "hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN",
"hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER", "hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:OWNER",
"hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT")); "hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT"));
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
.map(s -> s.replace("hs_office_", "")) .map(s -> s.replace("hs_office_", ""))
.containsExactlyInAnyOrder(fromFormatted( .containsExactlyInAnyOrder(fromFormatted(
initialGrantNames, initialGrantNames,
// global-admin
// owner // 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 // 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 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 role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER 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-someCloudServer-xyz91:OWNER to role:hs_booking_item#D-1000111-someCloudServer: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 // 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 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_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-somePrivateCloud:TENANT to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT 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 role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:TENANT to role:hs_hosting_asset#D-1000111-somePrivateCloud-vm9000:ADMIN by system and assume }",
null)); null));
} }
@ -161,7 +162,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
// then // then
allTheseServersAreReturned( allTheseServersAreReturned(
result, 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, 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 })"); "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: // then:
exactlyTheseAssetsAreReturned( exactlyTheseAssetsAreReturned(
result, 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, 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 })"); "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(); .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( void exactlyTheseAssetsAreReturned(
final List<HsHostingAssetEntity> actualResult, final List<HsHostingAssetEntity> actualResult,
final String... serverNames) { final String... serverNames) {