improved RBAC generators #26
@ -113,8 +113,17 @@ public class InsertTriggerGenerator {
|
||||
"invalid global role for INSERT permission: " + g.getSuperRoleDef().getRole());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final var superRoleEntityAlias = g.getSuperRoleDef().getEntityAlias();
|
||||
|
||||
// TODO: Maybe this should depend on the indirection degree of the fetchSql?
|
||||
// Maybe we need a separate fetchedBy method for all the simple, direct cases?
|
||||
if (superRoleEntityAlias.fetchSql().sql.contains("JOIN ")) {
|
||||
generateInsertPermissionTriggerAllowByRoleOfIndirectForeignKey(plPgSql, g);
|
||||
} else {
|
||||
generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(plPgSql, g);
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
@ -149,6 +158,50 @@ public class InsertTriggerGenerator {
|
||||
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 FIXME.
|
||||
*/
|
||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if ( not hasInsertPermission(
|
||||
( SELECT ${varName}.uuid FROM
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()));
|
||||
plPgSql.indented(3, () -> {
|
||||
plPgSql.writeLn(
|
||||
"(" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ") AS ${varName}",
|
||||
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()),
|
||||
with("ref", NEW.name()));
|
||||
});
|
||||
plPgSql.writeLn("""
|
||||
|
||||
), '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_missing_tf();
|
||||
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||
}
|
||||
|
||||
private void generateInsertPermissionTriggerAllowOnlyGlobalAdmin(final StringWriter plPgSql) {
|
||||
plPgSql.writeLn("""
|
||||
/**
|
||||
|
@ -1033,6 +1033,23 @@ public class RbacView {
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateRbacView(final Class<? extends HasUuid> c) {
|
||||
final Method mainMethod = stream(c.getMethods()).filter(
|
||||
m -> isStatic(m.getModifiers()) && m.getName().equals("main")
|
||||
)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (mainMethod != null) {
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { null });
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
System.err.println("WARNING: no main method in: " + c.getName() + " => no RBAC rules generated");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This main method generates the RbacViews (PostgreSQL+diagram) for all given entity classes.
|
||||
*/
|
||||
@ -1052,21 +1069,6 @@ public class RbacView {
|
||||
HsOfficeSepaMandateEntity.class,
|
||||
HsOfficeCoopSharesTransactionEntity.class,
|
||||
HsOfficeMembershipEntity.class
|
||||
).forEach(c -> {
|
||||
final Method mainMethod = stream(c.getMethods()).filter(
|
||||
m -> isStatic(m.getModifiers()) && m.getName().equals("main")
|
||||
)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (mainMethod != null) {
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { null });
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
System.err.println("WARNING: no main method in: " + c.getName() + " => no RBAC rules generated");
|
||||
}
|
||||
});
|
||||
).forEach(RbacView::generateRbacView);
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,9 @@ spring:
|
||||
platform: postgres
|
||||
|
||||
datasource:
|
||||
url: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url-tc: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url-local: jdbc:postgresql://localhost:5432/postgres
|
||||
url: ${spring.datasource.url-tc}
|
||||
username: postgres
|
||||
password: password
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user