RBAC Diagram+PostgreSQL Generator #21
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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) -> {
|
||||
|
@ -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);
|
||||
})
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
41
src/main/resources/db/changelog/113-test-customer-rbac.md
Normal file
41
src/main/resources/db/changelog/113-test-customer-rbac.md
Normal file
@ -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
|
||||
|
||||
```
|
@ -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(
|
||||
|
57
src/main/resources/db/changelog/123-test-package-rbac.md
Normal file
57
src/main/resources/db/changelog/123-test-package-rbac.md
Normal file
@ -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
|
||||
|
||||
```
|
@ -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:--//
|
||||
|
@ -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:
|
||||
|
||||
<pre>
|
||||
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
|
||||
);
|
||||
</pre>
|
||||
*/
|
||||
@Autowired
|
||||
protected RbacGrantsDiagramService diagramService;
|
||||
protected RbacGrantsDiagramService diagramService; // just to be used in subclasses
|
||||
|
||||
TestInfo test;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user