WIP
This commit is contained in:
parent
e422db9081
commit
9788205724
@ -59,8 +59,11 @@ public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable {
|
|||||||
|
|
||||||
public static RbacView rbac() {
|
public static RbacView rbac() {
|
||||||
return rbacViewFor("bankAccount", HsOfficeBankAccountEntity.class)
|
return rbacViewFor("bankAccount", HsOfficeBankAccountEntity.class)
|
||||||
.withIdentityView(SQL.projection("iban || ':' || holder"))
|
.withIdentityView(SQL.projection("concat(iban, ':', holder)"))
|
||||||
.withUpdatableColumns("holder", "iban", "bic")
|
.withUpdatableColumns("holder", "iban", "bic")
|
||||||
|
|
||||||
|
.toRole("global", GUEST).grantPermission("bankAccount", INSERT)
|
||||||
|
|
||||||
.createRole(OWNER, (with) -> {
|
.createRole(OWNER, (with) -> {
|
||||||
with.owningUser(CREATOR);
|
with.owningUser(CREATOR);
|
||||||
with.incomingSuperRole(GLOBAL, ADMIN);
|
with.incomingSuperRole(GLOBAL, ADMIN);
|
||||||
@ -75,6 +78,6 @@ public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
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)
|
return rbacViewFor("person", HsOfficePersonEntity.class)
|
||||||
.withIdentityView(SQL.projection("concat(tradeName, familyName, givenName)"))
|
.withIdentityView(SQL.projection("concat(tradeName, familyName, givenName)"))
|
||||||
.withUpdatableColumns("personType", "tradeName", "givenName", "familyName")
|
.withUpdatableColumns("personType", "tradeName", "givenName", "familyName")
|
||||||
|
.toRole("global", GUEST).grantPermission("person", INSERT)
|
||||||
|
|
||||||
.createRole(OWNER, (with) -> {
|
.createRole(OWNER, (with) -> {
|
||||||
with.permission(DELETE);
|
with.permission(DELETE);
|
||||||
with.owningUser(CREATOR);
|
with.owningUser(CREATOR);
|
||||||
@ -93,6 +95,6 @@ public class HsOfficePersonEntity implements HasUuid, Stringifyable {
|
|||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
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() {
|
public static RbacView rbac() {
|
||||||
return rbacViewFor("sepaMandate", HsOfficeSepaMandateEntity.class)
|
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")
|
.withUpdatableColumns("reference", "agreement", "validity")
|
||||||
|
|
||||||
.importEntityAlias("debitorRel", HsOfficeRelationshipEntity.class, dependsOnColumn("debitorRelUuid"))
|
.importEntityAlias("debitorRel", HsOfficeRelationshipEntity.class, dependsOnColumn("debitorRelUuid"))
|
||||||
@ -111,17 +116,17 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid {
|
|||||||
})
|
})
|
||||||
.createSubRole(AGENT, (with) -> {
|
.createSubRole(AGENT, (with) -> {
|
||||||
with.outgoingSubRole("bankAccount", REFERRER);
|
with.outgoingSubRole("bankAccount", REFERRER);
|
||||||
with.outgoingSubRole("debitorRel", AGENT);
|
with.outgoingSubRole("debitor", AGENT);
|
||||||
})
|
})
|
||||||
.createSubRole(REFERRER, (with) -> {
|
.createSubRole(REFERRER, (with) -> {
|
||||||
with.incomingSuperRole("bankAccount", ADMIN);
|
with.incomingSuperRole("bankAccount", ADMIN);
|
||||||
with.incomingSuperRole("debitorRel", AGENT);
|
with.incomingSuperRole("debitor", AGENT);
|
||||||
with.outgoingSubRole("debitorRel", TENANT);
|
with.outgoingSubRole("debitorRel", TENANT);
|
||||||
with.permission(SELECT);
|
with.permission(SELECT);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
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}
|
FOR row IN SELECT * FROM ${rawSuperTableName}
|
||||||
LOOP
|
LOOP
|
||||||
roleUuid := findRoleId(${rawSuperRoleDescriptor}(row));
|
roleUuid := findRoleId(${rawSuperRoleDescriptor});
|
||||||
permissionUuid := createPermission(row.uuid, 'INSERT', '${rawSubTableName}');
|
permissionUuid := createPermission(row.uuid, 'INSERT', '${rawSubTableName}');
|
||||||
call grantPermissionToRole(roleUuid, permissionUuid);
|
call grantPermissionToRole(roleUuid, permissionUuid);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
@ -62,7 +62,7 @@ public class InsertTriggerGenerator {
|
|||||||
""",
|
""",
|
||||||
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()),
|
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||||
with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()),
|
with("rawSuperTableName", superRoleDef.getEntityAlias().getRawTableName()),
|
||||||
with("rawSuperRoleDescriptor", toVar(superRoleDef))
|
with("rawSuperRoleDescriptor", toRoleDescriptor(superRoleDef, "row"))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public class InsertTriggerGenerator {
|
|||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
call grantPermissionToRole(
|
call grantPermissionToRole(
|
||||||
${rawSuperRoleDescriptor}(NEW),
|
${rawSuperRoleDescriptor},
|
||||||
createPermission(NEW.uuid, 'INSERT', '${rawSubTableName}'));
|
createPermission(NEW.uuid, 'INSERT', '${rawSubTableName}'));
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
@ -91,7 +91,7 @@ public class InsertTriggerGenerator {
|
|||||||
""",
|
""",
|
||||||
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()),
|
with("rawSubTableName", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||||
with("rawSuperTableName", superRoleDef.getEntityAlias().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()));
|
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||||
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
||||||
plPgSql.writeLn("""
|
if (!g.getSuperRoleDef().getEntityAlias().isGlobal()) {
|
||||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
plPgSql.writeLn(
|
||||||
before insert on ${rawSubTable}
|
"""
|
||||||
for each row
|
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||||
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
|
before insert on ${rawSubTable}
|
||||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
for each row
|
||||||
""",
|
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
|
||||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName() ));
|
""",
|
||||||
|
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("""
|
plPgSql.writeLn("""
|
||||||
@ -162,4 +186,12 @@ public class InsertTriggerGenerator {
|
|||||||
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName());
|
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$);
|
$idName$);
|
||||||
""";
|
""";
|
||||||
case SQL_QUERY -> """
|
case SQL_QUERY -> """
|
||||||
call generateRbacIdentityViewFromProjection('${rawTableName}', $idName$
|
call generateRbacIdentityViewFromQuery('${rawTableName}', $idName$
|
||||||
${identityViewSqlPart}
|
${identityViewSqlPart}
|
||||||
$idName$);
|
$idName$);
|
||||||
""";
|
""";
|
||||||
|
@ -24,9 +24,11 @@ public class RbacRestrictedViewGenerator {
|
|||||||
--changeset ${liquibaseTagPrefix}-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
--changeset ${liquibaseTagPrefix}-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('${rawTableName}',
|
call generateRbacRestrictedView('${rawTableName}',
|
||||||
'${orderBy}',
|
$orderBy$
|
||||||
|
${orderBy}
|
||||||
|
$orderBy$,
|
||||||
$updates$
|
$updates$
|
||||||
${updates}
|
${updates}
|
||||||
$updates$);
|
$updates$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -626,22 +626,23 @@ public class RbacView {
|
|||||||
return tableName.substring(0, tableName.length() - "_rv".length());
|
return tableName.substring(0, tableName.length() - "_rv".length());
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Role(String roleName) {
|
public enum Role {
|
||||||
|
|
||||||
public static final Role OWNER = new Role("owner");
|
OWNER,
|
||||||
public static final Role ADMIN = new Role("admin");
|
ADMIN,
|
||||||
public static final Role AGENT = new Role("agent");
|
AGENT,
|
||||||
public static final Role TENANT = new Role("tenant");
|
TENANT,
|
||||||
public static final Role REFERRER = new Role("referrer");
|
REFERRER,
|
||||||
|
|
||||||
|
GUEST;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return ":" + roleName;
|
return ":" + roleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
String roleName() {
|
||||||
public boolean equals(final Object obj) {
|
return name().toLowerCase();
|
||||||
return ((obj instanceof Role) && ((Role) obj).roleName.equals(this.roleName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ public class RbacGrantController implements RbacGrantsApi {
|
|||||||
// public ResponseEntity<String> allGrantsOfUserAsMermaid(
|
// public ResponseEntity<String> allGrantsOfUserAsMermaid(
|
||||||
// @RequestHeader(name = "current-user") String currentUser,
|
// @RequestHeader(name = "current-user") String currentUser,
|
||||||
// @RequestHeader(name = "assumed-roles", required = false) String assumedRoles) {
|
// @RequestHeader(name = "assumed-roles", required = false) String assumedRoles) {
|
||||||
// final var graph = RbacGrantsMermaidService.allGrantsToUser(currentUser);
|
// final var graph = RbacGrantsDiagramService.allGrantsToUser(currentUser);
|
||||||
// return ResponseEntity.ok(graph);
|
// 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"))
|
.withIdentityView(SQL.projection("prefix"))
|
||||||
.withRestrictedViewOrderBy(SQL.expression("reference"))
|
.withRestrictedViewOrderBy(SQL.expression("reference"))
|
||||||
.withUpdatableColumns("reference", "prefix", "adminUserName")
|
.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) -> {
|
.createRole(OWNER, (with) -> {
|
||||||
with.owningUser(CREATOR).unassumed();
|
with.owningUser(CREATOR).unassumed();
|
||||||
|
@ -373,10 +373,12 @@ create table RbacPermission
|
|||||||
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
||||||
objectUuid uuid not null references RbacObject,
|
objectUuid uuid not null references RbacObject,
|
||||||
op RbacOp not null,
|
op RbacOp not null,
|
||||||
opTableName varchar(60),
|
opTableName varchar(60)
|
||||||
unique (objectUuid, op)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ALTER TABLE RbacPermission
|
||||||
|
ADD CONSTRAINT RbacPermission_uc UNIQUE NULLS NOT DISTINCT (objectUuid, op, opTableName);
|
||||||
|
|
||||||
call create_journal('RbacPermission');
|
call create_journal('RbacPermission');
|
||||||
|
|
||||||
create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
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:--//
|
--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;
|
begin transaction;
|
||||||
call defineContext('creating global admin role', null, null, null);
|
call defineContext('creating global admin role', null, null, null);
|
||||||
select createRole(globalAdmin());
|
select createRole(globalAdmin());
|
||||||
commit;
|
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:--//
|
--changeset rbac-global-ADMIN-USERS:1 context:dev,tc endDelimiter:--//
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
--liquibase formatted sql
|
--liquibase formatted sql
|
||||||
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T15:13:04.479330676.
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
|
--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
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
if TG_OP <> 'INSERT' then
|
call buildRbacSystemForHsOfficePerson(NEW);
|
||||||
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)]
|
|
||||||
);
|
|
||||||
|
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
create trigger insertTriggerForHsOfficePerson_tg
|
||||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
after insert on hs_office_person
|
||||||
*/
|
|
||||||
|
|
||||||
create trigger createRbacRolesForHsOfficePerson_Trigger
|
|
||||||
after insert
|
|
||||||
on hs_office_person
|
|
||||||
for each row
|
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:--//
|
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$
|
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$
|
||||||
concat(target.tradeName, target.familyName, target.givenName)
|
concat(tradeName, familyName, givenName)
|
||||||
$idName$);
|
$idName$);
|
||||||
|
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
--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$
|
$updates$
|
||||||
personType = new.personType,
|
personType = new.personType,
|
||||||
tradeName = new.tradeName,
|
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
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
declare
|
declare
|
||||||
hsOfficeRelationshipTenant RbacRoleDescriptor;
|
newAnchorPerson hs_office_person;
|
||||||
newRelAnchor hs_office_person;
|
newHolderPerson hs_office_person;
|
||||||
newRelHolder hs_office_person;
|
|
||||||
oldContact hs_office_contact;
|
oldContact hs_office_contact;
|
||||||
newContact hs_office_contact;
|
newContact hs_office_contact;
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
hsOfficeRelationshipTenant := hsOfficeRelationshipTenant(NEW);
|
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_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_contact as c where c.uuid = NEW.contactUuid into newContact;
|
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
|
||||||
|
|
||||||
if TG_OP = 'INSERT' then
|
if TG_OP = 'INSERT' then
|
||||||
|
|
||||||
|
-- cannot be generated using `tools/generate` because there are multiple grants to the same entity type
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationshipOwner(NEW),
|
hsOfficeRelationshipOwner(NEW),
|
||||||
permissions => array['DELETE'],
|
permissions => array['DELETE'],
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
globalAdmin(),
|
globalAdmin()
|
||||||
hsOfficePersonAdmin(newRelAnchor)]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationshipAdmin(NEW),
|
hsOfficeRelationshipAdmin(NEW),
|
||||||
permissions => array['UPDATE'],
|
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(
|
perform createRoleWithGrants(
|
||||||
hsOfficeRelationshipTenant,
|
hsOfficeRelationshipAgent(NEW),
|
||||||
permissions => array['SELECT'],
|
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficeRelationshipAdmin(NEW),
|
hsOfficeRelationshipAdmin(NEW),
|
||||||
hsOfficePersonAdmin(newRelAnchor),
|
hsOfficePersonAdmin(newHolderPerson),
|
||||||
hsOfficePersonAdmin(newRelHolder),
|
hsOfficeContactAdmin(newContact)
|
||||||
hsOfficeContactAdmin(newContact)],
|
]
|
||||||
outgoingSubRoles => array[
|
);
|
||||||
hsOfficePersonTenant(newRelAnchor),
|
|
||||||
hsOfficePersonTenant(newRelHolder),
|
|
||||||
hsOfficeContactTenant(newContact)]
|
|
||||||
);
|
|
||||||
|
|
||||||
-- anchor and holder admin roles need each others tenant role
|
perform createRoleWithGrants(
|
||||||
-- to be able to see the joined relationship
|
hsOfficeRelationshipTenant(NEW),
|
||||||
-- TODO: this can probably be avoided through agent+guest roles
|
permissions => array['SELECT'],
|
||||||
call grantRoleToRole(hsOfficePersonTenant(newRelAnchor), hsOfficePersonAdmin(newRelHolder));
|
incomingSuperRoles => array[
|
||||||
call grantRoleToRole(hsOfficePersonTenant(newRelHolder), hsOfficePersonAdmin(newRelAnchor));
|
hsOfficeRelationshipAgent(NEW)
|
||||||
call grantRoleToRoleIfNotNull(hsOfficePersonTenant(newRelHolder), hsOfficeContactAdmin(newContact));
|
],
|
||||||
|
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
|
elsif TG_OP = 'UPDATE' then
|
||||||
|
|
||||||
if OLD.contactUuid <> NEW.contactUuid 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
|
-- 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;
|
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
|
||||||
|
|
||||||
call revokeRoleFromRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(oldContact) );
|
call revokeRoleFromRole( hsOfficeContactReferrer(oldContact), hsOfficeRelationshipTenant(NEW) );
|
||||||
call grantRoleToRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(newContact) );
|
call grantRoleToRole( hsOfficeContactReferrer(newContact), hsOfficeRelationshipTenant(NEW) );
|
||||||
|
|
||||||
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeRelationshipTenant );
|
call revokeRoleFromRole( hsOfficeRelationshipAgent(NEW), hsOfficeContactAdmin(oldContact) );
|
||||||
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeRelationshipTenant );
|
call grantRoleToRole( hsOfficeRelationshipAgent(NEW), hsOfficeContactAdmin(newContact) );
|
||||||
end if;
|
end if;
|
||||||
else
|
else
|
||||||
raise exception 'invalid usage of TRIGGER';
|
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:--//
|
--changeset hs-office-relationship-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('hs_office_relationship',
|
call generateRbacRestrictedView('hs_office_relationship',
|
||||||
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
|
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
|
||||||
$updates$
|
$updates$
|
||||||
contactUuid = new.contactUuid
|
contactUuid = new.contactUuid
|
||||||
$updates$);
|
$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
|
```mermaid
|
||||||
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
flowchart TB
|
flowchart TB
|
||||||
|
|
||||||
subgraph external[ ]
|
subgraph partnerRel.contact["`**partnerRel.contact**`"]
|
||||||
style external fill:#fff
|
direction TB
|
||||||
|
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
subgraph global
|
|
||||||
style global fill:#eee
|
|
||||||
|
|
||||||
role:global.admin[global.admin]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph partnerPerson
|
subgraph partnerRel.contact:roles[ ]
|
||||||
style partnerPerson fill:#eee
|
style partnerRel.contact:roles fill:#99bcdb,stroke:white
|
||||||
|
|
||||||
role:partnerPerson.admin[partnerPerson.admin]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph otherRelatedPerson
|
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
|
||||||
style otherRelatedPerson fill:#eee
|
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
|
||||||
|
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph internal[ ]
|
subgraph partner["`**partner**`"]
|
||||||
|
direction TB
|
||||||
|
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
subgraph hsOfficePartner
|
subgraph partner:permissions[ ]
|
||||||
style hsOfficePartner fill:#fff
|
style partner:permissions fill:#dd4901,stroke:white
|
||||||
|
|
||||||
perm:hsOfficePartner.*{{partner.*}}
|
perm:partner:new-partner{{partner:new-partner}}
|
||||||
role:hsOfficeRelationship.owner ==> perm:hsOfficePartner.*
|
perm:partner:DELETE{{partner:DELETE}}
|
||||||
|
perm:partner:UPDATE{{partner:UPDATE}}
|
||||||
perm:hsOfficePartner.edit{{partner.edit}}
|
perm:partner:SELECT{{partner:SELECT}}
|
||||||
role:hsOfficeRelationship.admin ==> perm:hsOfficePartner.edit
|
|
||||||
|
|
||||||
perm:hsOfficePartner.view{{partner.view}}
|
|
||||||
role:hsOfficeRelationship.tenant ==> perm:hsOfficePartner.view
|
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph hsOfficePartnerDetails
|
subgraph partnerRel["`**partnerRel**`"]
|
||||||
direction TB
|
direction TB
|
||||||
style hsOfficePartnerDetails fill:#eee
|
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
subgraph partnerRel.contact["`**partnerRel.contact**`"]
|
||||||
perm:hsOfficePartnerDetails.*{{partnerDetails.*}}
|
direction TB
|
||||||
role:hsOfficeRelationship.owner ==> perm:hsOfficePartnerDetails.*
|
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
perm:hsOfficePartnerDetails.edit{{partnerDetails.edit}}
|
subgraph partnerRel.contact:roles[ ]
|
||||||
role:hsOfficeRelationship.agent ==> perm:hsOfficePartnerDetails.edit
|
style partnerRel.contact:roles fill:#99bcdb,stroke:white
|
||||||
role:hsOfficeRelationship.agent ==> perm:hsOfficePartnerDetails.view
|
|
||||||
|
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
|
||||||
perm:hsOfficePartnerDetails.view{{partnerDetails.view}}
|
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
|
||||||
|
|
||||||
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
|
if TG_OP = 'INSERT' then
|
||||||
|
|
||||||
-- === ATTENTION: code generated from related Mermaid flowchart: ===
|
-- Permissions and Grants for Partner
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||||
@ -96,21 +45,21 @@ begin
|
|||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipTenant(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipTenant(newPartnerRel)),
|
||||||
createPermissions(partnerUuid, array ['view'])
|
createPermissions(partnerUuid, array ['SELECT'])
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Permissions and Grants for PartnerDetails
|
-- Permissions and Grants for PartnerDetails
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||||
createPermissions(partnerDetailsUuid, array ['*'])
|
createPermissions(partnerDetailsUuid, array ['DELETE'])
|
||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
|
||||||
createPermissions(partnerDetailsUuid, array ['edit'])
|
createPermissions(partnerDetailsUuid, array ['UPDATE'])
|
||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficeRelationshipTENANT.
|
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficeRelationshipTENANT.
|
||||||
@ -118,7 +67,7 @@ begin
|
|||||||
-- Otherwise package-admins etc. would be able to read the data.
|
-- Otherwise package-admins etc. would be able to read the data.
|
||||||
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
|
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
|
||||||
createPermissions(partnerDetailsUuid, array ['SELECT'])
|
createPermissions(partnerDetailsUuid, array ['SELECT'])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
elsif TG_OP = 'UPDATE' then
|
elsif TG_OP = 'UPDATE' then
|
||||||
@ -129,72 +78,72 @@ begin
|
|||||||
-- Revokes from Partner
|
-- Revokes from Partner
|
||||||
|
|
||||||
call revokePermissionFromRole(
|
call revokePermissionFromRole(
|
||||||
findPermissionId(partnerUuid, 'view'),
|
findPermissionId(partnerUuid, 'SELECT'),
|
||||||
hsOfficeRelationshipTenant(oldPartnerRel)
|
hsOfficeRelationshipTenant(oldPartnerRel)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- call revokePermissionFromRole(
|
-- call revokePermissionFromRole(
|
||||||
-- findPermissionId(partnerUuid, 'edit'),
|
-- findPermissionId(partnerUuid, 'edit'),
|
||||||
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call revokePermissionFromRole(
|
-- call revokePermissionFromRole(
|
||||||
-- findPermissionId(partnerUuid, '*'),
|
-- findPermissionId(partnerUuid, '*'),
|
||||||
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
||||||
-- );
|
-- );
|
||||||
|
|
||||||
-- Grants for Partner
|
-- Grants for Partner
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||||
array[findPermissionId(partnerUuid, '*')]
|
array[findPermissionId(partnerUuid, 'DELETE')]
|
||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
|
||||||
array[findPermissionId(partnerUuid, 'edit')]
|
array[findPermissionId(partnerUuid, 'UPDATE')]
|
||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipTenant(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipTenant(newPartnerRel)),
|
||||||
array[findPermissionId(partnerUuid, 'view')]
|
array[findPermissionId(partnerUuid, 'SELECT')]
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Revokes from PartnerDetails
|
-- Revokes from PartnerDetails
|
||||||
|
|
||||||
-- call revokePermissionFromRole(
|
-- call revokePermissionFromRole(
|
||||||
-- findPermissionId(partnerDetailsUuid, 'view'),
|
-- findPermissionId(partnerDetailsUuid, 'SELECT'),
|
||||||
-- hsOfficeRelationshipAgent(oldPartnerRel)
|
-- hsOfficeRelationshipAgent(oldPartnerRel)
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call revokePermissionFromRole(
|
-- call revokePermissionFromRole(
|
||||||
-- findPermissionId(partnerDetailsUuid, 'edit'),
|
-- findPermissionId(partnerDetailsUuid, 'UPDATE'),
|
||||||
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
-- hsOfficeRelationshipAdmin(oldPartnerRel)
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call revokePermissionFromRole(
|
-- call revokePermissionFromRole(
|
||||||
-- findPermissionId(partnerDetailsUuid, '*'),
|
-- findPermissionId(partnerDetailsUuid, 'DELETE'),
|
||||||
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
-- hsOfficeRelationshipOwner(oldPartnerRel)
|
||||||
-- );
|
-- );
|
||||||
|
|
||||||
-- Grants for PartnerDetails
|
-- Grants for PartnerDetails
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipOwner(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipOwner(newPartnerRel)),
|
||||||
array[findPermissionId(partnerDetailsUuid, '*')]
|
array[findPermissionId(partnerDetailsUuid, 'DELETE')]
|
||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipAdmin(newPartnerRel)),
|
||||||
array[findPermissionId(partnerDetailsUuid, 'edit')]
|
array[findPermissionId(partnerDetailsUuid, 'UPDATE')]
|
||||||
);
|
);
|
||||||
|
|
||||||
call grantPermissionsToRole(
|
call grantPermissionsToRole(
|
||||||
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
|
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
|
||||||
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
|
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
|
||||||
-- Otherwise package-admins etc. would be able to read the data.
|
-- Otherwise package-admins etc. would be able to read the data.
|
||||||
getRoleId(hsOfficeRelationshipAgent(newPartnerRel), 'fail'),
|
getRoleId(hsOfficeRelationshipAgent(newPartnerRel)),
|
||||||
array[findPermissionId(partnerDetailsUuid, 'view')]
|
array[findPermissionId(partnerDetailsUuid, 'SELECT')]
|
||||||
);
|
);
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
@ -203,7 +152,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(partnerUuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
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
|
```mermaid
|
||||||
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
flowchart TB
|
flowchart TB
|
||||||
|
|
||||||
%%% RbacEntity.builder().forEntity(HsOfficeBankAccountEntity.class)
|
subgraph bankAccount["`**bankAccount**`"]
|
||||||
%%% .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
|
|
||||||
|
|
||||||
direction TB
|
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:bankAccount:owner[[bankAccount:owner]]
|
||||||
role:hsOfficeBankAccount.owner[[bankAccount.owner]]
|
role:bankAccount:admin[[bankAccount:admin]]
|
||||||
%%% .withPermission(ALL)
|
role:bankAccount:referrer[[bankAccount:referrer]]
|
||||||
%% permissions
|
end
|
||||||
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
|
|
||||||
|
|
||||||
%%% .createSubRole(REFERRER)
|
subgraph bankAccount:permissions[ ]
|
||||||
role:hsOfficeBankAccount.referrer[[bankAccount.referrer]]
|
style bankAccount:permissions fill:#dd4901,stroke:white
|
||||||
%% permissions
|
|
||||||
%%% .withPermission(VIEW)
|
perm:bankAccount:INSERT{{bankAccount:INSERT}}
|
||||||
role:hsOfficeBankAccount.referrer --> perm:hsOfficeBankAccount.view{{hsOfficeBankAccount.view}}
|
perm:bankAccount:DELETE{{bankAccount:DELETE}}
|
||||||
%% incoming
|
perm:bankAccount:UPDATE{{bankAccount:UPDATE}}
|
||||||
role:hsOfficeBankAccount.admin ---> role:hsOfficeBankAccount.referrer
|
perm:bankAccount:SELECT{{bankAccount:SELECT}}
|
||||||
|
end
|
||||||
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
|
--liquibase formatted sql
|
||||||
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T19:09:38.359318650.
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
|
--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
|
returns trigger
|
||||||
language plpgsql
|
language plpgsql
|
||||||
strict as $$
|
strict as $$
|
||||||
begin
|
begin
|
||||||
if TG_OP <> 'INSERT' then
|
call buildRbacSystemForHsOfficeBankAccount(NEW);
|
||||||
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)]
|
|
||||||
);
|
|
||||||
|
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
create trigger insertTriggerForHsOfficeBankAccount_tg
|
||||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
after insert on hs_office_bankaccount
|
||||||
*/
|
|
||||||
|
|
||||||
create trigger createRbacRolesForHsOfficeBankAccount_Trigger
|
|
||||||
after insert
|
|
||||||
on hs_office_bankaccount
|
|
||||||
for each row
|
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:--//
|
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$
|
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$
|
||||||
target.iban || ':' || target.holder
|
concat(iban, ':', holder)
|
||||||
$idName$);
|
$idName$);
|
||||||
|
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
--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$
|
$updates$
|
||||||
holder = new.holder,
|
holder = new.holder,
|
||||||
iban = new.iban,
|
iban = new.iban,
|
||||||
bic = new.bic
|
bic = new.bic
|
||||||
$updates$);
|
$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
|
```mermaid
|
||||||
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
flowchart TB
|
flowchart TB
|
||||||
|
|
||||||
subgraph global
|
subgraph bankAccount["`**bankAccount**`"]
|
||||||
style global fill:#eee
|
|
||||||
|
|
||||||
role:global.admin[global.admin]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph hsOfficeBankAccount
|
|
||||||
direction TB
|
direction TB
|
||||||
style hsOfficeBankAccount fill:#eee
|
style bankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
role:hsOfficeBankAccount.owner[bankAccount.owner]
|
subgraph bankAccount:roles[ ]
|
||||||
--> role:hsOfficeBankAccount.admin[bankAccount.admin]
|
style bankAccount:roles fill:#99bcdb,stroke:white
|
||||||
--> role:hsOfficeBankAccount.referrer[bankAccount.referrer]
|
|
||||||
|
role:bankAccount:owner[[bankAccount:owner]]
|
||||||
|
role:bankAccount:admin[[bankAccount:admin]]
|
||||||
|
role:bankAccount:referrer[[bankAccount:referrer]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph hsOfficeRelationship:DEBITOR
|
subgraph debitorRel.contact["`**debitorRel.contact**`"]
|
||||||
direction TB
|
direction TB
|
||||||
style hsOfficeRelationship:DEBITOR fill:#eee
|
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
role:hsOfficeRelationship:DEBITOR.owner[debitorRel.owner]
|
subgraph debitorRel.contact:roles[ ]
|
||||||
--> role:hsOfficeRelationship:DEBITOR.admin[debitorRel.admin]
|
style debitorRel.contact:roles fill:#99bcdb,stroke:white
|
||||||
--> role:hsOfficeRelationship:DEBITOR.agent[debitorRel.agent]
|
|
||||||
--> role:hsOfficeRelationship:DEBITOR.tenant[debitorRel.tenant]
|
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
|
||||||
|
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
|
||||||
|
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph hsOfficeSepaMandate
|
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
|
||||||
|
direction TB
|
||||||
role:hsOfficeSepaMandate.owner[sepaMandate.owner]
|
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
%% 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: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
|
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
|
--liquibase formatted sql
|
||||||
|
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T18:29:47.095199204.
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-sepamandate-rbac-OBJECT:1 endDelimiter:--//
|
--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()
|
create or replace procedure buildRbacSystemForHsOfficeSepaMandate(
|
||||||
returns trigger
|
NEW hs_office_sepamandate
|
||||||
language plpgsql
|
)
|
||||||
strict as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
declare
|
||||||
newHsOfficeDebitor hs_office_debitor;
|
newBankAccount hs_office_bankaccount;
|
||||||
newhsOfficeRelationship:DEBITOR hs_office_relationship;
|
newDebitorRel hs_office_relationship;
|
||||||
newHsOfficeBankAccount hs_office_bankAccount;
|
|
||||||
begin
|
begin
|
||||||
call enterTriggerForObjectUuid(NEW.uuid);
|
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;
|
perform createRoleWithGrants(
|
||||||
select * from hs_office_relationship as r where r.uuid = newHsOfficeDebitor.debitorRelUuid into newhsOfficeRelationship:DEBITOR;
|
hsOfficeSepaMandateOwner(NEW),
|
||||||
select * from hs_office_bankAccount as c where c.uuid = NEW.bankAccountUuid into newHsOfficeBankAccount;
|
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(
|
perform createRoleWithGrants(
|
||||||
hsOfficeSepaMandateOwner(NEW),
|
hsOfficeSepaMandateReferrer(NEW),
|
||||||
permissions => array['DELETE'],
|
permissions => array['SELECT'],
|
||||||
incomingSuperRoles => array[globalAdmin()]
|
incomingSuperRoles => array[
|
||||||
);
|
hsOfficeRelationshipAgent(newDebitorRel),
|
||||||
|
hsOfficeBankAccountAdmin(newBankAccount),
|
||||||
perform createRoleWithGrants(
|
hsOfficeSepaMandateAgent(NEW)],
|
||||||
hsOfficeSepaMandateAdmin(NEW),
|
outgoingSubRoles => array[hsOfficeRelationshipTenant(newDebitorRel)]
|
||||||
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;
|
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
|
||||||
end; $$;
|
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
|
create or replace function insertTriggerForHsOfficeSepaMandate_tf()
|
||||||
on hs_office_sepamandate
|
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
|
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:--//
|
--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:--//
|
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
call generateRbacRestrictedView('hs_office_sepamandate',
|
call generateRbacRestrictedView('hs_office_sepamandate',
|
||||||
orderby => 'target.reference',
|
'validity',
|
||||||
columnUpdates => $updates$
|
$updates$
|
||||||
reference = new.reference,
|
reference = new.reference,
|
||||||
agreement = new.agreement,
|
agreement = new.agreement,
|
||||||
validity = new.validity
|
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
|
-- Permissions and Grants for Debitor
|
||||||
|
|
||||||
-- call grantPermissionsToRole(
|
-- call grantPermissionsToRole(
|
||||||
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel), 'fail'),
|
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel)),
|
||||||
-- createPermissions(partnerUuid, array ['DELETE'])
|
-- createPermissions(partnerUuid, array ['DELETE'])
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call grantPermissionsToRole(
|
-- call grantPermissionsToRole(
|
||||||
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel), 'fail'),
|
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel), 'fail'),
|
||||||
-- createPermissions(partnerUuid, array ['edit'])
|
-- createPermissions(partnerUuid, array ['UPDATE'])
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call grantPermissionsToRole(
|
-- call grantPermissionsToRole(
|
||||||
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel), 'fail'),
|
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel), 'fail'),
|
||||||
-- createPermissions(partnerUuid, array ['view'])
|
-- createPermissions(partnerUuid, array ['SELECT'])
|
||||||
-- );
|
-- );
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
-- Grants to and from related Partner Relationship
|
||||||
hsOfficeDebitorAdmin(NEW),
|
|
||||||
permissions => array['UPDATE'],
|
|
||||||
incomingSuperRoles => array[hsOfficeDebitorOwner(NEW)]
|
|
||||||
);
|
|
||||||
|
|
||||||
-- call grantRoleToRole(hsOfficeRelationshipAdmin(newDebitorRel), hsOfficeRelationshipAdmin(newPartnerRel), true);
|
-- call grantRoleToRole(hsOfficeRelationshipAdmin(newDebitorRel), hsOfficeRelationshipAdmin(newPartnerRel), true);
|
||||||
-- call grantRoleToRole(hsOfficeRelationshipAgent(newPartnerRel), hsOfficeRelationshipAdmin(newDebitorRel), true);
|
-- call grantRoleToRole(hsOfficeRelationshipAgent(newPartnerRel), hsOfficeRelationshipAdmin(newDebitorRel), true);
|
||||||
@ -78,12 +74,10 @@ begin
|
|||||||
|
|
||||||
-- Grants to and from refundBankAccount
|
-- Grants to and from refundBankAccount
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
-- if newBankAccount is not null then
|
||||||
hsOfficeDebitorGuest(NEW),
|
-- call grantRoleToRole(hsOfficeBankAccountReferrer(newBankAccount), hsOfficeRelationshipAgent(newDebitorRel), true);
|
||||||
permissions => array['SELECT'],
|
-- call grantRoleToRole(hsOfficeRelationshipAgent(newDebitorRel), hsOfficeBankAccountAdmin(newBankAccount), true);
|
||||||
incomingSuperRoles => array[
|
-- end if;
|
||||||
hsOfficeDebitorTenant(NEW)]
|
|
||||||
);
|
|
||||||
|
|
||||||
elsif TG_OP = 'UPDATE' then
|
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;
|
from hs_office_relationship as r where r.relType = 'ACCOUNTING' and r.relHolderUuid = NEW.debitorRelUuid;
|
||||||
|
|
||||||
-- call grantPermissionsToRole(
|
-- call grantPermissionsToRole(
|
||||||
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel), 'fail'),
|
-- getRoleId(hsOfficeRelationshipOwner(newDebitorRel)),
|
||||||
-- createPermissions(partnerUuid, array ['*'])
|
-- createPermissions(partnerUuid, array ['DELETE'])
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call grantPermissionsToRole(
|
-- call grantPermissionsToRole(
|
||||||
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel), 'fail'),
|
-- getRoleId(hsOfficeRelationshipAdmin(newDebitorRel)),
|
||||||
-- createPermissions(partnerUuid, array ['edit'])
|
-- createPermissions(partnerUuid, array ['UPDATE'])
|
||||||
-- );
|
-- );
|
||||||
--
|
--
|
||||||
-- call grantPermissionsToRole(
|
-- call grantPermissionsToRole(
|
||||||
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel), 'fail'),
|
-- getRoleId(hsOfficeRelationshipTenant(newDebitorRel)),
|
||||||
-- createPermissions(partnerUuid, array ['view'])
|
-- createPermissions(partnerUuid, array ['SELECT'])
|
||||||
-- );
|
-- );
|
||||||
|
|
||||||
end if;
|
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.relationship.HsOfficeRelationshipType;
|
||||||
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsMermaidService.Include;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService.Include;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
|
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
|
||||||
import net.hostsharing.test.Array;
|
import net.hostsharing.test.Array;
|
||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
@ -40,7 +40,7 @@ import static net.hostsharing.test.JpaAttempt.attempt;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@DataJpaTest
|
@DataJpaTest
|
||||||
@Import( { Context.class, JpaAttempt.class, RbacGrantsMermaidService.class })
|
@Import( { Context.class, JpaAttempt.class, RbacGrantsDiagramService.class })
|
||||||
class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -71,7 +71,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
JpaAttempt jpaAttempt;
|
JpaAttempt jpaAttempt;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
RbacGrantsMermaidService mermaidService;
|
RbacGrantsDiagramService mermaidService;
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
HttpServletRequest request;
|
HttpServletRequest request;
|
||||||
@ -315,7 +315,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fif");
|
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)),
|
mermaidService.allGrantsFrom(givenDebitor.getUuid(), "view", EnumSet.of(Include.USERS, Include.DETAILS)),
|
||||||
"doc/all-grants-before-globalAdmin_canUpdateArbitraryDebitor.md");
|
"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 givenPartnerPerson = personRepo.findPersonByOptionalNameLike(person).get(0);
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike(contact).get(0);
|
||||||
|
|
||||||
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
final var partnerRole = HsOfficeRelationshipEntity.builder()
|
||||||
.relHolder(givenPartnerPerson)
|
.relHolder(givenPartnerPerson)
|
||||||
.relType(HsOfficeRelationshipType.PARTNER)
|
.relType(HsOfficeRelationshipType.PARTNER)
|
||||||
.relAnchor(givenMandantorPerson)
|
.relAnchor(givenMandantorPerson)
|
||||||
.contact(givenContact)
|
.contact(givenContact)
|
||||||
.build();
|
.build();
|
||||||
relationshipRepo.save(partnerRole);
|
relationshipRepo.save(partnerRole);
|
||||||
|
return 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void exactlyThesePartnersAreReturned(final List<HsOfficePartnerEntity> actualResult, final String... partnerNames) {
|
void exactlyThesePartnersAreReturned(final List<HsOfficePartnerEntity> actualResult, final String... partnerNames) {
|
||||||
|
@ -59,7 +59,6 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
final var count = personRepo.count();
|
final var count = personRepo.count();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
||||||
final var result = attempt(em, () -> toCleanup(personRepo.save(
|
final var result = attempt(em, () -> toCleanup(personRepo.save(
|
||||||
hsOfficePerson("a new person"))));
|
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
|
platform: postgres
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
url-tc: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
|
||||||
url-local: jdbc:postgresql://localhost:5432/postgres
|
url: jdbc:postgresql://localhost:5432/postgres
|
||||||
username: postgres
|
username: postgres
|
||||||
password: password
|
password: password
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user