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
2 changed files with 29 additions and 19 deletions
Showing only changes of commit fc07f64e1f - Show all commits

View File

@ -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.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.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;
@ -25,16 +26,16 @@ public class InsertTriggerGenerator {
} }
void generateTo(final StringWriter plPgSql) { void generateTo(final StringWriter plPgSql) {
generateInsertGrants(plPgSql);
generateInsertPermissionChecks(plPgSql);
}
private void generateInsertGrants(final StringWriter plPgSql) {
if (isInsertPermissionGrantedToGlobalGuest()) { if (isInsertPermissionGrantedToGlobalGuest()) {
// any user is allowed to insert new rows => no insert check needed // any user is allowed to insert new rows => no insert check needed
return; return;
} }
generateInsertGrants(plPgSql);
generateInsertPermissionChecks(plPgSql);
}
private void generateInsertGrants(final StringWriter plPgSql) {
if (isInsertPermissionIsNotGrantedAtAll()) { if (isInsertPermissionIsNotGrantedAtAll()) {
generateInsertPermissionTriggerAlwaysDisallow(plPgSql); generateInsertPermissionTriggerAlwaysDisallow(plPgSql);
} else { } else {
@ -185,20 +186,29 @@ public class InsertTriggerGenerator {
getInsertGrants().forEach(g -> { getInsertGrants().forEach(g -> {
final RbacView.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias(); final RbacView.EntityAlias superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias();
if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) { final var caseCondition = g.isConditional()
final var caseCondition = g.isConditional() ? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ")
? ("NEW.type in (" + toStringList(g.getForCases()) + ") and ") : "";
: "";
if (g.getSuperRoleDef().isGlobalAdmin()) { if (g.getSuperRoleDef().isGlobal(GUEST)) {
plPgSql.writeLn( 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 if ${caseCondition}isGlobalAdmin() then
return NEW; return NEW;
end if; end if;
""", """,
with("caseCondition", caseCondition)); with("caseCondition", caseCondition));
} else { } else if (g.getSuperRoleDef().getEntityAlias().isFetchedByDirectForeignKey()) {
plPgSql.writeLn( plPgSql.writeLn(
""" """
-- check INSERT permission via direct foreign key: NEW.${refColumn} -- check INSERT permission via direct foreign key: NEW.${refColumn}
@ -209,17 +219,17 @@ public class InsertTriggerGenerator {
with("caseCondition", caseCondition), with("caseCondition", caseCondition),
with("refColumn", superRoleEntityAlias.dependsOnColumName()), with("refColumn", superRoleEntityAlias.dependsOnColumName()),
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName())); with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
}
} else { } else {
plPgSql.writeLn( plPgSql.writeLn(
""" """
-- check INSERT permission via indirect foreign key: NEW.${refColumn} -- check INSERT permission via indirect foreign key: NEW.${refColumn}
superObjectUuid := (${fetchSql}); superObjectUuid := (${fetchSql});
assert superObjectUuid is not null, 'object uuid fetched depending on ${rawSubTable}.${refColumn} must not be null, also check fetchSql in RBAC DSL'; 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; return NEW;
end if; end if;
""", """,
with("caseCondition", caseCondition),
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()), with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
with("refColumn", superRoleEntityAlias.dependsOnColumName()), with("refColumn", superRoleEntityAlias.dependsOnColumName()),
with("fetchSql", g.getSuperRoleDef().getEntityAlias().fetchSql().sql), with("fetchSql", g.getSuperRoleDef().getEntityAlias().fetchSql().sql),

View File

@ -604,9 +604,9 @@ public class RbacView {
} }
boolean matchesCase(final ColumnValue requestedCase) { boolean matchesCase(final ColumnValue requestedCase) {
final var noCasesDefined = forCases.isEmpty(); final var noCasesDefined = forCases == null || forCases.isEmpty();
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));
return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; return noCasesDefined || generateForAllCases || isGrantedForRequestedCase;
} }
@ -792,8 +792,8 @@ public class RbacView {
return "role:" + entityAlias.aliasName + role; return "role:" + entityAlias.aliasName + role;
} }
public boolean isGlobalAdmin() { public boolean isGlobal(final Role role) {
return entityAlias.isGlobal() && role == Role.ADMIN; return entityAlias.isGlobal() && this.role == role;
} }
} }