add RbacGrantsMermaidService and related cleanup

This commit is contained in:
Michael Hoennig 2024-02-13 09:19:39 +01:00
parent e272b5b2ae
commit 9c03e7441f
6 changed files with 154 additions and 57 deletions

View File

@ -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;

View File

@ -103,28 +103,8 @@ public class RbacGrantController implements RbacGrantsApi {
// public ResponseEntity<String> allGrantsOfUserAsMermaid(
// @RequestHeader(name = "current-user") String currentUser,
// @RequestHeader(name = "assumed-roles", required = false) String assumedRoles) {
// context(currentUser);
// final var graph = new ArrayList<String>();
// traverseGrantsTo( graph, context.getCurrentUserUUid());
// return ResponseEntity.ok("flowchart TB\n\n" + String.join("\n", graph));
// }
//
// private void traverseGrantsTo(final ArrayList<String> 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);
// }
}

View File

@ -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> include) {
final var graph = new ArrayList<String>();
traverseGrantsTo(graph, context.getCurrentUserUUid(), include);
return "flowchart TB\n\n" + String.join("\n", graph);
}
private void traverseGrantsTo(final ArrayList<String> graph, final UUID refUuid, final EnumSet<Include> 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(" ", ":");
}
}

View File

@ -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<String>();
traverseGrantsTo( graph, context.getCurrentUserUUid());
System.out.println("flowchart TB\n\n" + String.join("\n", graph));
}
private void traverseGrantsTo(final ArrayList<String> 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

View File

@ -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());
}
}