diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantEntity.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantEntity.java similarity index 97% rename from src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantEntity.java rename to src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantEntity.java index 6dc8d1ce..cea9c4c5 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantEntity.java @@ -1,13 +1,13 @@ package net.hostsharing.hsadminng.rbac.rbacgrant; import lombok.*; -import org.jetbrains.annotations.NotNull; import org.springframework.data.annotation.Immutable; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.UUID; diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantRepository.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantRepository.java similarity index 100% rename from src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantRepository.java rename to src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RawRbacGrantRepository.java diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java index 0e39c546..211c8b43 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java @@ -103,28 +103,8 @@ public class RbacGrantController implements RbacGrantsApi { // public ResponseEntity allGrantsOfUserAsMermaid( // @RequestHeader(name = "current-user") String currentUser, // @RequestHeader(name = "assumed-roles", required = false) String assumedRoles) { -// context(currentUser); -// final var graph = new ArrayList(); -// traverseGrantsTo( graph, context.getCurrentUserUUid()); -// return ResponseEntity.ok("flowchart TB\n\n" + String.join("\n", graph)); -// } -// -// private void traverseGrantsTo(final ArrayList graph, final UUID refUuid) { -// final var grants = rawGrantRepo.findByAscendingUuid(refUuid); -// grants.forEach(g -> { -// graph.add( -// id(g.getAscendantIdName()) + -// (g.isAssumed() ? " --> " : " -.-> " ) + -// id(g.getDescendantIdName())); -// traverseGrantsTo(graph, g.getDescendantUuid()); -// }); -// } -// -// private String id(final String idName) { -// if ( idName.contains("@")) { -// return quoted(idName).replaceAll("@.*", "") + "[" + quoted(idName) + "]"; -// } -// return quoted(idName); +// final var graph = RbacGrantsMermaidService.allGrantsToUser(currentUser); +// return ResponseEntity.ok(graph); // } } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsMermaidService.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsMermaidService.java new file mode 100644 index 00000000..77d8128a --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsMermaidService.java @@ -0,0 +1,69 @@ +package net.hostsharing.hsadminng.rbac.rbacgrant; + +import net.hostsharing.hsadminng.context.Context; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.UUID; + +import static net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService.Include.*; + +@Service +public class RbacGrantsMermaidService { + + public enum Include { + PERMISSIONS, + NOT_ASSUMED, + TEST_ENTITIES, + NON_TEST_ENTITIES + } + + @Autowired + private Context context; + + @Autowired + private RawRbacGrantRepository rawGrantRepo; + + public String allGrantsToCurrentUser(final EnumSet include) { + final var graph = new ArrayList(); + traverseGrantsTo(graph, context.getCurrentUserUUid(), include); + return "flowchart TB\n\n" + String.join("\n", graph); + } + + private void traverseGrantsTo(final ArrayList graph, final UUID refUuid, final EnumSet include) { + final var grants = rawGrantRepo.findByAscendingUuid(refUuid); + grants.forEach(g -> { + if (!include.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm ")) { + return; + } + if (!include.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(" test_")) { + return; + } + if (!include.contains(NON_TEST_ENTITIES) && !g.getDescendantIdName().contains(" test_")) { + return; + } + graph.add( + id(g.getAscendantIdName()) + + (g.isAssumed() ? " --> " : " -.-> ") + + id(g.getDescendantIdName())); + if (include.contains(NOT_ASSUMED) || g.isAssumed()) { + traverseGrantsTo(graph, g.getDescendantUuid(), include); + } + }); + } + + private String id(final String idName) { + if (idName.contains("@")) { + return quoted(idName).replaceAll("@.*", "") + "[" + quoted(idName) + "]"; + } + return quoted(idName); + } + + @NotNull + private static String quoted(final String idName) { + return idName.replace(" ", ":"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipRepositoryIntegrationTest.java index 81b1ae39..45cdff59 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipRepositoryIntegrationTest.java @@ -8,7 +8,6 @@ import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; import net.hostsharing.test.Array; import net.hostsharing.test.JpaAttempt; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,10 +19,8 @@ import org.springframework.orm.jpa.JpaSystemException; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.servlet.http.HttpServletRequest; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.UUID; import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.NATURAL_PERSON; import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.UNINCORPORATED_FIRM; @@ -201,37 +198,6 @@ class HsOfficeRelationshipRepositoryIntegrationTest extends ContextBasedTestWith "rel(relAnchor='IF Third OHG', relType='SUBSCRIBER', relMark='members-announce', relHolder='NP Smith, Peter', contact='third contact')", "rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='NP Smith, Peter', contact='sixth contact')"); } - - @Test - void visibilityTree() { - context("person-SmithPeter@example.com"); - final var graph = new ArrayList(); - traverseGrantsTo( graph, context.getCurrentUserUUid()); - System.out.println("flowchart TB\n\n" + String.join("\n", graph)); - } - - private void traverseGrantsTo(final ArrayList graph, final UUID refUuid) { - final var grants = rawGrantRepo.findByAscendingUuid(refUuid); - grants.forEach(g -> { - graph.add( - id(g.getAscendantIdName()) + - (g.isAssumed() ? " --> " : " -.-> " ) + - id(g.getDescendantIdName())); - traverseGrantsTo(graph, g.getDescendantUuid()); - }); - } - - private String id(final String idName) { - if ( idName.contains("@")) { - return quoted(idName).replaceAll("@.*", "") + "[" + quoted(idName) + "]"; - } - return quoted(idName); - } - - @NotNull - private static String quoted(final String idName) { - return idName.replace(" ", ":"); - } } @Nested diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsMermaidServiceIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsMermaidServiceIntegrationTest.java new file mode 100644 index 00000000..ba848d71 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsMermaidServiceIntegrationTest.java @@ -0,0 +1,82 @@ +package net.hostsharing.hsadminng.rbac.rbacgrant; + +import net.hostsharing.hsadminng.context.Context; +import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup; +import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService.Include; +import net.hostsharing.test.JpaAttempt; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +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.servlet.http.HttpServletRequest; +import java.util.EnumSet; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Import( { Context.class, JpaAttempt.class, RbacGrantsMermaidService.class}) +class RbacGrantsMermaidServiceIntegrationTest extends ContextBasedTestWithCleanup { + + @Autowired + RbacGrantsMermaidService grantsMermaidService; + + @MockBean + HttpServletRequest request; + + @Test + void allGrantsToCurrentUser() { + context("pac-admin-xxx00@xxx.example.com"); + final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.TEST_ENTITIES)); + + assertThat(graph).isEqualTo(""" + flowchart TB + + user:pac-admin-xxx00[user:pac-admin-xxx00@xxx.example.com] --> role:test_package#xxx00.admin + role:test_package#xxx00.admin --> role:test_domain#xxx00-aaaa.owner + role:test_domain#xxx00-aaaa.owner --> role:test_domain#xxx00-aaaa.admin + role:test_domain#xxx00-aaaa.admin --> role:test_package#xxx00.tenant + role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_package#xxx00.admin --> role:test_domain#xxx00-aaab.owner + role:test_domain#xxx00-aaab.owner --> role:test_domain#xxx00-aaab.admin + role:test_domain#xxx00-aaab.admin --> role:test_package#xxx00.tenant + role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_package#xxx00.admin --> role:test_package#xxx00.tenant + role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + """.trim()); + } + + @Test + void allGrantsToCurrentUserIncludingPermissions() { + context("pac-admin-xxx00@xxx.example.com"); + final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.TEST_ENTITIES, Include.PERMISSIONS)); + + assertThat(graph).isEqualTo(""" + flowchart TB + + user:pac-admin-xxx00[user:pac-admin-xxx00@xxx.example.com] --> role:test_package#xxx00.admin + role:test_package#xxx00.admin --> perm:add-domain:on:test_package#xxx00 + role:test_package#xxx00.admin --> role:test_domain#xxx00-aaaa.owner + role:test_domain#xxx00-aaaa.owner --> perm:*:on:test_domain#xxx00-aaaa + role:test_domain#xxx00-aaaa.owner --> role:test_domain#xxx00-aaaa.admin + role:test_domain#xxx00-aaaa.admin --> perm:edit:on:test_domain#xxx00-aaaa + role:test_domain#xxx00-aaaa.admin --> role:test_package#xxx00.tenant + role:test_package#xxx00.tenant --> perm:view:on:test_package#xxx00 + role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_customer#xxx.tenant --> perm:view:on:test_customer#xxx + role:test_package#xxx00.admin --> role:test_domain#xxx00-aaab.owner + role:test_domain#xxx00-aaab.owner --> perm:*:on:test_domain#xxx00-aaab + role:test_domain#xxx00-aaab.owner --> role:test_domain#xxx00-aaab.admin + role:test_domain#xxx00-aaab.admin --> perm:edit:on:test_domain#xxx00-aaab + role:test_domain#xxx00-aaab.admin --> role:test_package#xxx00.tenant + role:test_package#xxx00.tenant --> perm:view:on:test_package#xxx00 + role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_customer#xxx.tenant --> perm:view:on:test_customer#xxx + role:test_package#xxx00.admin --> role:test_package#xxx00.tenant + role:test_package#xxx00.tenant --> perm:view:on:test_package#xxx00 + role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_customer#xxx.tenant --> perm:view:on:test_customer#xxx + """.trim()); + } +}