From d40cf019cce30bc780ec9257511465c76c9e096b Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 8 Mar 2024 13:21:00 +0100 Subject: [PATCH] implement assumed in Generator --- .../hsadminng/rbac/rbacdef/RbacView.java | 5 +- .../rbacdef/RbacViewMermaidFlowchart.java | 5 +- .../RolesGrantsAndPermissionsGenerator.java | 27 +++++---- .../test/cust/TestCustomerEntity.java | 4 +- .../hsadminng/test/pac/TestPackageEntity.java | 3 +- .../resources/db/changelog/050-rbac-base.sql | 24 +++++++- .../db/changelog/057-rbac-role-builder.sql | 34 ++++------- .../db/changelog/058-rbac-generators.sql | 22 +++---- .../db/changelog/080-rbac-global.sql | 4 +- .../db/changelog/113-test-customer-rbac.md | 41 +++++++++++++ .../db/changelog/113-test-customer-rbac.sql | 4 +- .../db/changelog/123-test-package-rbac.md | 57 +++++++++++++++++++ .../db/changelog/123-test-package-rbac.sql | 2 +- .../hsadminng/context/ContextBasedTest.java | 19 ++++++- .../test/cust/TestCustomerEntityTest.java | 4 +- ...TestCustomerRepositoryIntegrationTest.java | 19 +------ .../test/pac/TestPackageEntityTest.java | 13 ++--- .../TestPackageRepositoryIntegrationTest.java | 13 ++--- 18 files changed, 203 insertions(+), 97 deletions(-) create mode 100644 src/main/resources/db/changelog/113-test-customer-rbac.md create mode 100644 src/main/resources/db/changelog/123-test-package-rbac.md 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 064a7350..5dd52c71 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -197,7 +197,7 @@ public class RbacView { }); importedRbacView.getGrantDefs().forEach(grantDef -> { if (grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE) { - findOrCreateGrantDef( + final var importedGrantDef = findOrCreateGrantDef( findRbacRole( mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName), grantDef.getSubRoleDef().getRole()), @@ -205,6 +205,9 @@ public class RbacView { mapper.map(grantDef.getSuperRoleDef().entityAlias.aliasName), grantDef.getSuperRoleDef().getRole()) ); + if (!grantDef.isAssumed()) { + importedGrantDef.unassumed(); + } } }); return this; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchart.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchart.java index 27615f85..9a806cc4 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchart.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchart.java @@ -109,9 +109,8 @@ public class RbacViewMermaidFlowchart { } private String grantDef(final RbacView.RbacGrantDefinition grant) { - final var arrow = grant.isToCreate() - ? grant.isAssumed() ? " ==> " : " == /// ==> " - : grant.isAssumed() ? " -.-> " : " -.- /// -.-> "; + final var arrow = (grant.isToCreate() ? " ==>" : " -.->") + + (grant.isAssumed() ? " " : "|XX| "); return switch (grant.grantType()) { case ROLE_TO_USER -> // TODO: other user types not implemented yet diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 20377ac4..edb1f609 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -230,7 +230,8 @@ class RolesGrantsAndPermissionsGenerator { private String generateGrant(RbacView.RbacGrantDefinition grantDef) { return switch (grantDef.grantType()) { case ROLE_TO_USER -> throw new IllegalArgumentException("unexpected grant"); - case ROLE_TO_ROLE -> "call grantRoleToRole(${subRoleRef}, ${superRoleRef});" + case ROLE_TO_ROLE -> "call grantRoleToRole(${subRoleRef}, ${superRoleRef}${assumed});" + .replace("${assumed}", grantDef.isAssumed() ? "" : ", unassumed()") .replace("${subRoleRef}", roleRef(NEW, grantDef.getSubRoleDef())) .replace("${superRoleRef}", roleRef(NEW, grantDef.getSuperRoleDef())); case PERM_TO_ROLE -> @@ -345,12 +346,11 @@ class RolesGrantsAndPermissionsGenerator { private void generateIncomingSuperRolesForRole(final StringWriter plPgSql, final RbacView.Role role) { final var incomingGrants = findIncomingSuperRolesForRole(rbacDef.getRootEntityAlias(), role); if (!incomingGrants.isEmpty()) { - final var arraElements = incomingGrants.stream() - .map(RbacView.RbacGrantDefinition::getSuperRoleDef) - .map(r -> toPlPgSqlReference(NEW, r)) + final var arrayElements = incomingGrants.stream() + .map(g -> toPlPgSqlReference(NEW, g.getSuperRoleDef(), g.isAssumed())) .toList(); plPgSql.indented(() -> - plPgSql.writeLn("incomingSuperRoles => array[" + joinArrayElements(arraElements, 1) + "],\n")); + plPgSql.writeLn("incomingSuperRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n")); rbacGrants.removeAll(incomingGrants); } } @@ -359,8 +359,7 @@ class RolesGrantsAndPermissionsGenerator { final var outgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getRootEntityAlias(), role); if (!outgoingGrants.isEmpty()) { final var arrayElements = outgoingGrants.stream() - .map(RbacView.RbacGrantDefinition::getSubRoleDef) - .map(r -> toPlPgSqlReference(NEW, r)) + .map(g -> toPlPgSqlReference(NEW, g.getSubRoleDef(), g.isAssumed())) .toList(); plPgSql.indented(() -> plPgSql.writeLn("outgoingSubRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n")); @@ -485,14 +484,18 @@ class RolesGrantsAndPermissionsGenerator { }; } - private String toPlPgSqlReference(final PostgresTriggerReference triggerRef, final RbacView.RbacRoleDefinition roleDef) { - return toVar(roleDef) + - (roleDef.getEntityAlias().isGlobal() ? "()" + private String toPlPgSqlReference( + final PostgresTriggerReference triggerRef, + final RbacView.RbacRoleDefinition roleDef, + final boolean assumed) { + final var assumedArg = assumed ? "" : ", unassumed()"; + return toRoleRef(roleDef) + + (roleDef.getEntityAlias().isGlobal() ? ( assumed ? "()" : "(unassumed())") : rbacDef.isRootEntityAlias(roleDef.getEntityAlias()) ? ("(" + triggerRef.name() + ")") - : "(" + toTriggerReference(triggerRef, roleDef.getEntityAlias()) + ")"); + : "(" + toTriggerReference(triggerRef, roleDef.getEntityAlias()) + assumedArg + ")"); } - private static String toVar(final RbacView.RbacRoleDefinition roleDef) { + private static String toRoleRef(final RbacView.RbacRoleDefinition roleDef) { return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName()); } diff --git a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java index 21a5f650..bde8db09 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java @@ -43,8 +43,8 @@ public class TestCustomerEntity implements HasUuid { .withUpdatableColumns("reference", "prefix", "adminUserName") .createRole(OWNER, (with) -> { - with.owningUser(CREATOR); - with.incomingSuperRole(GLOBAL, ADMIN); + with.owningUser(CREATOR).unassumed(); + with.incomingSuperRole(GLOBAL, ADMIN).unassumed(); with.permission(DELETE); }) .createSubRole(ADMIN, (with) -> { diff --git a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java index acbbc6ec..757fcf05 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java @@ -15,7 +15,6 @@ import java.util.UUID; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; @@ -58,7 +57,7 @@ public class TestPackageEntity implements HasUuid { .toRole("customer", ADMIN).grantPermission("package", INSERT) .createRole(OWNER, (with) -> { - with.incomingSuperRole("customer", ADMIN).unassumed(); + with.incomingSuperRole("customer", ADMIN); with.permission(DELETE); with.permission(UPDATE); }) diff --git a/src/main/resources/db/changelog/050-rbac-base.sql b/src/main/resources/db/changelog/050-rbac-base.sql index 44e5cba9..f3b784c8 100644 --- a/src/main/resources/db/changelog/050-rbac-base.sql +++ b/src/main/resources/db/changelog/050-rbac-base.sql @@ -203,15 +203,33 @@ create type RbacRoleDescriptor as ( objectTable varchar(63), -- for human readability and easier debugging objectUuid uuid, - roleType RbacRoleType + roleType RbacRoleType, + assumed boolean ); -create or replace function roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType) +create or replace function assumed() + returns boolean + stable -- leakproof + language sql as $$ + select true; +$$; + +create or replace function unassumed() + returns boolean + stable -- leakproof + language sql as $$ +select false; +$$; + + +create or replace function roleDescriptor( + objectTable varchar(63), objectUuid uuid, roleType RbacRoleType, + assumed boolean = true) -- just for DSL readability, belongs actually to the grant returns RbacRoleDescriptor returns null on null input stable -- leakproof language sql as $$ -select objectTable, objectUuid, roleType::RbacRoleType; + select objectTable, objectUuid, roleType::RbacRoleType, assumed; $$; create or replace function createRole(roleDescriptor RbacRoleDescriptor) diff --git a/src/main/resources/db/changelog/057-rbac-role-builder.sql b/src/main/resources/db/changelog/057-rbac-role-builder.sql index 93b36909..221919a3 100644 --- a/src/main/resources/db/changelog/057-rbac-role-builder.sql +++ b/src/main/resources/db/changelog/057-rbac-role-builder.sql @@ -13,24 +13,6 @@ begin return createPermissions(forObjectUuid, permitOps); end; $$; -create or replace function toRoleUuids(roleDescriptors RbacRoleDescriptor[]) - returns uuid[] - language plpgsql - strict as $$ -declare - superRoleDescriptor RbacRoleDescriptor; - superRoleUuids uuid[] := array []::uuid[]; -begin - foreach superRoleDescriptor in array roleDescriptors - loop - if superRoleDescriptor is not null then - superRoleUuids := superRoleUuids || getRoleId(superRoleDescriptor, 'fail'); - end if; - end loop; - - return superRoleUuids; -end; $$; - -- ================================================================= -- CREATE ROLE @@ -50,25 +32,29 @@ create or replace function createRoleWithGrants( language plpgsql as $$ declare roleUuid uuid; - superRoleUuid uuid; + subRoleDesc RbacRoleDescriptor; + superRoleDesc RbacRoleDescriptor; subRoleUuid uuid; + superRoleUuid uuid; userUuid uuid; grantedByRoleUuid uuid; begin roleUuid := createRole(roleDescriptor); - if cardinality(permissions) >0 then + if cardinality(permissions) > 0 then call grantPermissionsToRole(roleUuid, toPermissionUuids(roleDescriptor.objectuuid, permissions)); end if; - foreach superRoleUuid in array toRoleUuids(incomingSuperRoles) + foreach superRoleDesc in array incomingSuperRoles loop - call grantRoleToRole(roleUuid, superRoleUuid); + superRoleUuid = getRoleId(superRoleDesc, 'fail'); + call grantRoleToRole(roleUuid, superRoleUuid, superRoleDesc.assumed); end loop; - foreach subRoleUuid in array toRoleUuids(outgoingSubRoles) + foreach subRoleDesc in array outgoingSubRoles loop - call grantRoleToRole(subRoleUuid, roleUuid); + subRoleUuid = getRoleId(subRoleDesc, 'fail'); + call grantRoleToRole(subRoleUuid, roleUuid, subRoleDesc.assumed); end loop; if cardinality(userUuids) > 0 then diff --git a/src/main/resources/db/changelog/058-rbac-generators.sql b/src/main/resources/db/changelog/058-rbac-generators.sql index d77d1f20..4f4fb086 100644 --- a/src/main/resources/db/changelog/058-rbac-generators.sql +++ b/src/main/resources/db/changelog/058-rbac-generators.sql @@ -35,50 +35,50 @@ end; $$; --changeset rbac-generators-ROLE-DESCRIPTORS:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -create or replace procedure generateRbacRoleDescriptors(prefix text, targetTable text) +create procedure generateRbacRoleDescriptors(prefix text, targetTable text) language plpgsql as $$ declare sql text; begin sql = format($sql$ - create or replace function %1$sOwner(entity %2$s) + create or replace function %1$sOwner(entity %2$s, assumed boolean = true) returns RbacRoleDescriptor language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'owner'); + return roleDescriptor('%2$s', entity.uuid, 'owner', assumed); end; $f$; - create or replace function %1$sAdmin(entity %2$s) + create or replace function %1$sAdmin(entity %2$s, assumed boolean = true) returns RbacRoleDescriptor language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'admin'); + return roleDescriptor('%2$s', entity.uuid, 'admin', assumed); end; $f$; - create or replace function %1$sAgent(entity %2$s) + create or replace function %1$sAgent(entity %2$s, assumed boolean = true) returns RbacRoleDescriptor language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'agent'); + return roleDescriptor('%2$s', entity.uuid, 'agent', assumed); end; $f$; - create or replace function %1$sTenant(entity %2$s) + create or replace function %1$sTenant(entity %2$s, assumed boolean = true) returns RbacRoleDescriptor language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'tenant'); + return roleDescriptor('%2$s', entity.uuid, 'tenant', assumed); end; $f$; - create or replace function %1$sGuest(entity %2$s) + create or replace function %1$sGuest(entity %2$s, assumed boolean = true) returns RbacRoleDescriptor language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'guest'); + return roleDescriptor('%2$s', entity.uuid, 'guest', assumed); end; $f$; $sql$, prefix, targetTable); diff --git a/src/main/resources/db/changelog/080-rbac-global.sql b/src/main/resources/db/changelog/080-rbac-global.sql index a262791c..8313d05d 100644 --- a/src/main/resources/db/changelog/080-rbac-global.sql +++ b/src/main/resources/db/changelog/080-rbac-global.sql @@ -109,12 +109,12 @@ commit; /* A global administrator role. */ -create or replace function globalAdmin() +create or replace function globalAdmin(assumed boolean = true) returns RbacRoleDescriptor returns null on null input stable -- leakproof language sql as $$ -select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType; +select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType, assumed; $$; begin transaction; diff --git a/src/main/resources/db/changelog/113-test-customer-rbac.md b/src/main/resources/db/changelog/113-test-customer-rbac.md new file mode 100644 index 00000000..29e360a6 --- /dev/null +++ b/src/main/resources/db/changelog/113-test-customer-rbac.md @@ -0,0 +1,41 @@ +### rbac customer 2024-03-08T13:03:39.397294085 + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph customer["`**customer**`"] + direction TB + style customer fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph customer:roles[ ] + style customer:roles fill:#dd4901,stroke:white + + role:customer:owner[[customer:owner]] + role:customer:admin[[customer:admin]] + role:customer:tenant[[customer:tenant]] + end + + subgraph customer:permissions[ ] + style customer:permissions fill:#dd4901,stroke:white + + perm:customer:DELETE{{customer:DELETE}} + perm:customer:UPDATE{{customer:UPDATE}} + perm:customer:SELECT{{customer:SELECT}} + end +end + +%% granting roles to users +user:creator ==>|XX| role:customer:owner + +%% granting roles to roles +role:global:admin ==>|XX| role:customer:owner +role:customer:owner ==> role:customer:admin +role:customer:admin ==> role:customer:tenant + +%% granting permissions to roles +role:customer:owner ==> perm:customer:DELETE +role:customer:admin ==> perm:customer:UPDATE +role:customer:tenant ==> perm:customer:SELECT + +``` diff --git a/src/main/resources/db/changelog/113-test-customer-rbac.sql b/src/main/resources/db/changelog/113-test-customer-rbac.sql index da24ae34..2bdaf47a 100644 --- a/src/main/resources/db/changelog/113-test-customer-rbac.sql +++ b/src/main/resources/db/changelog/113-test-customer-rbac.sql @@ -1,5 +1,5 @@ --liquibase formatted sql --- This code generated was by RbacViewPostgresGenerator at 2024-03-08T08:48:56.112505380. +-- This code generated was by RbacViewPostgresGenerator at 2024-03-08T13:03:39.428165899. -- ============================================================================ --changeset test-customer-rbac-OBJECT:1 endDelimiter:--// @@ -37,7 +37,7 @@ begin testCustomerOwner(NEW), permissions => array['DELETE'], userUuids => array[currentUserUuid()], - incomingSuperRoles => array[globalAdmin()] + incomingSuperRoles => array[globalAdmin(unassumed())] ); perform createRoleWithGrants( diff --git a/src/main/resources/db/changelog/123-test-package-rbac.md b/src/main/resources/db/changelog/123-test-package-rbac.md new file mode 100644 index 00000000..42950bd0 --- /dev/null +++ b/src/main/resources/db/changelog/123-test-package-rbac.md @@ -0,0 +1,57 @@ +### rbac package 2024-03-08T13:03:39.472333368 + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph package["`**package**`"] + direction TB + style package fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph package:roles[ ] + style package:roles fill:#dd4901,stroke:white + + role:package:owner[[package:owner]] + role:package:admin[[package:admin]] + role:package:tenant[[package:tenant]] + end + + subgraph package:permissions[ ] + style package:permissions fill:#dd4901,stroke:white + + perm:package:INSERT{{package:INSERT}} + perm:package:DELETE{{package:DELETE}} + perm:package:UPDATE{{package:UPDATE}} + perm:package:SELECT{{package:SELECT}} + 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 +role:global:admin -.->|XX| role:customer:owner +role:customer:owner -.-> role:customer:admin +role:customer:admin -.-> role:customer:tenant +role:customer:admin ==> role:package:owner +role:package:owner ==> role:package:admin +role:package:admin ==> role:package:tenant +role:package:tenant ==> role:customer:tenant + +%% granting permissions to roles +role:customer:admin ==> perm:package:INSERT +role:package:owner ==> perm:package:DELETE +role:package:owner ==> perm:package:UPDATE +role:package:tenant ==> perm:package:SELECT + +``` diff --git a/src/main/resources/db/changelog/123-test-package-rbac.sql b/src/main/resources/db/changelog/123-test-package-rbac.sql index 950acef8..0f071c9e 100644 --- a/src/main/resources/db/changelog/123-test-package-rbac.sql +++ b/src/main/resources/db/changelog/123-test-package-rbac.sql @@ -1,5 +1,5 @@ --liquibase formatted sql --- This code generated was by RbacViewPostgresGenerator at 2024-03-08T08:48:56.148164198. +-- This code generated was by RbacViewPostgresGenerator at 2024-03-08T13:03:39.473061981. -- ============================================================================ --changeset test-package-rbac-OBJECT:1 endDelimiter:--// diff --git a/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java b/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java index a1f4cfbc..7f08f044 100644 --- a/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java +++ b/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java @@ -6,14 +6,31 @@ import org.junit.jupiter.api.TestInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Import; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; + @Import(RbacGrantsDiagramService.class) public abstract class ContextBasedTest { @Autowired protected Context context; + @PersistenceContext + protected EntityManager em; // just to be used in subclasses + + /** + * To generate a flowchart diagram from the database use something like this in a defined context: + +
+     RbacGrantsDiagramService.writeToFile(
+         "title",
+         diagramService.allGrantsToCurrentUser(of(RbacGrantsDiagramService.Include.USERS, RbacGrantsDiagramService.Include.TEST_ENTITIES, RbacGrantsDiagramService.Include.NOT_ASSUMED, RbacGrantsDiagramService.Include.DETAILS, RbacGrantsDiagramService.Include.PERMISSIONS)),
+         "filename.md
+     );
+    
+ */ @Autowired - protected RbacGrantsDiagramService diagramService; + protected RbacGrantsDiagramService diagramService; // just to be used in subclasses TestInfo test; diff --git a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityTest.java b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityTest.java index 4ff123d5..7094530e 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityTest.java @@ -36,10 +36,10 @@ class TestCustomerEntityTest { end %% granting roles to users - user:creator ==> role:customer:owner + user:creator ==>|XX| role:customer:owner %% granting roles to roles - role:global:admin ==> role:customer:owner + role:global:admin ==>|XX| role:customer:owner role:customer:owner ==> role:customer:admin role:customer:admin ==> role:customer:tenant diff --git a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java index 01aa0760..27458b14 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java @@ -2,8 +2,6 @@ package net.hostsharing.hsadminng.test.cust; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.ContextBasedTest; -import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; -import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService.Include; import net.hostsharing.test.JpaAttempt; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -12,14 +10,11 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceException; import jakarta.servlet.http.HttpServletRequest; import java.util.List; import java.util.UUID; -import static java.util.EnumSet.of; import static net.hostsharing.test.JpaAttempt.attempt; import static org.assertj.core.api.Assertions.assertThat; @@ -30,9 +25,6 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { @Autowired TestCustomerRepository testCustomerRepository; - @PersistenceContext - EntityManager em; - @MockBean HttpServletRequest request; @@ -118,15 +110,15 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { } @Test - public void globalAdmin_withAssumedglobalAdminRole_canViewAllCustomers() { + public void globalAdmin_withAssumedCustomerOwnerRole_canViewExactlyThatCustomer() { given: - context("superuser-alex@hostsharing.net", "global#global.admin"); + context("superuser-alex@hostsharing.net", "test_customer#yyy.owner"); // when final var result = testCustomerRepository.findCustomerByOptionalPrefixLike(null); then: - allTheseCustomersAreReturned(result, "xxx", "yyy", "zzz"); + allTheseCustomersAreReturned(result, "yyy"); } @Test @@ -144,11 +136,6 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { @Test public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnCustomer() { context("customer-admin@xxx.example.com"); - RbacGrantsDiagramService.writeToFile( - "customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnCustomer", - diagramService.allGrantsToCurrentUser(of(Include.USERS, Include.TEST_ENTITIES, Include.NOT_ASSUMED, Include.DETAILS, Include.PERMISSIONS)), - "doc/customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnCustomer.md" - ); context("customer-admin@xxx.example.com", "test_package#xxx00.admin"); diff --git a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityTest.java b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityTest.java index 534da710..392d0274 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityTest.java @@ -35,7 +35,7 @@ class TestPackageEntityTest { perm:package:SELECT{{package:SELECT}} end end - + subgraph customer["`**customer**`"] direction TB style customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px @@ -48,19 +48,16 @@ class TestPackageEntityTest { role:customer:tenant[[customer:tenant]] end end - - %% granting roles to users - user:creator ==> role:package:owner - + %% granting roles to roles - role:global:admin -.-> role:customer:owner + role:global:admin -.->|XX| role:customer:owner role:customer:owner -.-> role:customer:admin role:customer:admin -.-> role:customer:tenant - role:customer:admin == /// ==> role:package:owner + role:customer:admin ==> role:package:owner role:package:owner ==> role:package:admin role:package:admin ==> role:package:tenant role:package:tenant ==> role:customer:tenant - + %% granting permissions to roles role:customer:admin ==> perm:package:INSERT role:package:owner ==> perm:package:DELETE diff --git a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java index 89c6f993..a201d79e 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java @@ -1,6 +1,7 @@ package net.hostsharing.hsadminng.test.pac; import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.context.ContextBasedTest; import net.hostsharing.test.JpaAttempt; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -19,10 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest @Import( { Context.class, JpaAttempt.class }) -class TestPackageRepositoryIntegrationTest { - - @Autowired - Context context; +class TestPackageRepositoryIntegrationTest extends ContextBasedTest { @Autowired TestPackageRepository testPackageRepository; @@ -40,9 +38,10 @@ class TestPackageRepositoryIntegrationTest { class FindAllByOptionalNameLike { @Test - public void globalAdmin_withoutAssumedRole_canNotViewAnyPackages_becauseThoseGrantsAreNotassumedd() { + public void globalAdmin_withoutAssumedRole_canNotViewAnyPackages_becauseThoseGrantsAreNotAssumed() { // given - context.define("superuser-alex@hostsharing.net"); + // alex is not just global-admin but lso the creating user, thus we use fran + context.define("superuser-fran@hostsharing.net"); // when final var result = testPackageRepository.findAllByOptionalNameLike(null); @@ -52,7 +51,7 @@ class TestPackageRepositoryIntegrationTest { } @Test - public void globalAdmin_withAssumedglobalAdminRole__canNotViewAnyPackages_becauseThoseGrantsAreNotassumedd() { + public void globalAdmin_withAssumedglobalAdminRole__canNotViewAnyPackages_becauseThoseGrantsAreNotAssumed() { given: context.define("superuser-alex@hostsharing.net", "global#global.admin");