fix allowed licenses, do version upgrades upgrade and improve test coverage (#112)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: #112
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig 2024-10-10 09:31:43 +02:00
parent 60341bf644
commit cb8a5190ce
16 changed files with 1125 additions and 45 deletions

View File

@ -497,9 +497,19 @@ We'll see if this changes when the project progresses and more validations are a
### OWASP Security Vulnerability Check
An OWASP security vulnerability is configured and can be utilized by running:
An OWASP security vulnerability is configured, but you need an API key.
Fetch it from https://nvd.nist.gov/developers/request-an-api-key.
Then add it to your `~/.gradle/gradle.properties` file:
```
OWASP_API_KEY=........-....-....-....-............
```
Now you can run the dependency vulnerability check:
```shell
gw dependencyCheckUpdate
gw dependencyCheckAnalyze
```

View File

@ -1,10 +1,10 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.4'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
id 'io.openapiprocessor.openapi-processor' version '2023.2'
id 'com.github.jk1.dependency-license-report' version '2.6'
id "org.owasp.dependencycheck" version "9.0.10"
id 'com.github.jk1.dependency-license-report' version '2.9'
id "org.owasp.dependencycheck" version "10.0.4"
id "com.diffplug.spotless" version "6.25.0"
id 'jacoco'
id 'info.solidsoft.pitest' version '1.15.0'
@ -58,19 +58,20 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.9.1'
implementation 'org.springdoc:springdoc-openapi:2.4.0'
implementation 'org.postgresql:postgresql:42.7.3'
implementation 'org.liquibase:liquibase-core:4.27.0'
implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.3'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.0'
implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.9.2'
implementation 'org.springdoc:springdoc-openapi:2.6.0'
implementation 'org.postgresql:postgresql:42.7.4'
implementation 'org.liquibase:liquibase-core:4.29.2'
implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.8.3'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.0'
implementation 'org.openapitools:jackson-databind-nullable:0.2.6'
implementation 'org.apache.commons:commons-text:1.11.0'
implementation 'net.java.dev.jna:jna:5.8.0'
implementation 'org.modelmapper:modelmapper:3.2.0'
implementation 'org.iban4j:iban4j:3.2.7-RELEASE'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0'
implementation 'org.reflections:reflections:0.9.12'
implementation 'org.apache.commons:commons-text:1.12.0'
implementation 'net.java.dev.jna:jna:5.15.0'
implementation 'org.modelmapper:modelmapper:3.2.1'
implementation 'org.iban4j:iban4j:3.2.10-RELEASE'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'
implementation 'org.webjars:swagger-ui:5.17.14'
implementation 'org.reflections:reflections:0.10.2'
compileOnly 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
@ -85,9 +86,9 @@ dependencies {
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'
testImplementation 'com.tngtech.archunit:archunit-junit5:1.2.1'
testImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0'
testImplementation 'io.rest-assured:spring-mock-mvc'
testImplementation 'org.hamcrest:hamcrest-core:2.2'
testImplementation 'org.hamcrest:hamcrest-core:3.0'
testImplementation 'org.pitest:pitest-junit5-plugin:1.2.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
}

View File

@ -1,8 +1,10 @@
{
"allowedLicenses": [
{ "moduleLicense": "Apache 2.0" },
{ "moduleLicense": "Apache 2" },
{ "moduleLicense": "Apache 2.0" },
{ "moduleLicense": "Apache-2.0" },
{ "moduleLicense": "Apache License 2.0" },
{ "moduleLicense": "Apache License v2.0" },
{ "moduleLicense": "Apache License, Version 2.0" },
{ "moduleLicense": "The Apache Software License, Version 2.0" },
@ -11,6 +13,8 @@
{ "moduleLicense": "BSD-3-Clause" },
{ "moduleLicense": "The BSD License" },
{ "moduleLicense": "The New BSD License" },
{ "moduleLicense": "CDDL 1.1" },
{ "moduleLicense": "CDDL/GPLv2+CE" },
{ "moduleLicense": "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0" },
@ -29,11 +33,22 @@
{ "moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception" },
{ "moduleLicense": "GPL2 w/ CPE" },
{ "moduleLicense": "LGPL, version 2.1"},
{ "moduleLicense": "LGPL-2.1-or-later"},
{ "moduleLicense": "MIT License" },
{ "moduleLicense": "MIT" },
{ "moduleLicense": "The MIT License (MIT)" },
{ "moduleLicense": "The MIT License" },
{ "moduleName": "org.springdoc:springdoc-openapi" }
{ "moduleLicense": "WTFPL" },
{
"moduleLicense": null,
"#moduleLicense": "Apache License 2.0, see https://github.com/springdoc/springdoc-openapi/blob/main/LICENSE",
"moduleVersion": "2.4.0",
"moduleName": "org.springdoc:springdoc-openapi"
}
]
}

View File

@ -1,12 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<suppress>
<notes><![CDATA[
Cyclic references are not possible if file comes in JSON text format.
]]></notes>
<packageUrl regex="true">^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$</packageUrl>
<cpe>cpe:/a:fasterxml:jackson-databind</cpe>
</suppress>
<suppress>
<notes><![CDATA[
Internal tooling, not exposed to the Internet.
@ -14,4 +7,10 @@
<packageUrl regex="true">^pkg:maven/org\.pitest/pitest\-command\-line@.*$</packageUrl>
<cpe>cpe:/a:line:line</cpe>
</suppress>
<suppress>
<notes><![CDATA[
Malicious HTTP redirect in JAXB on a REST-endpoint is not that dangerous.
]]></notes>
<cve>CVE-2024-9329</cve>
</suppress>
</suppressions>

View File

@ -15,6 +15,7 @@ import org.opentest4j.AssertionFailedError;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.Resource;
import org.springframework.transaction.support.TransactionTemplate;
import jakarta.persistence.EntityManager;
@ -24,7 +25,6 @@ import jakarta.validation.ValidationException;
import jakarta.validation.constraints.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
@ -33,6 +33,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.time.LocalDate;
import java.util.LinkedHashSet;
import java.util.List;
@ -123,13 +124,10 @@ public class CsvDataImport extends ContextBasedTest {
}
}
protected String resourceAsString(@NotNull final String resourcePath) {
try (InputStream inputStream = requireNonNull(getClass().getClassLoader().getResourceAsStream(resourcePath));
final var reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
} catch (Exception exc) {
throw new AssertionFailedError("cannot open '" + resourcePath + "'");
}
@SneakyThrows
protected String resourceAsString(final Resource resource) {
final var lines = Files.readAllLines(resource.getFile().toPath(), StandardCharsets.UTF_8);
return String.join("\n", lines);
}
protected List<String[]> withoutHeader(final List<String[]> records) {

View File

@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.hs.migration;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hash.HashGenerator;
import net.hostsharing.hsadminng.hash.HashGenerator.Algorithm;
@ -26,10 +27,9 @@ import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.test.annotation.Commit;
import org.springframework.test.annotation.DirtiesContext;
@ -46,7 +46,6 @@ import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.regex.Pattern;
import static java.util.Arrays.stream;
import static java.util.Map.entry;
@ -497,13 +496,14 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
@Test
@Order(16020)
@SneakyThrows
void importZonenfiles() {
final var reflections = new Reflections(MIGRATION_DATA_PATH + "/hosting/zonefiles", new ResourcesScanner());
final var zonefileFiles = reflections.getResources(Pattern.compile(".*\\.json")).stream().sorted().toList();
zonefileFiles.forEach(zonenfileName -> {
System.out.println("Processing zonenfile: " + zonenfileName);
importZonefiles(vmName(zonenfileName), resourceAsString(zonenfileName));
});
final var resolver = new PathMatchingResourcePatternResolver();
final var resources = resolver.getResources("/" + MIGRATION_DATA_PATH + "/hosting/zonefiles/*.json");
for (var resource : resources) {
System.out.println("Processing zonenfile: " + resource);
importZonefiles(vmName(resource.getFilename()), resourceAsString(resource));
}
}
@Test

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.bankaccount;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -32,4 +33,48 @@ class HsOfficeBankAccountEntityUnitTest {
assertThat(givenBankAccount.toShortString()).isEqualTo("given holder");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeBankAccountEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph bankAccount["`**bankAccount**`"]
direction TB
style bankAccount fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph bankAccount:roles[ ]
style bankAccount:roles fill:#dd4901,stroke:white
role:bankAccount:OWNER[[bankAccount:OWNER]]
role:bankAccount:ADMIN[[bankAccount:ADMIN]]
role:bankAccount:REFERRER[[bankAccount:REFERRER]]
end
subgraph bankAccount:permissions[ ]
style bankAccount:permissions fill:#dd4901,stroke:white
perm:bankAccount:INSERT{{bankAccount:INSERT}}
perm:bankAccount:DELETE{{bankAccount:DELETE}}
perm:bankAccount:UPDATE{{bankAccount:UPDATE}}
perm:bankAccount:SELECT{{bankAccount:SELECT}}
end
end
%% granting roles to users
user:creator ==> role:bankAccount:OWNER
%% granting roles to roles
role:rbac.global:ADMIN ==> role:bankAccount:OWNER
role:bankAccount:OWNER ==> role:bankAccount:ADMIN
role:bankAccount:ADMIN ==> role:bankAccount:REFERRER
%% granting permissions to roles
role:rbac.global:GUEST ==> perm:bankAccount:INSERT
role:bankAccount:OWNER ==> perm:bankAccount:DELETE
role:bankAccount:ADMIN ==> perm:bankAccount:UPDATE
role:bankAccount:REFERRER ==> perm:bankAccount:SELECT
""");
}
}

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.contact;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -18,4 +19,48 @@ class HsOfficeContactUnitTest {
assertThat("" + givenContact).isEqualTo("contact(caption='given caption')");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeContactRbacEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph contact["`**contact**`"]
direction TB
style contact fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph contact:roles[ ]
style contact:roles fill:#dd4901,stroke:white
role:contact:OWNER[[contact:OWNER]]
role:contact:ADMIN[[contact:ADMIN]]
role:contact:REFERRER[[contact:REFERRER]]
end
subgraph contact:permissions[ ]
style contact:permissions fill:#dd4901,stroke:white
perm:contact:DELETE{{contact:DELETE}}
perm:contact:UPDATE{{contact:UPDATE}}
perm:contact:SELECT{{contact:SELECT}}
perm:contact:INSERT{{contact:INSERT}}
end
end
%% granting roles to users
user:creator ==> role:contact:OWNER
%% granting roles to roles
role:rbac.global:ADMIN ==> role:contact:OWNER
role:contact:OWNER ==> role:contact:ADMIN
role:contact:ADMIN ==> role:contact:REFERRER
%% granting permissions to roles
role:contact:OWNER ==> perm:contact:DELETE
role:contact:ADMIN ==> perm:contact:UPDATE
role:contact:REFERRER ==> perm:contact:SELECT
role:rbac.global:GUEST ==> perm:contact:INSERT
""");
}
}

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.coopassets;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
@ -68,4 +69,123 @@ class HsOfficeCoopAssetsTransactionEntityUnitTest {
assertThat(result).isEqualTo("M-???????:nul:+0.00");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeCoopAssetsTransactionEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"]
direction TB
style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph coopAssetsTransaction:permissions[ ]
style coopAssetsTransaction:permissions fill:#dd4901,stroke:white
perm:coopAssetsTransaction:INSERT{{coopAssetsTransaction:INSERT}}
perm:coopAssetsTransaction:UPDATE{{coopAssetsTransaction:UPDATE}}
perm:coopAssetsTransaction:SELECT{{coopAssetsTransaction:SELECT}}
end
end
subgraph membership["`**membership**`"]
direction TB
style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership:roles[ ]
style membership:roles fill:#99bcdb,stroke:white
role:membership:OWNER[[membership:OWNER]]
role:membership:ADMIN[[membership:ADMIN]]
role:membership:AGENT[[membership:AGENT]]
end
end
subgraph membership.partnerRel["`**membership.partnerRel**`"]
direction TB
style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel:roles[ ]
style membership.partnerRel:roles fill:#99bcdb,stroke:white
role:membership.partnerRel:OWNER[[membership.partnerRel:OWNER]]
role:membership.partnerRel:ADMIN[[membership.partnerRel:ADMIN]]
role:membership.partnerRel:AGENT[[membership.partnerRel:AGENT]]
role:membership.partnerRel:TENANT[[membership.partnerRel:TENANT]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]]
role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]]
role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:OWNER[[membership.partnerRel.contact:OWNER]]
role:membership.partnerRel.contact:ADMIN[[membership.partnerRel.contact:ADMIN]]
role:membership.partnerRel.contact:REFERRER[[membership.partnerRel.contact:REFERRER]]
end
end
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]]
role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]]
role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]]
end
end
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER
role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN
role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:membership.partnerRel.holderPerson:OWNER
role:membership.partnerRel.holderPerson:OWNER -.-> role:membership.partnerRel.holderPerson:ADMIN
role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:membership.partnerRel.contact:OWNER
role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact:ADMIN
role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:membership.partnerRel:OWNER
role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN
role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT
role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT
role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel:TENANT
role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.anchorPerson:REFERRER
role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.holderPerson:REFERRER
role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.contact:REFERRER
role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:OWNER
role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT
role:membership:OWNER -.-> role:membership:ADMIN
role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN
role:membership:ADMIN -.-> role:membership:AGENT
role:membership.partnerRel:AGENT -.-> role:membership:AGENT
role:membership:AGENT -.-> role:membership.partnerRel:TENANT
%% granting permissions to roles
role:membership:ADMIN ==> perm:coopAssetsTransaction:INSERT
role:membership:ADMIN ==> perm:coopAssetsTransaction:UPDATE
role:membership:AGENT ==> perm:coopAssetsTransaction:SELECT
""");
}
}

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.coopshares;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
@ -67,4 +68,123 @@ class HsOfficeCoopSharesTransactionEntityUnitTest {
assertThat(result).isEqualTo("null:nul:+0");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeCoopSharesTransactionEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph coopSharesTransaction["`**coopSharesTransaction**`"]
direction TB
style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph coopSharesTransaction:permissions[ ]
style coopSharesTransaction:permissions fill:#dd4901,stroke:white
perm:coopSharesTransaction:INSERT{{coopSharesTransaction:INSERT}}
perm:coopSharesTransaction:UPDATE{{coopSharesTransaction:UPDATE}}
perm:coopSharesTransaction:SELECT{{coopSharesTransaction:SELECT}}
end
end
subgraph membership["`**membership**`"]
direction TB
style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership:roles[ ]
style membership:roles fill:#99bcdb,stroke:white
role:membership:OWNER[[membership:OWNER]]
role:membership:ADMIN[[membership:ADMIN]]
role:membership:AGENT[[membership:AGENT]]
end
end
subgraph membership.partnerRel["`**membership.partnerRel**`"]
direction TB
style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel:roles[ ]
style membership.partnerRel:roles fill:#99bcdb,stroke:white
role:membership.partnerRel:OWNER[[membership.partnerRel:OWNER]]
role:membership.partnerRel:ADMIN[[membership.partnerRel:ADMIN]]
role:membership.partnerRel:AGENT[[membership.partnerRel:AGENT]]
role:membership.partnerRel:TENANT[[membership.partnerRel:TENANT]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]]
role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]]
role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:OWNER[[membership.partnerRel.contact:OWNER]]
role:membership.partnerRel.contact:ADMIN[[membership.partnerRel.contact:ADMIN]]
role:membership.partnerRel.contact:REFERRER[[membership.partnerRel.contact:REFERRER]]
end
end
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]]
role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]]
role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]]
end
end
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER
role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN
role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:membership.partnerRel.holderPerson:OWNER
role:membership.partnerRel.holderPerson:OWNER -.-> role:membership.partnerRel.holderPerson:ADMIN
role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:membership.partnerRel.contact:OWNER
role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact:ADMIN
role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:membership.partnerRel:OWNER
role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN
role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT
role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT
role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel:TENANT
role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.anchorPerson:REFERRER
role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.holderPerson:REFERRER
role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.contact:REFERRER
role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:OWNER
role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT
role:membership:OWNER -.-> role:membership:ADMIN
role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN
role:membership:ADMIN -.-> role:membership:AGENT
role:membership.partnerRel:AGENT -.-> role:membership:AGENT
role:membership:AGENT -.-> role:membership.partnerRel:TENANT
%% granting permissions to roles
role:membership:ADMIN ==> perm:coopSharesTransaction:INSERT
role:membership:ADMIN ==> perm:coopSharesTransaction:UPDATE
role:membership:AGENT ==> perm:coopSharesTransaction:SELECT
""");
}
}

View File

@ -5,6 +5,8 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import net.hostsharing.hsadminng.rbac.test.cust.TestCustomerEntity;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -109,4 +111,200 @@ class HsOfficeDebitorEntityUnitTest {
assertThat(result).isNull();
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeDebitorEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph debitor["`**debitor**`"]
direction TB
style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph debitor:permissions[ ]
style debitor:permissions fill:#dd4901,stroke:white
perm:debitor:INSERT{{debitor:INSERT}}
perm:debitor:DELETE{{debitor:DELETE}}
perm:debitor:UPDATE{{debitor:UPDATE}}
perm:debitor:SELECT{{debitor:SELECT}}
end
subgraph debitorRel["`**debitorRel**`"]
direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel:roles[ ]
style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel:OWNER[[debitorRel:OWNER]]
role:debitorRel:ADMIN[[debitorRel:ADMIN]]
role:debitorRel:AGENT[[debitorRel:AGENT]]
role:debitorRel:TENANT[[debitorRel:TENANT]]
end
end
end
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]]
role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]]
role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]]
role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]]
role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]]
role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]]
role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]]
end
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:OWNER[[partnerRel:OWNER]]
role:partnerRel:ADMIN[[partnerRel:ADMIN]]
role:partnerRel:AGENT[[partnerRel:AGENT]]
role:partnerRel:TENANT[[partnerRel:TENANT]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]]
role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]]
role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]]
role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]]
role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]]
role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]]
role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]]
end
end
subgraph refundBankAccount["`**refundBankAccount**`"]
direction TB
style refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph refundBankAccount:roles[ ]
style refundBankAccount:roles fill:#99bcdb,stroke:white
role:refundBankAccount:OWNER[[refundBankAccount:OWNER]]
role:refundBankAccount:ADMIN[[refundBankAccount:ADMIN]]
role:refundBankAccount:REFERRER[[refundBankAccount:REFERRER]]
end
end
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER
role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:debitorRel.holderPerson:OWNER
role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:debitorRel.contact:OWNER
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:debitorRel:OWNER
role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
role:debitorRel:AGENT -.-> role:debitorRel:TENANT
role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
role:rbac.global:ADMIN -.-> role:refundBankAccount:OWNER
role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN
role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER
role:refundBankAccount:ADMIN ==> role:debitorRel:AGENT
role:debitorRel:AGENT ==> role:refundBankAccount:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER
role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.holderPerson:OWNER
role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.contact:OWNER
role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel:OWNER
role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
role:partnerRel:AGENT -.-> role:partnerRel:TENANT
role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
role:partnerRel:ADMIN ==> role:debitorRel:ADMIN
role:partnerRel:AGENT ==> role:debitorRel:AGENT
role:debitorRel:AGENT ==> role:partnerRel:TENANT
%% granting permissions to roles
role:rbac.global:ADMIN ==> perm:debitor:INSERT
role:debitorRel:OWNER ==> perm:debitor:DELETE
role:debitorRel:ADMIN ==> perm:debitor:UPDATE
role:debitorRel:TENANT ==> perm:debitor:SELECT
""");
}
}

View File

@ -1,7 +1,9 @@
package net.hostsharing.hsadminng.hs.office.membership;
import io.hypersistence.utils.hibernate.type.range.Range;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import jakarta.persistence.PrePersist;
@ -98,7 +100,126 @@ class HsOfficeMembershipEntityUnitTest {
givenMembership.setValidTo(LocalDate.parse("2024-12-31"));
assertThat(givenMembership.getValidFrom()).isEqualTo(GIVEN_VALID_FROM);
assertThat(givenMembership.getValidTo()).isEqualTo(LocalDate.parse("2024-12-31"));
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeMembershipEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph membership["`**membership**`"]
direction TB
style membership fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph membership:roles[ ]
style membership:roles fill:#dd4901,stroke:white
role:membership:OWNER[[membership:OWNER]]
role:membership:ADMIN[[membership:ADMIN]]
role:membership:AGENT[[membership:AGENT]]
end
subgraph membership:permissions[ ]
style membership:permissions fill:#dd4901,stroke:white
perm:membership:INSERT{{membership:INSERT}}
perm:membership:DELETE{{membership:DELETE}}
perm:membership:UPDATE{{membership:UPDATE}}
perm:membership:SELECT{{membership:SELECT}}
end
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:OWNER[[partnerRel:OWNER]]
role:partnerRel:ADMIN[[partnerRel:ADMIN]]
role:partnerRel:AGENT[[partnerRel:AGENT]]
role:partnerRel:TENANT[[partnerRel:TENANT]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]]
role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]]
role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]]
role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]]
role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]]
role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]]
role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]]
end
end
%% granting roles to users
user:creator ==> role:membership:OWNER
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER
role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.holderPerson:OWNER
role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.contact:OWNER
role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel:OWNER
role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
role:partnerRel:AGENT -.-> role:partnerRel:TENANT
role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
role:membership:OWNER ==> role:membership:ADMIN
role:partnerRel:ADMIN ==> role:membership:ADMIN
role:membership:ADMIN ==> role:membership:AGENT
role:partnerRel:AGENT ==> role:membership:AGENT
role:membership:AGENT ==> role:partnerRel:TENANT
%% granting permissions to roles
role:rbac.global:ADMIN ==> perm:membership:INSERT
role:membership:ADMIN ==> perm:membership:DELETE
role:membership:ADMIN ==> perm:membership:UPDATE
role:membership:AGENT ==> perm:membership:SELECT
""");
}
private static void invokePrePersist(final HsOfficeMembershipEntity membershipEntity)

View File

@ -5,6 +5,7 @@ import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -38,4 +39,123 @@ class HsOfficePartnerEntityUnitTest {
final var result = givenPartner.toShortString();
assertThat(result).isEqualTo("P-12345");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficePartnerEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph partner["`**partner**`"]
direction TB
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph partner:permissions[ ]
style partner:permissions fill:#dd4901,stroke:white
perm:partner:INSERT{{partner:INSERT}}
perm:partner:DELETE{{partner:DELETE}}
perm:partner:UPDATE{{partner:UPDATE}}
perm:partner:SELECT{{partner:SELECT}}
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:OWNER[[partnerRel:OWNER]]
role:partnerRel:ADMIN[[partnerRel:ADMIN]]
role:partnerRel:AGENT[[partnerRel:AGENT]]
role:partnerRel:TENANT[[partnerRel:TENANT]]
end
end
end
subgraph partnerDetails["`**partnerDetails**`"]
direction TB
style partnerDetails fill:#feb28c,stroke:#274d6e,stroke-width:8px
subgraph partnerDetails:permissions[ ]
style partnerDetails:permissions fill:#feb28c,stroke:white
perm:partnerDetails:DELETE{{partnerDetails:DELETE}}
perm:partnerDetails:UPDATE{{partnerDetails:UPDATE}}
perm:partnerDetails:SELECT{{partnerDetails:SELECT}}
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]]
role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]]
role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]]
role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]]
role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]]
role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]]
role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]]
end
end
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER
role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.holderPerson:OWNER
role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel.contact:OWNER
role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:partnerRel:OWNER
role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
role:partnerRel:AGENT -.-> role:partnerRel:TENANT
role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
%% granting permissions to roles
role:rbac.global:ADMIN ==> perm:partner:INSERT
role:partnerRel:OWNER ==> perm:partner:DELETE
role:partnerRel:ADMIN ==> perm:partner:UPDATE
role:partnerRel:TENANT ==> perm:partner:SELECT
role:partnerRel:OWNER ==> perm:partnerDetails:DELETE
role:partnerRel:AGENT ==> perm:partnerDetails:UPDATE
role:partnerRel:AGENT ==> perm:partnerDetails:SELECT
""");
}
}

View File

@ -1,5 +1,7 @@
package net.hostsharing.hsadminng.hs.office.person;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import java.util.UUID;
@ -155,6 +157,7 @@ class HsOfficePersonEntityUnitTest {
assertThat(actualDisplay).isEqualTo("person(salutation='Herr', familyName='some family name', givenName='some given name')");
}
@Test
void toStringWithoutSalutationAndWithTitleSkipsSalutation() {
final var givenPersonEntity = HsOfficePersonEntity.builder()
@ -168,4 +171,48 @@ class HsOfficePersonEntityUnitTest {
assertThat(actualDisplay).isEqualTo("person(title='some title', familyName='some family name', givenName='some given name')");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficePersonEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph person["`**person**`"]
direction TB
style person fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph person:roles[ ]
style person:roles fill:#dd4901,stroke:white
role:person:OWNER[[person:OWNER]]
role:person:ADMIN[[person:ADMIN]]
role:person:REFERRER[[person:REFERRER]]
end
subgraph person:permissions[ ]
style person:permissions fill:#dd4901,stroke:white
perm:person:INSERT{{person:INSERT}}
perm:person:DELETE{{person:DELETE}}
perm:person:UPDATE{{person:UPDATE}}
perm:person:SELECT{{person:SELECT}}
end
end
%% granting roles to users
user:creator ==> role:person:OWNER
%% granting roles to roles
role:rbac.global:ADMIN ==> role:person:OWNER
role:person:OWNER ==> role:person:ADMIN
role:person:ADMIN ==> role:person:REFERRER
%% granting permissions to roles
role:rbac.global:GUEST ==> perm:person:INSERT
role:person:OWNER ==> perm:person:DELETE
role:person:ADMIN ==> perm:person:UPDATE
role:person:REFERRER ==> perm:person:SELECT
""");
}
}

View File

@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.hs.office.relation;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -40,4 +41,103 @@ class HsOfficeRelationUnitTest {
assertThat(given.toShortString()).isEqualTo("rel(anchor='LP some trade name', type='REPRESENTATIVE', holder='NP Meier, Mellie')");
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeRelationRbacEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph anchorPerson["`**anchorPerson**`"]
direction TB
style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph anchorPerson:roles[ ]
style anchorPerson:roles fill:#99bcdb,stroke:white
role:anchorPerson:OWNER[[anchorPerson:OWNER]]
role:anchorPerson:ADMIN[[anchorPerson:ADMIN]]
role:anchorPerson:REFERRER[[anchorPerson:REFERRER]]
end
end
subgraph contact["`**contact**`"]
direction TB
style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph contact:roles[ ]
style contact:roles fill:#99bcdb,stroke:white
role:contact:OWNER[[contact:OWNER]]
role:contact:ADMIN[[contact:ADMIN]]
role:contact:REFERRER[[contact:REFERRER]]
end
end
subgraph holderPerson["`**holderPerson**`"]
direction TB
style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph holderPerson:roles[ ]
style holderPerson:roles fill:#99bcdb,stroke:white
role:holderPerson:OWNER[[holderPerson:OWNER]]
role:holderPerson:ADMIN[[holderPerson:ADMIN]]
role:holderPerson:REFERRER[[holderPerson:REFERRER]]
end
end
subgraph relation["`**relation**`"]
direction TB
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph relation:roles[ ]
style relation:roles fill:#dd4901,stroke:white
role:relation:OWNER[[relation:OWNER]]
role:relation:ADMIN[[relation:ADMIN]]
role:relation:AGENT[[relation:AGENT]]
role:relation:TENANT[[relation:TENANT]]
end
subgraph relation:permissions[ ]
style relation:permissions fill:#dd4901,stroke:white
perm:relation:DELETE{{relation:DELETE}}
perm:relation:UPDATE{{relation:UPDATE}}
perm:relation:SELECT{{relation:SELECT}}
perm:relation:INSERT{{relation:INSERT}}
end
end
%% granting roles to users
user:creator ==> role:relation:OWNER
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:anchorPerson:OWNER
role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN
role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:holderPerson:OWNER
role:holderPerson:OWNER -.-> role:holderPerson:ADMIN
role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:contact:OWNER
role:contact:OWNER -.-> role:contact:ADMIN
role:contact:ADMIN -.-> role:contact:REFERRER
role:rbac.global:ADMIN ==> role:relation:OWNER
role:relation:OWNER ==> role:relation:ADMIN
role:relation:ADMIN ==> role:relation:AGENT
role:relation:AGENT ==> role:relation:TENANT
role:contact:ADMIN ==> role:relation:TENANT
role:relation:TENANT ==> role:anchorPerson:REFERRER
role:relation:TENANT ==> role:holderPerson:REFERRER
role:relation:TENANT ==> role:contact:REFERRER
%% granting permissions to roles
role:relation:OWNER ==> perm:relation:DELETE
role:relation:ADMIN ==> perm:relation:UPDATE
role:relation:TENANT ==> perm:relation:SELECT
role:anchorPerson:ADMIN ==> perm:relation:INSERT
""");
}
}

View File

@ -1,6 +1,8 @@
package net.hostsharing.hsadminng.hs.office.sepamandate;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRbacEntity;
import net.hostsharing.hsadminng.rbac.generator.RbacViewMermaidFlowchartGenerator;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
@ -49,4 +51,143 @@ class HsOfficeSepaMandateEntityUnitTest {
assertThat(givenSepaMandate.getValidTo()).isEqualTo(LocalDate.parse("2024-12-31"));
}
@Test
void definesRbac() {
final var rbacFlowchart = new RbacViewMermaidFlowchartGenerator(HsOfficeSepaMandateEntity.rbac()).toString();
assertThat(rbacFlowchart).isEqualTo("""
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph bankAccount["`**bankAccount**`"]
direction TB
style bankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph bankAccount:roles[ ]
style bankAccount:roles fill:#99bcdb,stroke:white
role:bankAccount:OWNER[[bankAccount:OWNER]]
role:bankAccount:ADMIN[[bankAccount:ADMIN]]
role:bankAccount:REFERRER[[bankAccount:REFERRER]]
end
end
subgraph debitorRel["`**debitorRel**`"]
direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel:roles[ ]
style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel:OWNER[[debitorRel:OWNER]]
role:debitorRel:ADMIN[[debitorRel:ADMIN]]
role:debitorRel:AGENT[[debitorRel:AGENT]]
role:debitorRel:TENANT[[debitorRel:TENANT]]
end
end
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]]
role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]]
role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]]
role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]]
role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]]
role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]]
role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]]
end
end
subgraph sepaMandate["`**sepaMandate**`"]
direction TB
style sepaMandate fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph sepaMandate:roles[ ]
style sepaMandate:roles fill:#dd4901,stroke:white
role:sepaMandate:OWNER[[sepaMandate:OWNER]]
role:sepaMandate:ADMIN[[sepaMandate:ADMIN]]
role:sepaMandate:AGENT[[sepaMandate:AGENT]]
role:sepaMandate:REFERRER[[sepaMandate:REFERRER]]
end
subgraph sepaMandate:permissions[ ]
style sepaMandate:permissions fill:#dd4901,stroke:white
perm:sepaMandate:DELETE{{sepaMandate:DELETE}}
perm:sepaMandate:UPDATE{{sepaMandate:UPDATE}}
perm:sepaMandate:SELECT{{sepaMandate:SELECT}}
perm:sepaMandate:INSERT{{sepaMandate:INSERT}}
end
end
%% granting roles to users
user:creator ==> role:sepaMandate:OWNER
%% granting roles to roles
role:rbac.global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER
role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER
role:rbac.global:ADMIN -.-> role:debitorRel.holderPerson:OWNER
role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER
role:rbac.global:ADMIN -.-> role:debitorRel.contact:OWNER
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
role:rbac.global:ADMIN -.-> role:debitorRel:OWNER
role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
role:debitorRel:AGENT -.-> role:debitorRel:TENANT
role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
role:rbac.global:ADMIN -.-> role:bankAccount:OWNER
role:bankAccount:OWNER -.-> role:bankAccount:ADMIN
role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER
role:rbac.global:ADMIN ==> role:sepaMandate:OWNER
role:sepaMandate:OWNER ==> role:sepaMandate:ADMIN
role:sepaMandate:ADMIN ==> role:sepaMandate:AGENT
role:sepaMandate:AGENT ==> role:bankAccount:REFERRER
role:sepaMandate:AGENT ==> role:debitorRel:AGENT
role:sepaMandate:AGENT ==> role:sepaMandate:REFERRER
role:bankAccount:ADMIN ==> role:sepaMandate:REFERRER
role:debitorRel:AGENT ==> role:sepaMandate:REFERRER
role:sepaMandate:REFERRER ==> role:debitorRel:TENANT
%% granting permissions to roles
role:sepaMandate:OWNER ==> perm:sepaMandate:DELETE
role:sepaMandate:ADMIN ==> perm:sepaMandate:UPDATE
role:sepaMandate:REFERRER ==> perm:sepaMandate:SELECT
role:debitorRel:ADMIN ==> perm:sepaMandate:INSERT
""");
}
}