diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java index 18bada8e..478c10db 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java @@ -9,6 +9,7 @@ import static java.util.stream.Collectors.joining; import static net.hostsharing.hsadminng.rbac.rbacdef.PostgresTriggerReference.NEW; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.GUEST; import static net.hostsharing.hsadminng.rbac.rbacdef.StringWriter.with; import static org.apache.commons.lang3.StringUtils.capitalize; @@ -25,16 +26,16 @@ public class InsertTriggerGenerator { } void generateTo(final StringWriter plPgSql) { - generateInsertGrants(plPgSql); - generateInsertPermissionChecks(plPgSql); - } - - private void generateInsertGrants(final StringWriter plPgSql) { if (isInsertPermissionGrantedToGlobalGuest()) { // any user is allowed to insert new rows => no insert check needed return; } + generateInsertGrants(plPgSql); + generateInsertPermissionChecks(plPgSql); + } + + private void generateInsertGrants(final StringWriter plPgSql) { if (isInsertPermissionIsNotGrantedAtAll()) { generateInsertPermissionTriggerAlwaysDisallow(plPgSql); } else { @@ -185,20 +186,29 @@ public class InsertTriggerGenerator { getInsertGrants().forEach(g -> { final RbacView.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias(); - if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) { - final var caseCondition = g.isConditional() - ? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ") - : ""; - if (g.getSuperRoleDef().isGlobalAdmin()) { - plPgSql.writeLn( + final var caseCondition = g.isConditional() + ? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ") + : ""; + + if (g.getSuperRoleDef().isGlobal(GUEST)) { + plPgSql.writeLn( """ - -- check INSERT INSERT permission via isGlobalAdmin + -- 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 { + } else if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) { plPgSql.writeLn( """ -- check INSERT permission via direct foreign key: NEW.${refColumn} @@ -209,17 +219,17 @@ public class InsertTriggerGenerator { with("caseCondition", caseCondition), with("refColumn", superRoleEntityAlias.dependsOnColumName()), with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); - } } else { plPgSql.writeLn( """ -- check INSERT permission via indirect foreign key: NEW.${refColumn} superObjectUuid := (${fetchSql}); assert superObjectUuid is not null, 'object uuid fetched depending on ${rawSubTable}.${refColumn} must not be null, also check fetchSql in RBAC DSL'; - if hasInsertPermission(superObjectUuid, '${rawSubTable}') then + 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), diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index 757c862d..efa9d43a 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -604,9 +604,9 @@ public class RbacView { } boolean matchesCase(final ColumnValue requestedCase) { - final var noCasesDefined = forCases.isEmpty(); + final var noCasesDefined = forCases == null || forCases.isEmpty(); 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)); return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; } @@ -792,8 +792,8 @@ public class RbacView { return "role:" + entityAlias.aliasName + role; } - public boolean isGlobalAdmin() { - return entityAlias.isGlobal() && role == Role.ADMIN; + public boolean isGlobal(final Role role) { + return entityAlias.isGlobal() && this.role == role; } }