RBAC Diagram+PostgreSQL Generator #21
@ -1,6 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.rbac.rbacdef;
|
package net.hostsharing.hsadminng.rbac.rbacdef;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
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;
|
||||||
@ -95,10 +96,6 @@ public class InsertTriggerGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateInsertCheckTrigger(final StringWriter plPgSql) {
|
private void generateInsertCheckTrigger(final StringWriter plPgSql) {
|
||||||
rbacDef.getGrantDefs().stream()
|
|
||||||
.filter(g -> g.isToCreate() && g.grantType() == PERM_TO_ROLE &&
|
|
||||||
g.getPermDef().getPermission() == INSERT )
|
|
||||||
.forEach(g -> {
|
|
||||||
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}.
|
||||||
@ -107,24 +104,51 @@ public class InsertTriggerGenerator {
|
|||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
begin
|
begin
|
||||||
raise exception 'insert into ${rawSubTable} not allowed for current subjects %', currentSubjectsUuids();
|
raise exception 'insert into ${rawSubTable} not allowed for current subjects % (%)',
|
||||||
|
currentSubjects(), currentSubjectsUuids();
|
||||||
end; $$;
|
end; $$;
|
||||||
|
""",
|
||||||
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||||
|
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
||||||
|
plPgSql.writeLn("""
|
||||||
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 hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
|
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
|
||||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||||
""",
|
""",
|
||||||
with("rawSubTable", g.getPermDef().entityAlias.getRawTableName()),
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName() ));
|
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName() ));
|
||||||
|
},
|
||||||
|
() -> {
|
||||||
|
plPgSql.writeLn("""
|
||||||
|
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||||
|
before insert on ${rawSubTable}
|
||||||
|
for each row
|
||||||
|
-- As there is no explicit INSERT grant specified for this table,
|
||||||
|
-- only global admins are allowed to insert any rows.
|
||||||
|
when ( not isGlobalAdmin() )
|
||||||
|
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||||
|
""",
|
||||||
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<RbacView.RbacGrantDefinition> getInsertGrants() {
|
||||||
|
return rbacDef.getGrantDefs().stream()
|
||||||
|
.filter(g -> g.grantType() == PERM_TO_ROLE)
|
||||||
|
.filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<RbacView.RbacGrantDefinition> getOptionalInsertGrant() {
|
||||||
|
return getInsertGrants()
|
||||||
|
.reduce((x, y) -> {
|
||||||
|
throw new IllegalStateException("only a single INSERT permission grant allowed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<RbacView.RbacRoleDefinition> getOptionalInsertSuperRole() {
|
private Optional<RbacView.RbacRoleDefinition> getOptionalInsertSuperRole() {
|
||||||
return rbacDef.getGrantDefs().stream()
|
return getInsertGrants()
|
||||||
.filter(g -> g.grantType() == PERM_TO_ROLE)
|
|
||||||
.filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT)
|
|
||||||
.map(RbacView.RbacGrantDefinition::getSuperRoleDef)
|
.map(RbacView.RbacGrantDefinition::getSuperRoleDef)
|
||||||
.reduce((x, y) -> {
|
.reduce((x, y) -> {
|
||||||
throw new IllegalStateException("only a single INSERT permission grant allowed");
|
throw new IllegalStateException("only a single INSERT permission grant allowed");
|
||||||
|
@ -334,6 +334,7 @@ class RolesGrantsAndPermissionsGenerator {
|
|||||||
.map(RbacPermissionDefinition::getPermission)
|
.map(RbacPermissionDefinition::getPermission)
|
||||||
.map(RbacView.Permission::permission)
|
.map(RbacView.Permission::permission)
|
||||||
.map(p -> "'" + p + "'")
|
.map(p -> "'" + p + "'")
|
||||||
|
.sorted()
|
||||||
.toList();
|
.toList();
|
||||||
plPgSql.indented(() ->
|
plPgSql.indented(() ->
|
||||||
plPgSql.writeLn("permissions => array[" + joinArrayElements(arrayElements, 3) + "],\n"));
|
plPgSql.writeLn("permissions => array[" + joinArrayElements(arrayElements, 3) + "],\n"));
|
||||||
|
@ -22,6 +22,19 @@ grant select on global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
|||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset rbac-global-IS-GLOBAL-ADMIN:1 endDelimiter:--//
|
||||||
|
-- ------------------------------------------------------------------
|
||||||
|
|
||||||
|
create or replace function isGlobalAdmin()
|
||||||
|
returns boolean
|
||||||
|
language plpgsql as $$
|
||||||
|
begin
|
||||||
|
return isGranted(currentSubjectsUuids(), findRoleId(globalAdmin()));
|
||||||
|
end; $$;
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset rbac-global-HAS-GLOBAL-PERMISSION:1 endDelimiter:--//
|
--changeset rbac-global-HAS-GLOBAL-PERMISSION:1 endDelimiter:--//
|
||||||
-- ------------------------------------------------------------------
|
-- ------------------------------------------------------------------
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
--liquibase formatted sql
|
--liquibase formatted sql
|
||||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-06T15:40:13.239729250.
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-07T12:25:36.376742633.
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
@ -80,6 +80,25 @@ execute procedure insertTriggerForTestCustomer_tf();
|
|||||||
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Checks if the user or assumed roles are allowed to insert a row to test_customer.
|
||||||
|
*/
|
||||||
|
create or replace function test_customer_insert_permission_missing_tf()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql as $$
|
||||||
|
begin
|
||||||
|
raise exception 'insert into test_customer not allowed for current subjects % (%)',
|
||||||
|
currentSubjects(), currentSubjectsUuids();
|
||||||
|
end; $$;
|
||||||
|
|
||||||
|
create trigger test_customer_insert_permission_check_tg
|
||||||
|
before insert on test_customer
|
||||||
|
for each row
|
||||||
|
-- As there is no explicit INSERT grant specified for this table,
|
||||||
|
-- only global admins are allowed to insert any rows.
|
||||||
|
when ( not isGlobalAdmin() )
|
||||||
|
execute procedure test_customer_insert_permission_missing_tf();
|
||||||
|
|
||||||
--//
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
--liquibase formatted sql
|
--liquibase formatted sql
|
||||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-06T15:40:13.277446553.
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-07T12:25:36.422351715.
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
@ -194,7 +194,8 @@ create or replace function test_package_insert_permission_missing_tf()
|
|||||||
returns trigger
|
returns trigger
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
begin
|
begin
|
||||||
raise exception 'insert into test_package not allowed for current subjects %', currentSubjectsUuids();
|
raise exception 'insert into test_package not allowed for current subjects % (%)',
|
||||||
|
currentSubjects(), currentSubjectsUuids();
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
create trigger test_package_insert_permission_check_tg
|
create trigger test_package_insert_permission_check_tg
|
||||||
|
@ -74,7 +74,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(
|
result.assertExceptionWithRootCauseMessage(
|
||||||
PersistenceException.class,
|
PersistenceException.class,
|
||||||
"add-customer not permitted for test_customer#xxx.admin");
|
"ERROR: insert into test_customer not allowed for current subjects {test_customer#xxx.admin}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -92,7 +92,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(
|
result.assertExceptionWithRootCauseMessage(
|
||||||
PersistenceException.class,
|
PersistenceException.class,
|
||||||
"add-customer not permitted for customer-admin@xxx.example.com");
|
"ERROR: insert into test_customer not allowed for current subjects {customer-admin@xxx.example.com}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user