move Parter+Debitor person+contact to related Relationsship #20
@ -59,8 +59,11 @@ public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable {
|
||||
|
||||
public static RbacView rbac() {
|
||||
return rbacViewFor("bankAccount", HsOfficeBankAccountEntity.class)
|
||||
.withIdentityView(SQL.projection("iban || ':' || holder"))
|
||||
.withIdentityView(SQL.projection("concat(iban, ':', holder)"))
|
||||
.withUpdatableColumns("holder", "iban", "bic")
|
||||
|
||||
.toRole("global", GUEST).grantPermission("bankAccount", INSERT)
|
||||
hsh-michaelhoennig marked this conversation as resolved
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
with.owningUser(CREATOR);
|
||||
with.incomingSuperRole(GLOBAL, ADMIN);
|
||||
@ -75,6 +78,6 @@ public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
rbac().generateWithBaseFileName("243-hs-office-bankaccount-rbac-generated");
|
||||
rbac().generateWithBaseFileName("243-hs-office-bankaccount-rbac");
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,8 @@ public class HsOfficePersonEntity implements HasUuid, Stringifyable {
|
||||
return rbacViewFor("person", HsOfficePersonEntity.class)
|
||||
.withIdentityView(SQL.projection("concat(tradeName, familyName, givenName)"))
|
||||
.withUpdatableColumns("personType", "tradeName", "givenName", "familyName")
|
||||
.toRole("global", GUEST).grantPermission("person", INSERT)
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
with.permission(DELETE);
|
||||
with.owningUser(CREATOR);
|
||||
@ -93,6 +95,6 @@ public class HsOfficePersonEntity implements HasUuid, Stringifyable {
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
rbac().generateWithBaseFileName("213-hs-office-person-rbac-generated");
|
||||
rbac().generateWithBaseFileName("213-hs-office-person-rbac");
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,12 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid {
|
||||
|
||||
public static RbacView rbac() {
|
||||
return rbacViewFor("sepaMandate", HsOfficeSepaMandateEntity.class)
|
||||
.withIdentityView(projection("concat(tradeName, familyName, givenName)"))
|
||||
.withIdentityView(query("""
|
||||
select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName
|
||||
from hs_office_sepamandate sm
|
||||
join hs_office_bankaccount ba on ba.uuid = sm.bankAccountUuid
|
||||
"""))
|
||||
.withRestrictedViewOrderBy(expression("validity"))
|
||||
.withUpdatableColumns("reference", "agreement", "validity")
|
||||
|
||||
.importEntityAlias("debitorRel", HsOfficeRelationshipEntity.class, dependsOnColumn("debitorRelUuid"))
|
||||
@ -111,17 +116,17 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid {
|
||||
})
|
||||
.createSubRole(AGENT, (with) -> {
|
||||
with.outgoingSubRole("bankAccount", REFERRER);
|
||||
with.outgoingSubRole("debitorRel", AGENT);
|
||||
with.outgoingSubRole("debitor", AGENT);
|
||||
})
|
||||
.createSubRole(REFERRER, (with) -> {
|
||||
with.incomingSuperRole("bankAccount", ADMIN);
|
||||
with.incomingSuperRole("debitorRel", AGENT);
|
||||
with.incomingSuperRole("debitor", AGENT);
|
||||
with.outgoingSubRole("debitorRel", TENANT);
|
||||
with.permission(SELECT);
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
rbac().generateWithBaseFileName("253-hs-office-sepamandate-rbac-generated");
|
||||
rbac().generateWithBaseFileName("253-hs-office-sepamandate-rbac");
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public class InsertTriggerGenerator {
|
||||
|
||||
FOR row IN SELECT * FROM ${rawSuperTableName}
|
||||
LOOP
|
||||
roleUuid := findRoleId(${rawSuperRoleDescriptor}(row));
|
||||
roleUuid := findRoleId(${rawSuperRoleDescriptor});
|
||||
permissionUuid := createPermission(row.uuid, 'INSERT', '${rawSubTableName}');
|
||||
call grantPermissionToRole(roleUuid, permissionUuid);
|
||||
END LOOP;
|
||||
@ -62,7 +62,7 @@ public class InsertTriggerGenerator {
|
||||
""",
|
||||
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()),
|
||||
with("rawSuperRoleDescriptor", toVar(superRoleDef))
|
||||
with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, "row"))
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -79,7 +79,7 @@ public class InsertTriggerGenerator {
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
${rawSuperRoleDescriptor}(NEW),
|
||||
${rawSuperRoleDescriptor},
|
||||
createPermission(NEW.uuid, 'INSERT', '${rawSubTableName}'));
|
||||
return NEW;
|
||||
end; $$;
|
||||
@ -91,7 +91,7 @@ public class InsertTriggerGenerator {
|
||||
""",
|
||||
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()),
|
||||
with("rawSuperRoleDescriptor", toVar(superRoleDef))
|
||||
with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, PostgresTriggerReference.NEW.name()))
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -111,15 +111,39 @@ public class InsertTriggerGenerator {
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
||||
plPgSql.writeLn("""
|
||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||
before insert on ${rawSubTable}
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
|
||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName() ));
|
||||
if (!g.getSuperRoleDef().getEntityAlias().isGlobal()) {
|
||||
plPgSql.writeLn(
|
||||
"""
|
||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||
before insert on ${rawSubTable}
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
|
||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName()));
|
||||
} else {
|
||||
switch (g.getSuperRoleDef().getRole()) {
|
||||
case ADMIN -> {
|
||||
plPgSql.writeLn(
|
||||
"""
|
||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||
before insert on ${rawSubTable}
|
||||
for each row
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||
}
|
||||
case GUEST -> {
|
||||
// no permission check trigger generated, as anybody can insert rows into this table
|
||||
}
|
||||
default -> {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid global role for INSERT permission: " + g.getSuperRoleDef().getRole());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
plPgSql.writeLn("""
|
||||
@ -162,4 +186,12 @@ public class InsertTriggerGenerator {
|
||||
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName());
|
||||
}
|
||||
|
||||
|
||||
private String toRoleDescriptor(final RbacView.RbacRoleDefinition roleDef, final String ref) {
|
||||
final var functionName = toVar(roleDef);
|
||||
if (roleDef.getEntityAlias().isGlobal()) {
|
||||
return functionName + "()";
|
||||
}
|
||||
return functionName + "(" + ref + ")";
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class RbacIdentityViewGenerator {
|
||||
$idName$);
|
||||
""";
|
||||
case SQL_QUERY -> """
|
||||
call generateRbacIdentityViewFromProjection('${rawTableName}', $idName$
|
||||
call generateRbacIdentityViewFromQuery('${rawTableName}', $idName$
|
||||
${identityViewSqlPart}
|
||||
$idName$);
|
||||
""";
|
||||
|
@ -24,9 +24,11 @@ public class RbacRestrictedViewGenerator {
|
||||
--changeset ${liquibaseTagPrefix}-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('${rawTableName}',
|
||||
'${orderBy}',
|
||||
$orderBy$
|
||||
${orderBy}
|
||||
$orderBy$,
|
||||
$updates$
|
||||
${updates}
|
||||
${updates}
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
@ -626,22 +626,23 @@ public class RbacView {
|
||||
return tableName.substring(0, tableName.length() - "_rv".length());
|
||||
}
|
||||
|
||||
public record Role(String roleName) {
|
||||
public enum Role {
|
||||
|
||||
public static final Role OWNER = new Role("owner");
|
||||
public static final Role ADMIN = new Role("admin");
|
||||
public static final Role AGENT = new Role("agent");
|
||||
public static final Role TENANT = new Role("tenant");
|
||||
public static final Role REFERRER = new Role("referrer");
|
||||
OWNER,
|
||||
ADMIN,
|
||||
AGENT,
|
||||
TENANT,
|
||||
REFERRER,
|
||||
|
||||
GUEST;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ":" + roleName;
|
||||
return ":" + roleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return ((obj instanceof Role) && ((Role) obj).roleName.equals(this.roleName));
|
||||
String roleName() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class RbacGrantController implements RbacGrantsApi {
|
||||
// public ResponseEntity<String> allGrantsOfUserAsMermaid(
|
||||
// @RequestHeader(name = "current-user") String currentUser,
|
||||
// @RequestHeader(name = "assumed-roles", required = false) String assumedRoles) {
|
||||
// final var graph = RbacGrantsMermaidService.allGrantsToUser(currentUser);
|
||||
// final var graph = RbacGrantsDiagramService.allGrantsToUser(currentUser);
|
||||
// return ResponseEntity.ok(graph);
|
||||
// }
|
||||
|
||||
|
@ -1,204 +0,0 @@
|
||||
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.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService.Include.*;
|
||||
|
||||
// TODO: cleanup - this code was 'hacked' to quickly fix a specific problem, needs refactoring
|
||||
@Service
|
||||
public class RbacGrantsMermaidService {
|
||||
|
||||
public static void writeToFile(final String title, final String graph, final String fileName) {
|
||||
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
|
||||
writer.write("""
|
||||
### all grants to %s
|
||||
|
||||
```mermaid
|
||||
%s
|
||||
```
|
||||
""".formatted(title, graph));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public enum Include {
|
||||
DETAILS,
|
||||
USERS,
|
||||
PERMISSIONS,
|
||||
NOT_ASSUMED,
|
||||
TEST_ENTITIES,
|
||||
NON_TEST_ENTITIES
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private Context context;
|
||||
|
||||
@Autowired
|
||||
private RawRbacGrantRepository rawGrantRepo;
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
public String allGrantsToCurrentUser(final EnumSet<Include> includes) {
|
||||
final var graph = new HashSet<RawRbacGrantEntity>();
|
||||
for ( UUID subjectUuid: context.currentSubjectsUuids() ) {
|
||||
traverseGrantsTo(graph, subjectUuid, includes);
|
||||
}
|
||||
return toMermaidFlowchart(graph, includes);
|
||||
}
|
||||
|
||||
private void traverseGrantsTo(final Set<RawRbacGrantEntity> graph, final UUID refUuid, final EnumSet<Include> includes) {
|
||||
final var grants = rawGrantRepo.findByAscendingUuid(refUuid);
|
||||
grants.forEach(g -> {
|
||||
if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm ")) {
|
||||
return;
|
||||
}
|
||||
if (!includes.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(" test_")) {
|
||||
return;
|
||||
}
|
||||
if (!includes.contains(NON_TEST_ENTITIES) && !g.getDescendantIdName().contains(" test_")) {
|
||||
return;
|
||||
}
|
||||
graph.add(g);
|
||||
if (includes.contains(NOT_ASSUMED) || g.isAssumed()) {
|
||||
traverseGrantsTo(graph, g.getDescendantUuid(), includes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String allGrantsFrom(final UUID targetObject, final String op, final EnumSet<Include> includes) {
|
||||
final var refUuid = (UUID) em.createNativeQuery("SELECT uuid FROM rbacpermission WHERE objectuuid=:targetObject AND op=:op")
|
||||
.setParameter("targetObject", targetObject)
|
||||
.setParameter("op", op)
|
||||
.getSingleResult();
|
||||
final var graph = new HashSet<RawRbacGrantEntity>();
|
||||
traverseGrantsFrom(graph, refUuid, includes);
|
||||
return toMermaidFlowchart(graph, includes);
|
||||
}
|
||||
|
||||
private void traverseGrantsFrom(final Set<RawRbacGrantEntity> graph, final UUID refUuid, final EnumSet<Include> option) {
|
||||
final var grants = rawGrantRepo.findByDescendantUuid(refUuid);
|
||||
grants.forEach(g -> {
|
||||
if (!option.contains(USERS) && g.getAscendantIdName().startsWith("user ")) {
|
||||
return;
|
||||
}
|
||||
graph.add(g);
|
||||
if (option.contains(NOT_ASSUMED) || g.isAssumed()) {
|
||||
traverseGrantsFrom(graph, g.getAscendingUuid(), option);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String toMermaidFlowchart(final HashSet<RawRbacGrantEntity> graph, final EnumSet<Include> includes) {
|
||||
final var entities =
|
||||
includes.contains(DETAILS)
|
||||
? graph.stream()
|
||||
.flatMap(g -> Stream.of(
|
||||
new Node(g.getAscendantIdName(), g.getAscendingUuid()),
|
||||
new Node(g.getDescendantIdName(), g.getDescendantUuid()))
|
||||
)
|
||||
.collect(groupingBy(RbacGrantsMermaidService::renderEntityIdName))
|
||||
.entrySet().stream()
|
||||
.map(entity -> "subgraph " + quoted(entity.getKey()) + renderSubgraph(entity.getKey()) + "\n\n "
|
||||
+ entity.getValue().stream()
|
||||
.map(n -> renderNode(n.idName(), n.uuid()).replace("\n", "\n "))
|
||||
.sorted()
|
||||
.distinct()
|
||||
.collect(joining("\n\n ")))
|
||||
.collect(joining("\n\nend\n\n"))
|
||||
+ "\n\nend\n\n"
|
||||
: "";
|
||||
|
||||
final var grants = graph.stream()
|
||||
.map(g -> quoted(g.getAscendantIdName()) +
|
||||
(g.isAssumed() ? " --> " : " -.-> ") +
|
||||
quoted(g.getDescendantIdName()))
|
||||
.sorted()
|
||||
.collect(joining("\n"));
|
||||
|
||||
final var avoidCroppedNodeLabels = "%%{init:{'flowchart':{'htmlLabels':false}}}%%\n\n";
|
||||
return (includes.contains(DETAILS) ? avoidCroppedNodeLabels : "")
|
||||
+ "flowchart TB\n\n"
|
||||
+ entities
|
||||
+ grants;
|
||||
}
|
||||
|
||||
private String renderSubgraph(final String entityId) {
|
||||
// this does not work according to Mermaid bug https://github.com/mermaid-js/mermaid/issues/3806
|
||||
// if (entityId.contains("#")) {
|
||||
// final var parts = entityId.split("#");
|
||||
// final var table = parts[0];
|
||||
// final var entity = parts[1];
|
||||
// if (table.equals("entity")) {
|
||||
// return "[" + entity "]";
|
||||
// }
|
||||
// return "[" + table + "\n" + entity + "]";
|
||||
// }
|
||||
return "[" + entityId + "]";
|
||||
}
|
||||
|
||||
private static String renderEntityIdName(final Node node) {
|
||||
final var refType = refType(node.idName());
|
||||
if (refType.equals("user")) {
|
||||
return "users";
|
||||
}
|
||||
if (refType.equals("perm")) {
|
||||
return node.idName().split(" ", 4)[3];
|
||||
}
|
||||
if (refType.equals("role")) {
|
||||
final var withoutRolePrefix = node.idName().substring("role:".length());
|
||||
return withoutRolePrefix.substring(0, withoutRolePrefix.lastIndexOf('.'));
|
||||
}
|
||||
throw new IllegalArgumentException("unknown refType '" + refType + "' in '" + node.idName() + "'");
|
||||
}
|
||||
|
||||
private String renderNode(final String idName, final UUID uuid) {
|
||||
return quoted(idName) + renderNodeContent(idName, uuid);
|
||||
}
|
||||
|
||||
private String renderNodeContent(final String idName, final UUID uuid) {
|
||||
final var refType = refType(idName);
|
||||
|
||||
if (refType.equals("user")) {
|
||||
final var displayName = idName.substring(refType.length()+1);
|
||||
return "(" + displayName + "\nref:" + uuid + ")";
|
||||
}
|
||||
if (refType.equals("role")) {
|
||||
final var roleType = idName.substring(idName.lastIndexOf('.') + 1);
|
||||
return "[" + roleType + "\nref:" + uuid + "]";
|
||||
}
|
||||
if (refType.equals("perm")) {
|
||||
final var roleType = idName.split(" ")[1];
|
||||
return "{{" + roleType + "\nref:" + uuid + "}}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String refType(final String idName) {
|
||||
return idName.split(" ", 2)[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String quoted(final String idName) {
|
||||
return idName.replace(" ", ":").replaceAll("@.*", "");
|
||||
}
|
||||
}
|
||||
|
||||
record Node(String idName, UUID uuid) {
|
||||
|
||||
}
|
@ -41,8 +41,7 @@ public class TestCustomerEntity implements HasUuid {
|
||||
.withIdentityView(SQL.projection("prefix"))
|
||||
.withRestrictedViewOrderBy(SQL.expression("reference"))
|
||||
.withUpdatableColumns("reference", "prefix", "adminUserName")
|
||||
// TODO: do we want explicit specification of parent-independent insert permissions?
|
||||
// .toRole("global", ADMIN).grantPermission("customer", INSERT)
|
||||
.toRole("global", ADMIN).grantPermission("customer", INSERT)
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
with.owningUser(CREATOR).unassumed();
|
||||
|
@ -373,10 +373,12 @@ create table RbacPermission
|
||||
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
||||
objectUuid uuid not null references RbacObject,
|
||||
op RbacOp not null,
|
||||
opTableName varchar(60),
|
||||
unique (objectUuid, op)
|
||||
opTableName varchar(60)
|
||||
);
|
||||
|
||||
ALTER TABLE RbacPermission
|
||||
ADD CONSTRAINT RbacPermission_uc UNIQUE NULLS NOT DISTINCT (objectUuid, op, opTableName);
|
||||
|
||||
call create_journal('RbacPermission');
|
||||
|
||||
create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
@ -469,23 +471,6 @@ $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-duplicate-role-grant-exception:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure raiseDuplicateRoleGrantException(subRoleId uuid, superRoleId uuid)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
subRoleIdName text;
|
||||
superRoleIdName text;
|
||||
begin
|
||||
select roleIdName from rbacRole_ev where uuid=subRoleId into subRoleIdName;
|
||||
select roleIdName from rbacRole_ev where uuid=superRoleId into superRoleIdName;
|
||||
raise exception '[400] Duplicate role grant detected: role % (%) already granted to % (%)', subRoleId, subRoleIdName, superRoleId, superRoleIdName;
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-duplicate-role-grant-exception:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
@ -118,9 +118,32 @@ select 'global', (select uuid from RbacObject where objectTable = 'global'), 'ad
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating global admin role', null, null, null);
|
||||
select createRole(globalAdmin());
|
||||
call defineContext('creating global admin role', null, null, null);
|
||||
select createRole(globalAdmin());
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-GUEST-ROLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A global guest role.
|
||||
*/
|
||||
create or replace function globalGuest(assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'guest'::RbacRoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating global guest role', null, null, null);
|
||||
select createRole(globalGuest());
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-ADMIN-USERS:1 context:dev,tc endDelimiter:--//
|
||||
|
@ -1,4 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T15:13:04.479330676.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
|
||||
@ -15,69 +16,134 @@ call generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
--changeset hs-office-person-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles and their assignments for a new person for the AFTER INSERT TRIGGER.
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
create or replace function createRbacRolesForHsOfficePerson()
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficePerson(
|
||||
NEW hs_office_person
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
userUuids => array[currentUserUuid()],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonReferrer(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficePersonAdmin(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_person row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficePerson_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalAdmin()],
|
||||
userUuids => array[currentUserUuid()],
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
-- TODO: who is admin? the person itself? is it allowed for the person itself or a representative to update the data?
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonReferrer(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficePersonAdmin(NEW)]
|
||||
);
|
||||
|
||||
call buildRbacSystemForHsOfficePerson(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
|
||||
create trigger createRbacRolesForHsOfficePerson_Trigger
|
||||
after insert
|
||||
on hs_office_person
|
||||
create trigger insertTriggerForHsOfficePerson_tg
|
||||
after insert on hs_office_person
|
||||
for each row
|
||||
execute procedure createRbacRolesForHsOfficePerson();
|
||||
execute procedure insertTriggerForHsOfficePerson_tf();
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_person permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
permissionUuid uuid;
|
||||
roleUuid uuid;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_person permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
roleUuid := findRoleId(globalGuest());
|
||||
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_person');
|
||||
call grantPermissionToRole(roleUuid, permissionUuid);
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_person INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_person_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
globalGuest(),
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_person'));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_person_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_person_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_person.
|
||||
*/
|
||||
create or replace function hs_office_person_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_person not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
--//
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$
|
||||
concat(target.tradeName, target.familyName, target.givenName)
|
||||
concat(tradeName, familyName, givenName)
|
||||
$idName$);
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_person', 'concat(target.tradeName, target.familyName, target.givenName)',
|
||||
call generateRbacRestrictedView('hs_office_person',
|
||||
'concat(tradeName, familyName, givenName)',
|
||||
$updates$
|
||||
personType = new.personType,
|
||||
tradeName = new.tradeName,
|
||||
@ -87,48 +153,3 @@ call generateRbacRestrictedView('hs_office_person', 'concat(target.tradeName, ta
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-NEW-PERSON:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-person and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-person permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-person']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficePersonNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-person not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_person_insert_trigger
|
||||
before insert
|
||||
on hs_office_person
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new persons
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficePersonNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
||||
|
@ -27,71 +27,77 @@ create or replace function hsOfficeRelationshipRbacRolesTrigger()
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
hsOfficeRelationshipTenant RbacRoleDescriptor;
|
||||
newRelAnchor hs_office_person;
|
||||
newRelHolder hs_office_person;
|
||||
newAnchorPerson hs_office_person;
|
||||
newHolderPerson hs_office_person;
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
hsOfficeRelationshipTenant := hsOfficeRelationshipTenant(NEW);
|
||||
|
||||
select * from hs_office_person as p where p.uuid = NEW.relAnchorUuid into newRelAnchor;
|
||||
select * from hs_office_person as p where p.uuid = NEW.relHolderUuid into newRelHolder;
|
||||
select * from hs_office_person as p where p.uuid = NEW.relAnchorUuid into newAnchorPerson;
|
||||
select * from hs_office_person as p where p.uuid = NEW.relHolderUuid into newHolderPerson;
|
||||
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- cannot be generated using `tools/generate` because there are multiple grants to the same entity type
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[
|
||||
globalAdmin(),
|
||||
hsOfficePersonAdmin(newRelAnchor)]
|
||||
);
|
||||
globalAdmin()
|
||||
]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeRelationshipOwner(NEW)]
|
||||
);
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeRelationshipOwner(NEW),
|
||||
hsOfficePersonAdmin(newAnchorPerson)
|
||||
]
|
||||
);
|
||||
|
||||
-- the tenant role for those related users who can view the data
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipTenant,
|
||||
permissions => array['SELECT'],
|
||||
hsOfficeRelationshipAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeRelationshipAdmin(NEW),
|
||||
hsOfficePersonAdmin(newRelAnchor),
|
||||
hsOfficePersonAdmin(newRelHolder),
|
||||
hsOfficeContactAdmin(newContact)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficePersonTenant(newRelAnchor),
|
||||
hsOfficePersonTenant(newRelHolder),
|
||||
hsOfficeContactTenant(newContact)]
|
||||
);
|
||||
hsOfficePersonAdmin(newHolderPerson),
|
||||
hsOfficeContactAdmin(newContact)
|
||||
]
|
||||
);
|
||||
|
||||
-- anchor and holder admin roles need each others tenant role
|
||||
-- to be able to see the joined relationship
|
||||
-- TODO: this can probably be avoided through agent+guest roles
|
||||
call grantRoleToRole(hsOfficePersonTenant(newRelAnchor), hsOfficePersonAdmin(newRelHolder));
|
||||
call grantRoleToRole(hsOfficePersonTenant(newRelHolder), hsOfficePersonAdmin(newRelAnchor));
|
||||
call grantRoleToRoleIfNotNull(hsOfficePersonTenant(newRelHolder), hsOfficeContactAdmin(newContact));
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipTenant(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeRelationshipAgent(NEW)
|
||||
],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficePersonReferrer(newAnchorPerson),
|
||||
hsOfficePersonReferrer(newHolderPerson),
|
||||
hsOfficeContactReferrer(newContact)
|
||||
]
|
||||
);
|
||||
|
||||
if ( NEW.relType = 'REPRESENTATIVE' ) then
|
||||
call grantRoleToRole(hsOfficePersonAdmin(newHolderPerson), hsOfficePersonAdmin(newAnchorPerson));
|
||||
end if;
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.contactUuid <> NEW.contactUuid then
|
||||
-- nothing but the contact can be updated,
|
||||
-- only the contact can be updated,
|
||||
-- in other cases, a new relationship needs to be created and the old updated
|
||||
|
||||
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
|
||||
|
||||
call revokeRoleFromRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(oldContact) );
|
||||
call grantRoleToRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(newContact) );
|
||||
call revokeRoleFromRole( hsOfficeContactReferrer(oldContact), hsOfficeRelationshipTenant(NEW) );
|
||||
call grantRoleToRole( hsOfficeContactReferrer(newContact), hsOfficeRelationshipTenant(NEW) );
|
||||
|
||||
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeRelationshipTenant );
|
||||
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeRelationshipTenant );
|
||||
call revokeRoleFromRole( hsOfficeRelationshipAgent(NEW), hsOfficeContactAdmin(oldContact) );
|
||||
call grantRoleToRole( hsOfficeRelationshipAgent(NEW), hsOfficeContactAdmin(newContact) );
|
||||
end if;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
@ -136,8 +142,8 @@ call generateRbacIdentityViewFromProjection('hs_office_relationship', $idName$
|
||||
--changeset hs-office-relationship-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_relationship',
|
||||
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
|
||||
$updates$
|
||||
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
|
||||
$updates$
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
@ -1,72 +1,158 @@
|
||||
### hs_office_partner RBAC
|
||||
### rbac partner
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T15:29:41.494727519.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph external[ ]
|
||||
style external fill:#fff
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
subgraph partnerRel.contact["`**partnerRel.contact**`"]
|
||||
direction TB
|
||||
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerPerson
|
||||
style partnerPerson fill:#eee
|
||||
|
||||
role:partnerPerson.admin[partnerPerson.admin]
|
||||
end
|
||||
subgraph partnerRel.contact:roles[ ]
|
||||
style partnerRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
subgraph otherRelatedPerson
|
||||
style otherRelatedPerson fill:#eee
|
||||
|
||||
role:otherRelatedPerson.admin[otherRelatedPerson.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeRelationship[hsOfficeRelationship:PARTNER]
|
||||
direction TB
|
||||
style hsOfficeRelationship fill:#eee
|
||||
|
||||
role:global.admin
|
||||
--> role:hsOfficeRelationship.owner[relationship.owner]
|
||||
--> role:hsOfficeRelationship.admin[relationship.admin]
|
||||
--> role:hsOfficeRelationship.agent[relationship.agent]
|
||||
--> role:hsOfficeRelationship.tenant[relationship.tenant]
|
||||
|
||||
role:partnerPerson.admin --> role:hsOfficeRelationship.agent
|
||||
role:otherRelatedPerson.admin --> role:hsOfficeRelationship.tenant
|
||||
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
|
||||
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
|
||||
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph internal[ ]
|
||||
subgraph partner["`**partner**`"]
|
||||
direction TB
|
||||
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph hsOfficePartner
|
||||
style hsOfficePartner fill:#fff
|
||||
|
||||
perm:hsOfficePartner.*{{partner.*}}
|
||||
role:hsOfficeRelationship.owner ==> perm:hsOfficePartner.*
|
||||
|
||||
perm:hsOfficePartner.edit{{partner.edit}}
|
||||
role:hsOfficeRelationship.admin ==> perm:hsOfficePartner.edit
|
||||
|
||||
perm:hsOfficePartner.view{{partner.view}}
|
||||
role:hsOfficeRelationship.tenant ==> perm:hsOfficePartner.view
|
||||
subgraph partner:permissions[ ]
|
||||
style partner:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:partner:new-partner{{partner:new-partner}}
|
||||
perm:partner:DELETE{{partner:DELETE}}
|
||||
perm:partner:UPDATE{{partner:UPDATE}}
|
||||
perm:partner:SELECT{{partner:SELECT}}
|
||||
end
|
||||
|
||||
subgraph hsOfficePartnerDetails
|
||||
subgraph partnerRel["`**partnerRel**`"]
|
||||
direction TB
|
||||
style hsOfficePartnerDetails fill:#eee
|
||||
|
||||
perm:hsOfficePartnerDetails.*{{partnerDetails.*}}
|
||||
role:hsOfficeRelationship.owner ==> perm:hsOfficePartnerDetails.*
|
||||
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
subgraph partnerRel.contact["`**partnerRel.contact**`"]
|
||||
direction TB
|
||||
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
perm:hsOfficePartnerDetails.edit{{partnerDetails.edit}}
|
||||
role:hsOfficeRelationship.agent ==> perm:hsOfficePartnerDetails.edit
|
||||
role:hsOfficeRelationship.agent ==> perm:hsOfficePartnerDetails.view
|
||||
|
||||
perm:hsOfficePartnerDetails.view{{partnerDetails.view}}
|
||||
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.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.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 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.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:global:admin -.-> role:partnerRel.anchorPerson:owner
|
||||
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
|
||||
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
|
||||
role:global:admin -.-> role:partnerRel.holderPerson:owner
|
||||
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
|
||||
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
|
||||
role:global:admin -.-> role:partnerRel.contact:owner
|
||||
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
|
||||
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
|
||||
role:global:admin -.-> role:partnerRel:owner
|
||||
role:partnerRel:owner -.-> role:partnerRel:admin
|
||||
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
|
||||
role:partnerRel:admin -.-> role:partnerRel:agent
|
||||
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
|
||||
role:partnerRel:agent -.-> role:partnerRel:tenant
|
||||
role:partnerRel.holderPerson:admin -.-> 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
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:admin ==> perm:partner:new-partner
|
||||
role:partnerRel:admin ==> perm:partner:DELETE
|
||||
role:partnerRel:agent ==> perm:partner:UPDATE
|
||||
role:partnerRel:tenant ==> perm:partner:SELECT
|
||||
role:partnerRel:admin ==> perm:partnerDetails:DELETE
|
||||
role:partnerRel:agent ==> perm:partnerDetails:UPDATE
|
||||
role:partnerRel:agent ==> perm:partnerDetails:SELECT
|
||||
|
||||
```
|
||||
|
@ -32,58 +32,7 @@ begin
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- === ATTENTION: code generated from related Mermaid flowchart: ===
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerOwner(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newPartnerRole),
|
||||
hsOfficePersonTenant(newPerson),
|
||||
hsOfficeContactTenant(newContact)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerAdmin(NEW),
|
||||
hsOfficeRelationshipAdmin(newPartnerRole),
|
||||
hsOfficePersonAdmin(newPerson),
|
||||
hsOfficeContactAdmin(newContact)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerTenant(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerAgent(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newPartnerRole),
|
||||
hsOfficePersonGuest(newPerson),
|
||||
hsOfficeContactGuest(newContact)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerGuest(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficePartnerTenant(NEW)]
|
||||
);
|
||||
|
||||
-- === END of code generated from Mermaid flowchart. ===
|
||||
|
||||
-- Each partner-details entity belong exactly to one partner entity
|
||||
-- and it makes little sense just to delegate partner-details roles.
|
||||
-- Therefore, we did not model partner-details roles,
|
||||
-- but instead just assign extra permissions to existing partner-roles.
|
||||
|
||||
--Attention: Cannot be in partner-details because of insert order (partner is not in database yet)
|
||||
-- Permissions and Grants for Partner
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||
@ -96,21 +45,21 @@ begin
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipTenant(newPartnerRel), 'fail'),
|
||||
createPermissions(partnerUuid, array ['view'])
|
||||
getRoleId(hsOfficeRelationshipTenant(newPartnerRel)),
|
||||
createPermissions(partnerUuid, array ['SELECT'])
|
||||
);
|
||||
|
||||
-- Permissions and Grants for PartnerDetails
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel), 'fail'),
|
||||
createPermissions(partnerDetailsUuid, array ['*'])
|
||||
);
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||
createPermissions(partnerDetailsUuid, array ['DELETE'])
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel), 'fail'),
|
||||
createPermissions(partnerDetailsUuid, array ['edit'])
|
||||
);
|
||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
|
||||
createPermissions(partnerDetailsUuid, array ['UPDATE'])
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficeRelationshipTENANT.
|
||||
@ -118,7 +67,7 @@ begin
|
||||
-- Otherwise package-admins etc. would be able to read the data.
|
||||
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
|
||||
createPermissions(partnerDetailsUuid, array ['SELECT'])
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
@ -129,72 +78,72 @@ begin
|
||||
-- Revokes from Partner
|
||||
|
||||
call revokePermissionFromRole(
|
||||
findPermissionId(partnerUuid, 'view'),
|
||||
findPermissionId(partnerUuid, 'SELECT'),
|
||||
hsOfficeRelationshipTenant(oldPartnerRel)
|
||||
);
|
||||
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerUuid, 'edit'),
|
||||
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
||||
-- );
|
||||
--
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerUuid, '*'),
|
||||
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
||||
-- );
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerUuid, 'edit'),
|
||||
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
||||
-- );
|
||||
--
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerUuid, '*'),
|
||||
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
||||
-- );
|
||||
|
||||
-- Grants for Partner
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel), 'fail'),
|
||||
array[findPermissionId(partnerUuid, '*')]
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||
array[findPermissionId(partnerUuid, 'DELETE')]
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel), 'fail'),
|
||||
array[findPermissionId(partnerUuid, 'edit')]
|
||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
|
||||
array[findPermissionId(partnerUuid, 'UPDATE')]
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipTenant(newPartnerRel), 'fail'),
|
||||
array[findPermissionId(partnerUuid, 'view')]
|
||||
getRoleId(hsOfficeRelationshipTenant(newPartnerRel)),
|
||||
array[findPermissionId(partnerUuid, 'SELECT')]
|
||||
);
|
||||
|
||||
-- Revokes from PartnerDetails
|
||||
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerDetailsUuid, 'view'),
|
||||
-- hsOfficeRelationshipAgent(oldPartnerRel)
|
||||
-- );
|
||||
--
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerDetailsUuid, 'edit'),
|
||||
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
||||
-- );
|
||||
--
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerDetailsUuid, '*'),
|
||||
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
||||
-- );
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerDetailsUuid, 'SELECT'),
|
||||
-- hsOfficeRelationshipAgent(oldPartnerRel)
|
||||
-- );
|
||||
--
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerDetailsUuid, 'UPDATE'),
|
||||
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
||||
-- );
|
||||
--
|
||||
-- call revokePermissionFromRole(
|
||||
-- findPermissionId(partnerDetailsUuid, 'DELETE'),
|
||||
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
||||
-- );
|
||||
|
||||
-- Grants for PartnerDetails
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel), 'fail'),
|
||||
array[findPermissionId(partnerDetailsUuid, '*')]
|
||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||
array[findPermissionId(partnerDetailsUuid, 'DELETE')]
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel), 'fail'),
|
||||
array[findPermissionId(partnerDetailsUuid, 'edit')]
|
||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
|
||||
array[findPermissionId(partnerDetailsUuid, 'UPDATE')]
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
|
||||
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
|
||||
-- Otherwise package-admins etc. would be able to read the data.
|
||||
getRoleId(hsOfficeRelationshipAgent(newPartnerRel), 'fail'),
|
||||
array[findPermissionId(partnerDetailsUuid, 'view')]
|
||||
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
|
||||
array[findPermissionId(partnerDetailsUuid, 'SELECT')]
|
||||
);
|
||||
|
||||
end if;
|
||||
@ -203,7 +152,7 @@ begin
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call leaveTriggerForObjectUuid(partnerUuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
|
@ -1,50 +1,45 @@
|
||||
### hs_office_bankaccount RBAC Roles
|
||||
### rbac bankAccount
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T19:09:38.350576842.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
%%% RbacEntity.builder().forEntity(HsOfficeBankAccountEntity.class)
|
||||
%%% .alias("bankAccount")
|
||||
%% the global subgraph would get imported implicitly by later usage
|
||||
subgraph global
|
||||
style global fill: #eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeBankAccount
|
||||
|
||||
subgraph bankAccount["`**bankAccount**`"]
|
||||
direction TB
|
||||
style hsOfficeBankAccount fill: #e9f7ef
|
||||
style bankAccount fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
user:hsOfficeBankAccount.creator([bankAccount.creator])
|
||||
subgraph bankAccount:roles[ ]
|
||||
style bankAccount:roles fill:#dd4901,stroke:white
|
||||
|
||||
%%% .createRole(OWNER)
|
||||
role:hsOfficeBankAccount.owner[[bankAccount.owner]]
|
||||
%%% .withPermission(ALL)
|
||||
%% permissions
|
||||
role:hsOfficeBankAccount.owner --> perm:hsOfficeBankAccount.*{{hsOfficeBankAccount.*}}
|
||||
%% incoming
|
||||
%%% .withCreatorAsOwningUser()
|
||||
user:hsOfficeBankAccount.creator ---> role:hsOfficeBankAccount.owner
|
||||
%%% .withIncomingSuperRole(GlobalEntity.class, ADMIN)
|
||||
role:global.admin --> role:hsOfficeBankAccount.owner
|
||||
|
||||
%%% .createSubRole(ADMIN)
|
||||
role:hsOfficeBankAccount.admin[[bankAccount.admin]]
|
||||
%% permissions
|
||||
%%% .withPermission(EDIT)
|
||||
role:hsOfficeBankAccount.admin --> perm:hsOfficeBankAccount.edit{{hsOfficeBankAccount.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.owner ---> role:hsOfficeBankAccount.admin
|
||||
role:bankAccount:owner[[bankAccount:owner]]
|
||||
role:bankAccount:admin[[bankAccount:admin]]
|
||||
role:bankAccount:referrer[[bankAccount:referrer]]
|
||||
end
|
||||
|
||||
%%% .createSubRole(REFERRER)
|
||||
role:hsOfficeBankAccount.referrer[[bankAccount.referrer]]
|
||||
%% permissions
|
||||
%%% .withPermission(VIEW)
|
||||
role:hsOfficeBankAccount.referrer --> perm:hsOfficeBankAccount.view{{hsOfficeBankAccount.view}}
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.admin ---> role:hsOfficeBankAccount.referrer
|
||||
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:global:admin ==> role:bankAccount:owner
|
||||
role:bankAccount:owner ==> role:bankAccount:admin
|
||||
role:bankAccount:admin ==> role:bankAccount:referrer
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:guest ==> perm:bankAccount:INSERT
|
||||
role:bankAccount:owner ==> perm:bankAccount:DELETE
|
||||
role:bankAccount:admin ==> perm:bankAccount:UPDATE
|
||||
role:bankAccount:referrer ==> perm:bankAccount:SELECT
|
||||
|
||||
```
|
||||
|
@ -1,4 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T19:09:38.359318650.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
|
||||
@ -15,125 +16,141 @@ call generateRbacRoleDescriptors('hsOfficeBankAccount', 'hs_office_bankaccount')
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
--changeset hs-office-bankaccount-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles and their assignments for a new bankaccount for the AFTER INSERT TRIGGER.
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function createRbacRolesForHsOfficeBankAccount()
|
||||
create or replace procedure buildRbacSystemForHsOfficeBankAccount(
|
||||
NEW hs_office_bankaccount
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
userUuids => array[currentUserUuid()],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountReferrer(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_bankaccount row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficeBankAccount_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalAdmin()],
|
||||
userUuids => array[currentUserUuid()],
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountAdmin(NEW),
|
||||
incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountGuest(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficeBankAccountTenant(NEW)]
|
||||
);
|
||||
|
||||
call buildRbacSystemForHsOfficeBankAccount(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
|
||||
create trigger createRbacRolesForHsOfficeBankAccount_Trigger
|
||||
after insert
|
||||
on hs_office_bankaccount
|
||||
create trigger insertTriggerForHsOfficeBankAccount_tg
|
||||
after insert on hs_office_bankaccount
|
||||
for each row
|
||||
execute procedure createRbacRolesForHsOfficeBankAccount();
|
||||
execute procedure insertTriggerForHsOfficeBankAccount_tf();
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_bankaccount permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
permissionUuid uuid;
|
||||
roleUuid uuid;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_bankaccount permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
roleUuid := findRoleId(globalGuest());
|
||||
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_bankaccount');
|
||||
call grantPermissionToRole(roleUuid, permissionUuid);
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_bankaccount INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_bankaccount_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
globalGuest(),
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_bankaccount_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_bankaccount_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_bankaccount.
|
||||
*/
|
||||
create or replace function hs_office_bankaccount_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_bankaccount not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
--//
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$
|
||||
target.iban || ':' || target.holder
|
||||
concat(iban, ':', holder)
|
||||
$idName$);
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_bankaccount', 'target.holder',
|
||||
call generateRbacRestrictedView('hs_office_bankaccount',
|
||||
$orderBy$
|
||||
concat(iban, ':', holder)
|
||||
$orderBy$,
|
||||
$updates$
|
||||
holder = new.holder,
|
||||
holder = new.holder,
|
||||
iban = new.iban,
|
||||
bic = new.bic
|
||||
$updates$);
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-NEW-BANKACCOUNT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-bankaccount and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-bankaccount permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-bankaccount']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeBankAccountNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-bankaccount not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_bankaccount_insert_trigger
|
||||
before insert
|
||||
on hs_office_bankaccount
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new bankaccounts
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeBankAccountNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
||||
|
||||
|
@ -1,62 +1,178 @@
|
||||
### hs_office_sepaMandate RBAC
|
||||
### rbac sepaMandate
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T18:29:47.084556363.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeBankAccount
|
||||
subgraph bankAccount["`**bankAccount**`"]
|
||||
direction TB
|
||||
style hsOfficeBankAccount fill:#eee
|
||||
|
||||
role:hsOfficeBankAccount.owner[bankAccount.owner]
|
||||
--> role:hsOfficeBankAccount.admin[bankAccount.admin]
|
||||
--> role:hsOfficeBankAccount.referrer[bankAccount.referrer]
|
||||
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 hsOfficeRelationship:DEBITOR
|
||||
subgraph debitorRel.contact["`**debitorRel.contact**`"]
|
||||
direction TB
|
||||
style hsOfficeRelationship:DEBITOR fill:#eee
|
||||
|
||||
role:hsOfficeRelationship:DEBITOR.owner[debitorRel.owner]
|
||||
--> role:hsOfficeRelationship:DEBITOR.admin[debitorRel.admin]
|
||||
--> role:hsOfficeRelationship:DEBITOR.agent[debitorRel.agent]
|
||||
--> role:hsOfficeRelationship:DEBITOR.tenant[debitorRel.tenant]
|
||||
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 hsOfficeSepaMandate
|
||||
|
||||
role:hsOfficeSepaMandate.owner[sepaMandate.owner]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.owner --> perm:hsOfficeSepaMandate.*{{sepaMandate.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficeSepaMandate.owner
|
||||
|
||||
role:hsOfficeSepaMandate.admin[sepaMandate.admin]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.admin --> perm:hsOfficeSepaMandate.edit{{sepaMandate.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.owner ---> role:hsOfficeSepaMandate.admin
|
||||
|
||||
role:hsOfficeSepaMandate.agent[sepaMandate.agent]
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.admin ---> role:hsOfficeSepaMandate.agent
|
||||
role:hsOfficeRelationship:DEBITOR.admin --> role:hsOfficeSepaMandate.agent
|
||||
role:hsOfficeBankAccount.admin --> role:hsOfficeSepaMandate.agent
|
||||
%% outgoing
|
||||
role:hsOfficeSepaMandate.admin --> role:hsOfficeBankAccount.referrer
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeRelationship:DEBITOR.tenant
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeBankAccount.referrer
|
||||
|
||||
role:hsOfficeSepaMandate.tenant[sepaMandate.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeSepaMandate.tenant
|
||||
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.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}}
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel["`**debitorRel**`"]
|
||||
direction TB
|
||||
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
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.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.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 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
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==> role:sepaMandate:owner
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:admin -.-> role:debitorRel.anchorPerson:owner
|
||||
role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin
|
||||
role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer
|
||||
role:global:admin -.-> role:debitorRel.holderPerson:owner
|
||||
role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin
|
||||
role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer
|
||||
role:global:admin -.-> role:debitorRel.contact:owner
|
||||
role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin
|
||||
role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer
|
||||
role:global:admin -.-> role:debitorRel:owner
|
||||
role:debitorRel:owner -.-> role:debitorRel:admin
|
||||
role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin
|
||||
role:debitorRel:admin -.-> role:debitorRel:agent
|
||||
role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent
|
||||
role:debitorRel:agent -.-> role:debitorRel:tenant
|
||||
role:debitorRel.holderPerson:admin -.-> 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:global:admin -.-> role:bankAccount:owner
|
||||
role:bankAccount:owner -.-> role:bankAccount:admin
|
||||
role:bankAccount:admin -.-> role:bankAccount:referrer
|
||||
role: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
|
||||
|
||||
```
|
||||
|
@ -1,4 +1,5 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T18:29:47.095199204.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-OBJECT:1 endDelimiter:--//
|
||||
@ -15,105 +16,123 @@ call generateRbacRoleDescriptors('hsOfficeSepaMandate', 'hs_office_sepamandate')
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
--changeset hs-office-sepamandate-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for sepaMandate entities.
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeSepaMandateRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
create or replace procedure buildRbacSystemForHsOfficeSepaMandate(
|
||||
NEW hs_office_sepamandate
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newHsOfficeDebitor hs_office_debitor;
|
||||
newhsOfficeRelationship:DEBITOR hs_office_relationship;
|
||||
newHsOfficeBankAccount hs_office_bankAccount;
|
||||
newBankAccount hs_office_bankaccount;
|
||||
newDebitorRel hs_office_relationship;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.bankAccountUuid into newBankAccount;
|
||||
SELECT * FROM hs_office_relationship WHERE uuid = NEW.debitorUuid into newDebitorRel;
|
||||
|
||||
select * from hs_office_debitor as p where p.uuid = NEW.debitorUuid into newHsOfficeDebitor;
|
||||
select * from hs_office_relationship as r where r.uuid = newHsOfficeDebitor.debitorRelUuid into newhsOfficeRelationship:DEBITOR;
|
||||
select * from hs_office_bankAccount as c where c.uuid = NEW.bankAccountUuid into newHsOfficeBankAccount;
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
userUuids => array[currentUserUuid()],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)]
|
||||
);
|
||||
|
||||
-- === ATTENTION: code generated from related Mermaid flowchart: ===
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAgent(NEW),
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeBankAccountReferrer(newBankAccount),
|
||||
hsOfficeRelationshipAgent(newDebitorRel)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeSepaMandateOwner(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeBankAccountTenant(newHsOfficeBankAccount)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeSepaMandateAdmin(NEW),
|
||||
hsOfficeRelationshipAdmin(newhsOfficeRelationship:DEBITOR),
|
||||
hsOfficeBankAccountAdmin(newHsOfficeBankAccount)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newhsOfficeRelationship:DEBITOR)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateAgent(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipReferrer(newhsOfficeRelationship:DEBITOR),
|
||||
hsOfficeBankAccountGuest(newHsOfficeBankAccount)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateGuest(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateTenant(NEW)]
|
||||
);
|
||||
|
||||
-- === END of code generated from Mermaid flowchart. ===
|
||||
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateReferrer(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeRelationshipAgent(newDebitorRel),
|
||||
hsOfficeBankAccountAdmin(newBankAccount),
|
||||
hsOfficeSepaMandateAgent(NEW)],
|
||||
outgoingSubRoles => array[hsOfficeRelationshipTenant(newDebitorRel)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_sepamandate row.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeSepaMandate_Trigger
|
||||
after insert
|
||||
on hs_office_sepamandate
|
||||
|
||||
create or replace function insertTriggerForHsOfficeSepaMandate_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficeSepaMandate(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficeSepaMandate_tg
|
||||
after insert on hs_office_sepamandate
|
||||
for each row
|
||||
execute procedure hsOfficeSepaMandateRbacRolesTrigger();
|
||||
execute procedure insertTriggerForHsOfficeSepaMandate_tf();
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate.
|
||||
*/
|
||||
create or replace function hs_office_sepamandate_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_sepamandate not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_sepamandate_insert_permission_check_tg
|
||||
before insert on hs_office_sepamandate
|
||||
for each row
|
||||
-- As there is no explicit INSERT grant specified for this table,
|
||||
-- only global admins are allowed to insert any rows.
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure hs_office_sepamandate_insert_permission_missing_tf();
|
||||
|
||||
--//
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityViewFromProjection('hs_office_sepamandate', 'target.reference');
|
||||
|
||||
call generateRbacIdentityViewFromQuery('hs_office_sepamandate', $idName$
|
||||
select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName
|
||||
from hs_office_sepamandate sm
|
||||
join hs_office_bankaccount ba on ba.uuid = sm.bankAccountUuid
|
||||
|
||||
$idName$);
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_sepamandate',
|
||||
orderby => 'target.reference',
|
||||
columnUpdates => $updates$
|
||||
'validity',
|
||||
$updates$
|
||||
reference = new.reference,
|
||||
agreement = new.agreement,
|
||||
validity = new.validity
|
||||
@ -121,48 +140,3 @@ call generateRbacRestrictedView('hs_office_sepamandate',
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-NEW-SepaMandate:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-sepaMandate and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-sepaMandate permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-sepamandate']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeSepaMandateNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-sepaMandate not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_sepamandate_insert_trigger
|
||||
before insert
|
||||
on hs_office_sepamandate
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new sepaMandates
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeSepaMandateNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
||||
|
@ -50,25 +50,21 @@ begin
|
||||
-- Permissions and Grants for Debitor
|
||||
|
||||
-- call grantPermissionsToRole(
|
||||
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel), 'fail'),
|
||||
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel)),
|
||||
-- createPermissions(partnerUuid, array ['DELETE'])
|
||||
-- );
|
||||
--
|
||||
-- call grantPermissionsToRole(
|
||||
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel), 'fail'),
|
||||
-- createPermissions(partnerUuid, array ['edit'])
|
||||
-- createPermissions(partnerUuid, array ['UPDATE'])
|
||||
-- );
|
||||
--
|
||||
-- call grantPermissionsToRole(
|
||||
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel), 'fail'),
|
||||
-- createPermissions(partnerUuid, array ['view'])
|
||||
-- createPermissions(partnerUuid, array ['SELECT'])
|
||||
-- );
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorAdmin(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeDebitorOwner(NEW)]
|
||||
);
|
||||
-- Grants to and from related Partner Relationship
|
||||
|
||||
-- call grantRoleToRole(hsOfficeRelationshipAdmin(newDebitorRel), hsOfficeRelationshipAdmin(newPartnerRel), true);
|
||||
-- call grantRoleToRole(hsOfficeRelationshipAgent(newPartnerRel), hsOfficeRelationshipAdmin(newDebitorRel), true);
|
||||
@ -78,12 +74,10 @@ begin
|
||||
|
||||
-- Grants to and from refundBankAccount
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorGuest(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeDebitorTenant(NEW)]
|
||||
);
|
||||
-- if newBankAccount is not null then
|
||||
-- call grantRoleToRole(hsOfficeBankAccountReferrer(newBankAccount), hsOfficeRelationshipAgent(newDebitorRel), true);
|
||||
-- call grantRoleToRole(hsOfficeRelationshipAgent(newDebitorRel), hsOfficeBankAccountAdmin(newBankAccount), true);
|
||||
-- end if;
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
@ -93,18 +87,18 @@ begin
|
||||
from hs_office_relationship as r where r.relType = 'ACCOUNTING' and r.relHolderUuid = NEW.debitorRelUuid;
|
||||
|
||||
-- call grantPermissionsToRole(
|
||||
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel), 'fail'),
|
||||
-- createPermissions(partnerUuid, array ['*'])
|
||||
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel)),
|
||||
-- createPermissions(partnerUuid, array ['DELETE'])
|
||||
-- );
|
||||
--
|
||||
-- call grantPermissionsToRole(
|
||||
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel), 'fail'),
|
||||
-- createPermissions(partnerUuid, array ['edit'])
|
||||
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel)),
|
||||
-- createPermissions(partnerUuid, array ['UPDATE'])
|
||||
-- );
|
||||
--
|
||||
-- call grantPermissionsToRole(
|
||||
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel), 'fail'),
|
||||
-- createPermissions(partnerUuid, array ['view'])
|
||||
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel)),
|
||||
-- createPermissions(partnerUuid, array ['SELECT'])
|
||||
-- );
|
||||
|
||||
end if;
|
||||
|
@ -9,8 +9,8 @@ import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEnti
|
||||
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService;
|
||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService.Include;
|
||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
|
||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService.Include;
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
|
||||
import net.hostsharing.test.Array;
|
||||
import net.hostsharing.test.JpaAttempt;
|
||||
@ -40,7 +40,7 @@ import static net.hostsharing.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class, RbacGrantsMermaidService.class })
|
||||
@Import( { Context.class, JpaAttempt.class, RbacGrantsDiagramService.class })
|
||||
class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
||||
|
||||
@Autowired
|
||||
@ -71,7 +71,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
||||
JpaAttempt jpaAttempt;
|
||||
|
||||
@Autowired
|
||||
RbacGrantsMermaidService mermaidService;
|
||||
RbacGrantsDiagramService mermaidService;
|
||||
|
||||
@MockBean
|
||||
HttpServletRequest request;
|
||||
@ -315,7 +315,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
||||
context("superuser-alex@hostsharing.net");
|
||||
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fif");
|
||||
|
||||
RbacGrantsMermaidService.writeToFile("initial partner: Fourth eG + fourth contact",
|
||||
RbacGrantsDiagramService.writeToFile("initial partner: Fourth eG + fourth contact",
|
||||
mermaidService.allGrantsFrom(givenDebitor.getUuid(), "view", EnumSet.of(Include.USERS, Include.DETAILS)),
|
||||
"doc/all-grants-before-globalAdmin_canUpdateArbitraryDebitor.md");
|
||||
|
||||
|
@ -465,24 +465,14 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
||||
final var givenPartnerPerson = personRepo.findPersonByOptionalNameLike(person).get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
||||
|
||||
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
||||
.relHolder(givenPartnerPerson)
|
||||
.relType(HsOfficeRelationshipType.PARTNER)
|
||||
.relAnchor(givenMandantorPerson)
|
||||
.contact(givenContact)
|
||||
.build();
|
||||
relationshipRepo.save(partnerRole);
|
||||
|
||||
final var newPartner = HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(partnerNumber)
|
||||
.partnerRole(partnerRole)
|
||||
.person(givenPartnerPerson)
|
||||
.contact(givenContact)
|
||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||
.build();
|
||||
|
||||
return partnerRepo.save(newPartner);
|
||||
}).assertSuccessful().returnedValue();
|
||||
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
||||
.relHolder(givenPartnerPerson)
|
||||
.relType(HsOfficeRelationshipType.PARTNER)
|
||||
.relAnchor(givenMandantorPerson)
|
||||
.contact(givenContact)
|
||||
.build();
|
||||
relationshipRepo.save(partnerRole);
|
||||
return partnerRole;
|
||||
}
|
||||
|
||||
void exactlyThesePartnersAreReturned(final List<HsOfficePartnerEntity> actualResult, final String... partnerNames) {
|
||||
|
@ -59,7 +59,6 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
||||
final var count = personRepo.count();
|
||||
|
||||
// when
|
||||
|
||||
final var result = attempt(em, () -> toCleanup(personRepo.save(
|
||||
hsOfficePerson("a new person"))));
|
||||
|
||||
|
@ -1,136 +0,0 @@
|
||||
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.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.lang.String.join;
|
||||
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("superuser-alex@hostsharing.net", "test_domain#xxx00-aaaa.owner");
|
||||
final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.TEST_ENTITIES));
|
||||
|
||||
assertThat(graph).isEqualTo("""
|
||||
flowchart TB
|
||||
|
||||
role:test_package#xxx00.tenant[
|
||||
test_package
|
||||
xxx00.t
|
||||
tenant] --> role:test_customer#xxx.tenant[
|
||||
test_customer
|
||||
xxx.t
|
||||
tenant]
|
||||
role:test_domain#xxx00-aaaa.owner[
|
||||
test_domain
|
||||
xxx00-aaaa.o
|
||||
owner] --> role:test_domain#xxx00-aaaa.admin[
|
||||
test_domain
|
||||
xxx00-aaaa.a
|
||||
admin]
|
||||
role:test_domain#xxx00-aaaa.admin[
|
||||
test_domain
|
||||
xxx00-aaaa.a
|
||||
admin] --> role:test_package#xxx00.tenant[
|
||||
test_package
|
||||
xxx00.t
|
||||
tenant]
|
||||
""".trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
void allGrantsToCurrentUserIncludingPermissions() {
|
||||
context("superuser-alex@hostsharing.net", "test_domain#xxx00-aaaa.owner");
|
||||
final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.TEST_ENTITIES, Include.PERMISSIONS));
|
||||
|
||||
assertThat(graph).isEqualTo("""
|
||||
flowchart TB
|
||||
|
||||
role:test_domain#xxx00-aaaa.owner[
|
||||
test_domain
|
||||
xxx00-aaaa.o
|
||||
owner] --> perm:*:on:test_domain#xxx00-aaaa{{
|
||||
test_domain
|
||||
xxx00-aaaa
|
||||
*}}
|
||||
role:test_customer#xxx.tenant[
|
||||
test_customer
|
||||
xxx.t
|
||||
tenant] --> perm:view:on:test_customer#xxx{{
|
||||
test_customer
|
||||
xxx
|
||||
view}}
|
||||
role:test_domain#xxx00-aaaa.admin[
|
||||
test_domain
|
||||
xxx00-aaaa.a
|
||||
admin] --> perm:edit:on:test_domain#xxx00-aaaa{{
|
||||
test_domain
|
||||
xxx00-aaaa
|
||||
edit}}
|
||||
role:test_package#xxx00.tenant[
|
||||
test_package
|
||||
xxx00.t
|
||||
tenant] --> role:test_customer#xxx.tenant[
|
||||
test_customer
|
||||
xxx.t
|
||||
tenant]
|
||||
role:test_domain#xxx00-aaaa.owner[
|
||||
test_domain
|
||||
xxx00-aaaa.o
|
||||
owner] --> role:test_domain#xxx00-aaaa.admin[
|
||||
test_domain
|
||||
xxx00-aaaa.a
|
||||
admin]
|
||||
role:test_package#xxx00.tenant[
|
||||
test_package
|
||||
xxx00.t
|
||||
tenant] --> perm:view:on:test_package#xxx00{{
|
||||
test_package
|
||||
xxx00
|
||||
view}}
|
||||
role:test_domain#xxx00-aaaa.admin[
|
||||
test_domain
|
||||
xxx00-aaaa.a
|
||||
admin] --> role:test_package#xxx00.tenant[
|
||||
test_package
|
||||
xxx00.t
|
||||
tenant]
|
||||
""".trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
// @Disabled
|
||||
void print() throws IOException {
|
||||
//context("superuser-alex@hostsharing.net", "hs_office_person#FirbySusan.admin");
|
||||
context("superuser-alex@hostsharing.net");
|
||||
|
||||
//final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.NON_TEST_ENTITIES, Include.PERMISSIONS));
|
||||
|
||||
final var targetObject = (UUID) em.createNativeQuery("SELECT uuid FROM hs_office_coopassetstransaction WHERE reference='ref 1000101-1'").getSingleResult();
|
||||
final var graph = grantsMermaidService.allGrantsFrom(targetObject, "view", EnumSet.of(Include.USERS));
|
||||
|
||||
RbacGrantsMermaidService.writeToFile(join(";", context.getAssumedRoles()), graph, "doc/all-grants.md");
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@ spring:
|
||||
platform: postgres
|
||||
|
||||
datasource:
|
||||
url: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url-local: jdbc:postgresql://localhost:5432/postgres
|
||||
url-tc: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||
url: jdbc:postgresql://localhost:5432/postgres
|
||||
username: postgres
|
||||
password: password
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
besser jeder