uniform idnames (#28)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: #28 Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
parent
f8fb273918
commit
7f418c12a1
@ -82,7 +82,7 @@ If you have at least Docker and the Java JDK installed in appropriate versions a
|
||||
|
||||
# the following command should return a JSON array with just all packages visible for the admin of the customer yyy:
|
||||
curl \
|
||||
-H 'current-user: superuser-alex@hostsharing.net' -H 'assumed-roles: test_customer#yyy.admin' \
|
||||
-H 'current-user: superuser-alex@hostsharing.net' -H 'assumed-roles: test_customer#yyy:ADMIN' \
|
||||
http://localhost:8080/api/test/packages
|
||||
|
||||
# add a new customer
|
||||
|
@ -27,8 +27,8 @@ Objektorientiert gedacht, enthalten solche Objekte die Zusatzdaten einer Subklas
|
||||
- Für die Rollenzuordnung zwischen referenzierten Objekten gilt:
|
||||
- Für Objekte vom Typ Root werden die Rollen des zugehörigen Aggregator-Objektes verwendet.
|
||||
- Gibt es Referenzen auf hierarchisch verbundene Objekte (z.B. Debitor.refundBankAccount) gilt folgende Faustregel:
|
||||
***Nach oben absteigen, nach unten halten oder aufsteigen.*** An einem fachlich übergeordneten Objekt wird also eine niedrigere Rolle (z.B. Debitor-admin -> Partner.agent), einem fachlich untergeordneten Objekt eine gleichwertige Rolle (z.B. Partner.admin -> Debitor.admin) zugewiesen oder sogar aufgestiegen (Debitor.admin -> Package.tenant).
|
||||
- Für Referenzen zwischen Objekten, die nicht hierarchisch zueinander stehen (z.B. Debitor und Bankverbindung), wird auf beiden seiten abgestiegen (also Debitor.admin -> BankAccount.referrer und BankAccount.admin -> Debitor.tenant).
|
||||
***Nach oben absteigen, nach unten halten oder aufsteigen.*** An einem fachlich übergeordneten Objekt wird also eine niedrigere Rolle (z.B. Debitor.ADMIN -> Partner.AGENT), einem fachlich untergeordneten Objekt eine gleichwertige Rolle (z.B. Partner.ADMIN -> Debitor.ADMIN) zugewiesen oder sogar aufgestiegen (Debitor.ADMIN -> Package.TENANT).
|
||||
- Für Referenzen zwischen Objekten, die nicht hierarchisch zueinander stehen (z.B. Debitor und Bankverbindung), wird auf beiden seiten abgestiegen (also Debitor.ADMIN -> BankAccount.REFERRER und BankAccount.ADMIN -> Debitor.TENANT).
|
||||
|
||||
Anmerkung: Der Typ-Begriff *Root* bezieht sich auf die Rolle im fachlichen Datenmodell. Im Bezug auf den Teilgraphen eines fachlichen Kontexts ist dies auch eine Wurzel im Sinne der Graphentheorie. Aber in anderen fachlichen Kontexten können auch diese Objekte von anderen Teilgraphen referenziert werden und werden dann zum inneren Knoten.
|
||||
|
||||
|
@ -16,11 +16,11 @@ Beim Debitor ist das nämlich selbst mit Generator die Hölle, zumal eben auch Q
|
||||
|
||||
Mit anderen Worten, um als Repräsentant eines Geschäftspartners auf den Bank-Account der Sepa-Mandate sehen zu dürfen, wird derzeut folgende Grant-Kette durchlaufen (bzw. eben noch nicht, weil es noch nicht funktioniert):
|
||||
|
||||
User -> Partner-Holder-Person:Admin -> Partner-Relation:Agent -> Debitor-Relation:Agent -> Sepa-Mandat:Admin -> BankAccount:Admin -> BankAccount:SELECT
|
||||
User -> Partner-Holder-Person:ADMIN -> Partner-Relation:AGENT -> Debitor-Relation:AGENT -> Sepa-Mandat:ADMIN -> BankAccount:ADMIN -> BankAccount:SELECT
|
||||
|
||||
Daraus würde:
|
||||
|
||||
User -> Partner-Relation:Agent -> Debitor-Relation:Agent -> Sepa-Mandat:Admin -> Sepa-Mandat:SELECT*
|
||||
User -> Partner-Relation:AGENT -> Debitor-Relation:AGENT -> Sepa-Mandat:ADMIN -> Sepa-Mandat:SELECT*
|
||||
|
||||
(*mit JOIN auf RawBankAccount, also implizitem Leserecht)
|
||||
|
||||
|
48
doc/rbac.md
48
doc/rbac.md
@ -196,24 +196,24 @@ E.g. if a new package is added, the admin-role of the related customer has to be
|
||||
There can be global roles like 'administrators'.
|
||||
Most roles, though, are specific for certain business-objects and automatically generated as such:
|
||||
|
||||
business-object-table#business-object-name.relative-role
|
||||
business-object-table#business-object-name.role-stereotype
|
||||
|
||||
|
||||
Where *business-object-table* is the name of the SQL table of the business object (e.g *customer* or 'package'),
|
||||
*business-object-name* is generated from an immutable business key(e.g. a prefix like 'xyz' or 'xyz00')
|
||||
and the *relative-role*' describes the role relative to the referenced business-object as follows:
|
||||
and the *role-stereotype* describes a role relative to a referenced business-object as follows:
|
||||
|
||||
#### owner
|
||||
|
||||
The owner-role is granted to the subject which created the business object.
|
||||
E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...admin'.
|
||||
E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...:ADMIN'.
|
||||
|
||||
Whoever has the owner-role assigned can do everything with the related business-object, including deleting (or deactivating) it.
|
||||
|
||||
In most cases, the permissions to other operations than 'DELETE' are granted through the 'admin' role.
|
||||
By this, all roles ob sub-objects, which are assigned to the 'admin' role, are also granted to the 'owner'.
|
||||
|
||||
#### admin
|
||||
#### ADMIN
|
||||
|
||||
The admin-role is granted to a role of those subjects who manage the business object.
|
||||
E.g. a 'package' is manged by the admin of the customer.
|
||||
@ -222,7 +222,7 @@ Whoever has the admin-role assigned, can usually update the related business-obj
|
||||
|
||||
The admin-role also comprises lesser roles, through which the SELECT-permission is granted.
|
||||
|
||||
#### agent
|
||||
#### AGENT
|
||||
|
||||
The agent-role is not used in the examples of this document, because it's for more complex cases.
|
||||
It's usually granted to those roles and users who represent the related business-object, but are not allowed to update it.
|
||||
@ -231,21 +231,25 @@ Other than the tenant-role, it usually offers broader visibility of sub-business
|
||||
E.g. a package-admin is allowed to see the related debitor-business-object,
|
||||
but not its banking data.
|
||||
|
||||
#### tenant
|
||||
#### TENANT
|
||||
|
||||
The tenant-role is granted to everybody who needs to be able to select the business-object and (probably some) related business-objects.
|
||||
Usually all owners, admins and tenants of sub-objects get this role granted.
|
||||
|
||||
Some business-objects only have very limited data directly in the main business-object and store more sensitive data in special sub-objects (e.g. 'customer-details') to which tenants of sub-objects of the main-object (e.g. package admins) do not get SELECT permission.
|
||||
|
||||
#### guest
|
||||
#### GUEST
|
||||
|
||||
(Deprecated)
|
||||
|
||||
#### REFERRER
|
||||
|
||||
Like the agent-role, the guest-role too is not used in the examples of this document, because it's for more complex cases.
|
||||
|
||||
If the guest-role exists, the SELECT-permission is granted to it, instead of to the tenant-role.
|
||||
Other than the tenant-role, the guest-roles does never grant any roles of related objects.
|
||||
If the referrer-role exists, the SELECT-permission is granted to it, instead of to the tenant-role.
|
||||
Other than the tenant-role, the referrer-roles does never grant any roles of related objects.
|
||||
|
||||
Also, if the guest-role exists, the tenant-role receives the SELECT-permission through the guest-role.
|
||||
Also, if the referrer-role exists, the tenant-role receives the SELECT-permission through the referrer-role.
|
||||
|
||||
|
||||
### Referenced Business Objects and Role-Depreciation
|
||||
@ -372,7 +376,7 @@ That user is also used for historicization and audit log, but which is a differe
|
||||
If the session variable `hsadminng.assumedRoles` is set to a non-empty value, its content is interpreted as a list of semicolon-separated role names.
|
||||
Example:
|
||||
|
||||
SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
|
||||
SET LOCAL hsadminng.assumedRoles = 'customer#aab:admin;customer#aac:admin';
|
||||
|
||||
In this case, not the current user but the assumed roles are used as a starting point for any further queries.
|
||||
Roles which are not granted to the current user, directly or indirectly, cannot be assumed.
|
||||
@ -385,7 +389,7 @@ A full example is shown here:
|
||||
BEGIN TRANSACTION;
|
||||
SET SESSION SESSION AUTHORIZATION restricted;
|
||||
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
|
||||
SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin';
|
||||
SET LOCAL hsadminng.assumedRoles = 'customer#aab:admin;customer#aac:admin';
|
||||
|
||||
SELECT c.prefix, p.name as "package", ema.localPart || '@' || dom.name as "email-address"
|
||||
FROM emailaddress_rv ema
|
||||
@ -466,14 +470,14 @@ together {
|
||||
permCustomerXyzSELECT--> boCustXyz
|
||||
}
|
||||
|
||||
entity "Role customer#xyz.tenant" as roleCustXyzTenant
|
||||
entity "Role customer#xyz:TENANT" as roleCustXyzTenant
|
||||
roleCustXyzTenant --> permCustomerXyzSELECT
|
||||
|
||||
entity "Role customer#xyz.admin" as roleCustXyzAdmin
|
||||
entity "Role customer#xyz:ADMIN" as roleCustXyzAdmin
|
||||
roleCustXyzAdmin --> roleCustXyzTenant
|
||||
roleCustXyzAdmin --> permCustomerXyzINSERT:package
|
||||
|
||||
entity "Role customer#xyz.owner" as roleCustXyzOwner
|
||||
entity "Role customer#xyz:OWNER" as roleCustXyzOwner
|
||||
roleCustXyzOwner ..> roleCustXyzAdmin
|
||||
roleCustXyzOwner --> permCustomerXyzDELETE
|
||||
|
||||
@ -489,7 +493,7 @@ actorHostmaster --> roleAdmins
|
||||
```
|
||||
|
||||
As you can see, there something special:
|
||||
From the 'Role customer#xyz.owner' to the 'Role customer#xyz.admin' there is a dashed line, whereas all other lines are solid lines.
|
||||
From the 'Role customer#xyz:OWNER' to the 'Role customer#xyz:admin' there is a dashed line, whereas all other lines are solid lines.
|
||||
Solid lines means, that one role is granted to another and automatically assumed in all queries to the restricted views.
|
||||
The dashed line means that one role is granted to another but not automatically assumed in queries to the restricted views.
|
||||
|
||||
@ -537,15 +541,15 @@ together {
|
||||
}
|
||||
|
||||
package {
|
||||
entity "Role customer#xyz.tenant" as roleCustXyzTenant
|
||||
entity "Role customer#xyz.admin" as roleCustXyzAdmin
|
||||
entity "Role customer#xyz.owner" as roleCustXyzOwner
|
||||
entity "Role customer#xyz:TENANT" as roleCustXyzTenant
|
||||
entity "Role customer#xyz:ADMIN" as roleCustXyzAdmin
|
||||
entity "Role customer#xyz:OWNER" as roleCustXyzOwner
|
||||
}
|
||||
|
||||
package {
|
||||
entity "Role package#xyz00.owner" as rolePacXyz00Owner
|
||||
entity "Role package#xyz00.admin" as rolePacXyz00Admin
|
||||
entity "Role package#xyz00.tenant" as rolePacXyz00Tenant
|
||||
entity "Role package#xyz00:OWNER" as rolePacXyz00Owner
|
||||
entity "Role package#xyz00:ADMIN" as rolePacXyz00Admin
|
||||
entity "Role package#xyz00:TENANT" as rolePacXyz00Tenant
|
||||
}
|
||||
|
||||
rolePacXyz00Tenant --> permPacXyz00SELECT
|
||||
|
@ -3,10 +3,10 @@
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
||||
select isGranted(findRoleId('administrators'), findRoleId('test_package#aaa00.owner'));
|
||||
select isGranted(findRoleId('test_package#aaa00.owner'), findRoleId('administrators'));
|
||||
-- call grantRoleToRole(findRoleId('test_package#aaa00.owner'), findRoleId('administrators'));
|
||||
-- call grantRoleToRole(findRoleId('administrators'), findRoleId('test_package#aaa00.owner'));
|
||||
select isGranted(findRoleId('administrators'), findRoleId('test_package#aaa00:OWNER'));
|
||||
select isGranted(findRoleId('test_package#aaa00:OWNER'), findRoleId('administrators'));
|
||||
-- call grantRoleToRole(findRoleId('test_package#aaa00:OWNER'), findRoleId('administrators'));
|
||||
-- call grantRoleToRole(findRoleId('administrators'), findRoleId('test_package#aaa00:OWNER'));
|
||||
|
||||
select count(*)
|
||||
FROM queryAllPermissionsOfSubjectIdForObjectUuids(findRbacUser('superuser-fran@hostsharing.net'),
|
||||
|
@ -83,7 +83,7 @@ select rr.uuid, rr.type from RbacGrants g
|
||||
select uuid from queryAllPermissionsOfSubjectId(findRbacUser('alex@example.com'))
|
||||
where objectTable='test_customer');
|
||||
|
||||
call grantRoleToUser(findRoleId('test_customer#aaa.admin'), findRbacUser('aaaaouq@example.com'));
|
||||
call grantRoleToUser(findRoleId('test_customer#aaa:ADMIN'), findRbacUser('aaaaouq@example.com'));
|
||||
|
||||
select queryAllPermissionsOfSubjectId(findRbacUser('aaaaouq@example.com'));
|
||||
|
||||
|
@ -24,7 +24,10 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
||||
|
@ -68,7 +68,7 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
|
||||
public static RbacView rbac() {
|
||||
return rbacViewFor("partnerDetails", HsOfficePartnerDetailsEntity.class)
|
||||
.withIdentityView(SQL.query("""
|
||||
SELECT partnerDetails.uuid as uuid, partner_iv.idName || '-details' as idName
|
||||
SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName
|
||||
FROM hs_office_partner_details AS partnerDetails
|
||||
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
|
||||
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
|
||||
|
@ -120,7 +120,7 @@ public class InsertTriggerGenerator {
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global.admin");
|
||||
System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global:ADMIN");
|
||||
generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql);
|
||||
});
|
||||
}
|
||||
@ -246,7 +246,7 @@ public class InsertTriggerGenerator {
|
||||
}
|
||||
|
||||
private static String toVar(final RbacView.RbacRoleDefinition roleDef) {
|
||||
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName());
|
||||
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().name());
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ public class RbacView {
|
||||
* <p>An identity view is a view which maps an objectUuid to an idName.
|
||||
* The idName should be a human-readable representation of the row, but as short as possible.
|
||||
* The idName must only consist of letters (A-Z, a-z), digits (0-9), dash (-), dot (.) and unserscore '_'.
|
||||
* It's used to create the object-specific-role-names like test_customer#abc.admin - here 'abc' is the idName.
|
||||
* It's used to create the object-specific-role-names like test_customer#abc:ADMIN - here 'abc' is the idName.
|
||||
* The idName not necessarily unique in a table, but it should be avoided.
|
||||
* </p>
|
||||
*
|
||||
@ -882,15 +882,12 @@ public class RbacView {
|
||||
TENANT,
|
||||
REFERRER,
|
||||
|
||||
@Deprecated
|
||||
GUEST;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ":" + roleName();
|
||||
}
|
||||
|
||||
String roleName() {
|
||||
return name().toLowerCase();
|
||||
return ":" + name();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class RbacViewMermaidFlowchartGenerator {
|
||||
|
||||
flowchart.indented( () -> {
|
||||
rbacDef.getEntityAliases().values().stream()
|
||||
.filter(e -> e.aliasName().startsWith(entity.aliasName() + "."))
|
||||
.filter(e -> e.aliasName().startsWith(entity.aliasName() + ":"))
|
||||
.forEach(this::renderEntitySubgraph);
|
||||
|
||||
wrapOutputInSubgraph(entity.aliasName() + ":roles", color,
|
||||
|
@ -333,7 +333,7 @@ class RolesGrantsAndPermissionsGenerator {
|
||||
return "globalAdmin()";
|
||||
}
|
||||
final String entityRefVar = entityRefVar(rootRefVar, roleDef.getEntityAlias());
|
||||
return roleDef.getEntityAlias().simpleName() + capitalize(roleDef.getRole().roleName())
|
||||
return roleDef.getEntityAlias().simpleName() + capitalize(roleDef.getRole().name())
|
||||
+ "(" + entityRefVar + ")";
|
||||
}
|
||||
|
||||
@ -359,7 +359,7 @@ class RolesGrantsAndPermissionsGenerator {
|
||||
plPgSql.indented(() -> {
|
||||
plPgSql.writeLn("${simpleVarName)${roleSuffix}(NEW),"
|
||||
.replace("${simpleVarName)", simpleEntityVarName)
|
||||
.replace("${roleSuffix}", capitalize(role.roleName())));
|
||||
.replace("${roleSuffix}", capitalize(role.name())));
|
||||
|
||||
generatePermissionsForRole(plPgSql, role);
|
||||
|
||||
@ -562,7 +562,7 @@ class RolesGrantsAndPermissionsGenerator {
|
||||
}
|
||||
|
||||
private static String toRoleRef(final RbacView.RbacRoleDefinition roleDef) {
|
||||
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName());
|
||||
return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().name());
|
||||
}
|
||||
|
||||
private static String toTriggerReference(
|
||||
|
@ -59,9 +59,9 @@ public class RbacGrantEntity {
|
||||
}
|
||||
|
||||
public String toDisplay() {
|
||||
return "{ grant role " + grantedRoleIdName +
|
||||
" to user " + granteeUserName +
|
||||
" by role " + grantedByRoleIdName +
|
||||
return "{ grant role:" + grantedRoleIdName +
|
||||
" to user:" + granteeUserName +
|
||||
" by role:" + grantedByRoleIdName +
|
||||
(assumed ? " and assume" : "") +
|
||||
" }";
|
||||
}
|
||||
|
@ -71,14 +71,14 @@ public class RbacGrantsDiagramService {
|
||||
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 ")) {
|
||||
if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm:")) {
|
||||
return;
|
||||
}
|
||||
if ( !g.getDescendantIdName().startsWith("role global")) {
|
||||
if (!includes.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(" test_")) {
|
||||
if ( !g.getDescendantIdName().startsWith("role:global")) {
|
||||
if (!includes.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(":test_")) {
|
||||
return;
|
||||
}
|
||||
if (!includes.contains(NON_TEST_ENTITIES) && !g.getDescendantIdName().contains(" test_")) {
|
||||
if (!includes.contains(NON_TEST_ENTITIES) && !g.getDescendantIdName().contains(":test_")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,7 @@ public class RbacGrantsDiagramService {
|
||||
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 ")) {
|
||||
if (!option.contains(USERS) && g.getAscendantIdName().startsWith("user:")) {
|
||||
return;
|
||||
}
|
||||
graph.add(g);
|
||||
@ -171,7 +171,7 @@ public class RbacGrantsDiagramService {
|
||||
}
|
||||
if (refType.equals("role")) {
|
||||
final var withoutRolePrefix = node.idName().substring("role:".length());
|
||||
return withoutRolePrefix.substring(0, withoutRolePrefix.lastIndexOf('.'));
|
||||
return withoutRolePrefix.substring(0, withoutRolePrefix.lastIndexOf(':'));
|
||||
}
|
||||
throw new IllegalArgumentException("unknown refType '" + refType + "' in '" + node.idName() + "'");
|
||||
}
|
||||
@ -188,23 +188,23 @@ public class RbacGrantsDiagramService {
|
||||
return "(" + displayName + "\nref:" + uuid + ")";
|
||||
}
|
||||
if (refType.equals("role")) {
|
||||
final var roleType = idName.substring(idName.lastIndexOf('.') + 1);
|
||||
final var roleType = idName.substring(idName.lastIndexOf(':') + 1);
|
||||
return "[" + roleType + "\nref:" + uuid + "]";
|
||||
}
|
||||
if (refType.equals("perm")) {
|
||||
final var roleType = idName.split(" ")[1];
|
||||
final var roleType = idName.split(":")[1];
|
||||
return "{{" + roleType + "\nref:" + uuid + "}}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String refType(final String idName) {
|
||||
return idName.split(" ", 2)[0];
|
||||
return idName.split(":", 2)[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String cleanId(final String idName) {
|
||||
return idName.replace(" ", ":").replaceAll("@.*", "")
|
||||
return idName.replaceAll("@.*", "")
|
||||
.replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", "");
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,6 @@ public class RbacRoleEntity {
|
||||
@Enumerated(EnumType.STRING)
|
||||
private RbacRoleType roleType;
|
||||
|
||||
@Formula("objectTable||'#'||objectIdName||'.'||roleType")
|
||||
@Formula("objectTable||'#'||objectIdName||':'||roleType")
|
||||
private String roleName;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
|
||||
public enum RbacRoleType {
|
||||
owner, admin, agent, tenant, guest, referrer
|
||||
OWNER, ADMIN, AGENT, TENANT, GUEST, REFERRER
|
||||
}
|
||||
|
@ -19,9 +19,11 @@ components:
|
||||
roleType:
|
||||
type: string
|
||||
enum:
|
||||
- owner
|
||||
- admin
|
||||
- tenant
|
||||
- referrer
|
||||
- OWNER
|
||||
- ADMIN
|
||||
- AGENT
|
||||
- TENANT
|
||||
- GUEST
|
||||
- REFERRER
|
||||
roleName:
|
||||
type: string
|
||||
|
@ -149,8 +149,7 @@ create or replace function cleanIdentifier(rawIdentifier varchar)
|
||||
declare
|
||||
cleanIdentifier varchar;
|
||||
begin
|
||||
-- TODO: remove the ':' from the list of allowed characters as soon as it's not used anymore
|
||||
cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._:]+', '', 'g');
|
||||
cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._]+', '', 'g');
|
||||
return cleanIdentifier;
|
||||
end; $$;
|
||||
|
||||
|
@ -164,7 +164,7 @@ end; $$;
|
||||
|
||||
*/
|
||||
|
||||
create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest', 'referrer');
|
||||
create type RbacRoleType as enum ('OWNER', 'ADMIN', 'AGENT', 'TENANT', 'GUEST', 'REFERRER');
|
||||
|
||||
create table RbacRole
|
||||
(
|
||||
@ -249,7 +249,7 @@ declare
|
||||
roleUuid uuid;
|
||||
begin
|
||||
-- TODO.refact: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences
|
||||
roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), '.'));
|
||||
roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), ':'));
|
||||
objectTableFromRoleIdName = split_part(roleParts, '#', 1);
|
||||
objectNameFromRoleIdName = split_part(roleParts, '#', 2);
|
||||
roleTypeFromRoleIdName = split_part(roleParts, '#', 3);
|
||||
|
@ -50,7 +50,7 @@ begin
|
||||
|
||||
foreach roleName in array string_to_array(assumedRoles, ';')
|
||||
loop
|
||||
roleNameParts = overlay(roleName placing '#' from length(roleName) + 1 - strpos(reverse(roleName), '.'));
|
||||
roleNameParts = overlay(roleName placing '#' from length(roleName) + 1 - strpos(reverse(roleName), ':'));
|
||||
objectTableToAssume = split_part(roleNameParts, '#', 1);
|
||||
objectNameToAssume = split_part(roleNameParts, '#', 2);
|
||||
roleTypeToAssume = split_part(roleNameParts, '#', 3);
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
drop view if exists rbacrole_ev;
|
||||
create or replace view rbacrole_ev as
|
||||
select (objectTable || '#' || objectIdName || '.' || roleType) as roleIdName, *
|
||||
select (objectTable || '#' || objectIdName || ':' || roleType) as roleIdName, *
|
||||
-- @formatter:off
|
||||
from (
|
||||
select r.*,
|
||||
@ -40,7 +40,7 @@ select *
|
||||
where isGranted(currentSubjectsUuids(), r.uuid)
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by objectTable || '#' || objectIdName || '.' || roleType;
|
||||
order by objectTable || '#' || objectIdName || ':' || roleType;
|
||||
grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
@ -57,7 +57,7 @@ create or replace view rbacgrants_ev as
|
||||
-- @formatter:off
|
||||
select x.grantUuid as uuid,
|
||||
x.grantedByTriggerOf as grantedByTriggerOf,
|
||||
go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName,
|
||||
go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || ':' || r.roletype as grantedByRoleIdName,
|
||||
x.ascendingIdName as ascendantIdName,
|
||||
x.descendingIdName as descendantIdName,
|
||||
x.grantedByRoleUuid,
|
||||
@ -71,16 +71,16 @@ create or replace view rbacgrants_ev as
|
||||
g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||
|
||||
coalesce(
|
||||
'user ' || au.name,
|
||||
'role ' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || '.' || ar.roletype
|
||||
'user:' || au.name,
|
||||
'role:' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || ':' || ar.roletype
|
||||
) as ascendingIdName,
|
||||
aro.objectTable, aro.uuid,
|
||||
( case
|
||||
when dro is not null
|
||||
then ('role ' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || '.' || dr.roletype)
|
||||
then ('role:' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || ':' || dr.roletype)
|
||||
when dp.op = 'INSERT'
|
||||
then 'perm ' || dp.op || ' into ' || dp.opTableName || ' with ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
|
||||
else 'perm ' || dp.op || ' on ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
|
||||
then 'perm:' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) || ':' || dp.op || '>' || dp.opTableName
|
||||
else 'perm:' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) || ':' || dp.op
|
||||
end
|
||||
) as descendingIdName,
|
||||
dro.objectTable, dro.uuid,
|
||||
@ -115,8 +115,8 @@ create or replace view rbacgrants_ev as
|
||||
drop view if exists rbacgrants_rv;
|
||||
create or replace view rbacgrants_rv as
|
||||
-- @formatter:off
|
||||
select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) || '.' || r.roletype as grantedByRoleIdName,
|
||||
g.objectTable || '#' || g.objectIdName || '.' || g.roletype as grantedRoleIdName, g.userName, g.assumed,
|
||||
select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) || ':' || r.roletype as grantedByRoleIdName,
|
||||
g.objectTable || '#' || g.objectIdName || ':' || g.roletype as grantedRoleIdName, g.userName, g.assumed,
|
||||
g.grantedByRoleUuid, g.descendantUuid as grantedRoleUuid, g.ascendantUuid as userUuid,
|
||||
g.objectTable, g.objectUuid, g.objectIdName, g.roleType as grantedRoleType
|
||||
from (
|
||||
@ -327,7 +327,7 @@ execute function deleteRbacUser();
|
||||
drop view if exists RbacOwnGrantedPermissions_rv;
|
||||
create or replace view RbacOwnGrantedPermissions_rv as
|
||||
select r.uuid as roleuuid, p.uuid as permissionUuid,
|
||||
(r.objecttable || '#' || r.objectidname || '.' || r.roletype) as roleName, p.op,
|
||||
(r.objecttable || ':' || r.objectidname || ':' || r.roletype) as roleName, p.op,
|
||||
o.objecttable, r.objectidname, o.uuid as objectuuid
|
||||
from rbacrole_rv r
|
||||
join rbacgrants g on g.ascendantuuid = r.uuid
|
||||
@ -359,7 +359,7 @@ begin
|
||||
|
||||
return query select
|
||||
xp.roleUuid,
|
||||
(xp.roleObjectTable || '#' || xp.roleObjectIdName || '.' || xp.roleType) as roleName,
|
||||
(xp.roleObjectTable || '#' || xp.roleObjectIdName || ':' || xp.roleType) as roleName,
|
||||
xp.permissionUuid, xp.op, xp.opTableName,
|
||||
xp.permissionObjectTable, xp.permissionObjectIdName, xp.permissionObjectUuid
|
||||
from (select
|
||||
|
@ -46,7 +46,7 @@ begin
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'owner', assumed);
|
||||
return roleDescriptor('%2$s', entity.uuid, 'OWNER', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sAdmin(entity %2$s, assumed boolean = true)
|
||||
@ -54,7 +54,7 @@ begin
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'admin', assumed);
|
||||
return roleDescriptor('%2$s', entity.uuid, 'ADMIN', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sAgent(entity %2$s, assumed boolean = true)
|
||||
@ -62,7 +62,7 @@ begin
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'agent', assumed);
|
||||
return roleDescriptor('%2$s', entity.uuid, 'AGENT', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sTenant(entity %2$s, assumed boolean = true)
|
||||
@ -70,7 +70,7 @@ begin
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'tenant', assumed);
|
||||
return roleDescriptor('%2$s', entity.uuid, 'TENANT', assumed);
|
||||
end; $f$;
|
||||
|
||||
-- TODO: remove guest role
|
||||
@ -79,7 +79,7 @@ begin
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'guest', assumed);
|
||||
return roleDescriptor('%2$s', entity.uuid, 'GUEST', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sReferrer(entity %2$s)
|
||||
@ -87,7 +87,7 @@ begin
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'referrer');
|
||||
return roleDescriptor('%2$s', entity.uuid, 'REFERRER');
|
||||
end; $f$;
|
||||
|
||||
$sql$, prefix, targetTable);
|
||||
|
@ -114,11 +114,11 @@ create or replace function globalAdmin(assumed boolean = true)
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType, assumed;
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'ADMIN'::RbacRoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating global admin role', null, null, null);
|
||||
call defineContext('creating role:global#global:ADMIN', null, null, null);
|
||||
select createRole(globalAdmin());
|
||||
commit;
|
||||
--//
|
||||
@ -135,11 +135,11 @@ create or replace function globalGuest(assumed boolean = true)
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'guest'::RbacRoleType, assumed;
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'GUEST'::RbacRoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating global guest role', null, null, null);
|
||||
call defineContext('creating role:global#globa:guest', null, null, null);
|
||||
select createRole(globalGuest());
|
||||
commit;
|
||||
--//
|
||||
|
@ -13,9 +13,9 @@ subgraph customer["`**customer**`"]
|
||||
subgraph customer:roles[ ]
|
||||
style customer:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:customer:owner[[customer:owner]]
|
||||
role:customer:admin[[customer:admin]]
|
||||
role:customer:tenant[[customer:tenant]]
|
||||
role:customer:OWNER[[customer:OWNER]]
|
||||
role:customer:ADMIN[[customer:ADMIN]]
|
||||
role:customer:TENANT[[customer:TENANT]]
|
||||
end
|
||||
|
||||
subgraph customer:permissions[ ]
|
||||
@ -29,17 +29,17 @@ subgraph customer["`**customer**`"]
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==>|XX| role:customer:owner
|
||||
user:creator ==>|XX| role:customer:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:admin ==>|XX| role:customer:owner
|
||||
role:customer:owner ==> role:customer:admin
|
||||
role:customer:admin ==> role:customer:tenant
|
||||
role:global:ADMIN ==>|XX| role:customer:OWNER
|
||||
role:customer:OWNER ==> role:customer:ADMIN
|
||||
role:customer:ADMIN ==> role:customer:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:admin ==> perm:customer:INSERT
|
||||
role:customer:owner ==> perm:customer:DELETE
|
||||
role:customer:admin ==> perm:customer:UPDATE
|
||||
role:customer:tenant ==> perm:customer:SELECT
|
||||
role:global:ADMIN ==> perm:customer:INSERT
|
||||
role:customer:OWNER ==> perm:customer:DELETE
|
||||
role:customer:ADMIN ==> perm:customer:UPDATE
|
||||
role:customer:TENANT ==> perm:customer:SELECT
|
||||
|
||||
```
|
||||
|
@ -35,22 +35,22 @@ begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testCustomerOwner(NEW),
|
||||
testCustomerOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalAdmin(unassumed())],
|
||||
incomingSuperRoles => array[globalADMIN(unassumed())],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testCustomerAdmin(NEW),
|
||||
testCustomerADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[testCustomerOwner(NEW)]
|
||||
incomingSuperRoles => array[testCustomerOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testCustomerTenant(NEW),
|
||||
testCustomerTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testCustomerAdmin(NEW)]
|
||||
incomingSuperRoles => array[testCustomerADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
@ -93,7 +93,7 @@ do language plpgsql $$
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_customer'),
|
||||
globalAdmin());
|
||||
globalADMIN());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
@ -108,7 +108,7 @@ create or replace function test_customer_global_insert_tf()
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_customer'),
|
||||
globalAdmin());
|
||||
globalADMIN());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
|
@ -32,7 +32,7 @@ declare
|
||||
newCust test_customer;
|
||||
begin
|
||||
currentTask = 'creating RBAC test customer #' || custReference || '/' || custPrefix;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
custRowId = uuid_generate_v4();
|
||||
|
@ -13,9 +13,9 @@ subgraph package["`**package**`"]
|
||||
subgraph package:roles[ ]
|
||||
style package:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:package:owner[[package:owner]]
|
||||
role:package:admin[[package:admin]]
|
||||
role:package:tenant[[package:tenant]]
|
||||
role:package:OWNER[[package:OWNER]]
|
||||
role:package:ADMIN[[package:ADMIN]]
|
||||
role:package:TENANT[[package:TENANT]]
|
||||
end
|
||||
|
||||
subgraph package:permissions[ ]
|
||||
@ -35,25 +35,25 @@ subgraph customer["`**customer**`"]
|
||||
subgraph customer:roles[ ]
|
||||
style customer:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:customer:owner[[customer:owner]]
|
||||
role:customer:admin[[customer:admin]]
|
||||
role:customer:tenant[[customer:tenant]]
|
||||
role:customer:OWNER[[customer:OWNER]]
|
||||
role:customer:ADMIN[[customer:ADMIN]]
|
||||
role:customer:TENANT[[customer:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:admin -.->|XX| role:customer:owner
|
||||
role:customer:owner -.-> role:customer:admin
|
||||
role:customer:admin -.-> role:customer:tenant
|
||||
role:customer:admin ==> role:package:owner
|
||||
role:package:owner ==> role:package:admin
|
||||
role:package:admin ==> role:package:tenant
|
||||
role:package:tenant ==> role:customer:tenant
|
||||
role:global:ADMIN -.->|XX| role:customer:OWNER
|
||||
role:customer:OWNER -.-> role:customer:ADMIN
|
||||
role:customer:ADMIN -.-> role:customer:TENANT
|
||||
role:customer:ADMIN ==> role:package:OWNER
|
||||
role:package:OWNER ==> role:package:ADMIN
|
||||
role:package:ADMIN ==> role:package:TENANT
|
||||
role:package:TENANT ==> role:customer:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:customer:admin ==> perm:package:INSERT
|
||||
role:package:owner ==> perm:package:DELETE
|
||||
role:package:owner ==> perm:package:UPDATE
|
||||
role:package:tenant ==> perm:package:SELECT
|
||||
role:customer:ADMIN ==> perm:package:INSERT
|
||||
role:package:OWNER ==> perm:package:DELETE
|
||||
role:package:OWNER ==> perm:package:UPDATE
|
||||
role:package:TENANT ==> perm:package:SELECT
|
||||
|
||||
```
|
||||
|
@ -40,21 +40,21 @@ begin
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testPackageOwner(NEW),
|
||||
testPackageOWNER(NEW),
|
||||
permissions => array['DELETE', 'UPDATE'],
|
||||
incomingSuperRoles => array[testCustomerAdmin(newCustomer)]
|
||||
incomingSuperRoles => array[testCustomerADMIN(newCustomer)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testPackageAdmin(NEW),
|
||||
incomingSuperRoles => array[testPackageOwner(NEW)]
|
||||
testPackageADMIN(NEW),
|
||||
incomingSuperRoles => array[testPackageOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testPackageTenant(NEW),
|
||||
testPackageTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testPackageAdmin(NEW)],
|
||||
outgoingSubRoles => array[testCustomerTenant(newCustomer)]
|
||||
incomingSuperRoles => array[testPackageADMIN(NEW)],
|
||||
outgoingSubRoles => array[testCustomerTENANT(newCustomer)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
@ -110,11 +110,11 @@ begin
|
||||
|
||||
if NEW.customerUuid <> OLD.customerUuid then
|
||||
|
||||
call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer));
|
||||
call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer));
|
||||
call revokeRoleFromRole(testPackageOWNER(OLD), testCustomerADMIN(oldCustomer));
|
||||
call grantRoleToRole(testPackageOWNER(NEW), testCustomerADMIN(newCustomer));
|
||||
|
||||
call revokeRoleFromRole(testCustomerTenant(oldCustomer), testPackageTenant(OLD));
|
||||
call grantRoleToRole(testCustomerTenant(newCustomer), testPackageTenant(NEW));
|
||||
call revokeRoleFromRole(testCustomerTENANT(oldCustomer), testPackageTENANT(OLD));
|
||||
call grantRoleToRole(testCustomerTENANT(newCustomer), testPackageTENANT(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
@ -158,7 +158,7 @@ do language plpgsql $$
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_package'),
|
||||
testCustomerAdmin(row));
|
||||
testCustomerADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
@ -173,7 +173,7 @@ create or replace function test_package_test_customer_insert_tf()
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_package'),
|
||||
testCustomerAdmin(NEW));
|
||||
testCustomerADMIN(NEW));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
|
@ -25,7 +25,7 @@ begin
|
||||
cust.uuid;
|
||||
|
||||
custAdminUser = 'customer-admin@' || cust.prefix || '.example.com';
|
||||
custAdminRole = 'test_customer#' || cust.prefix || '.admin';
|
||||
custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN';
|
||||
call defineContext(currentTask, null, 'superuser-fran@hostsharing.net', custAdminRole);
|
||||
raise notice 'task: % by % as %', currentTask, custAdminUser, custAdminRole;
|
||||
|
||||
|
@ -13,9 +13,9 @@ subgraph package.customer["`**package.customer**`"]
|
||||
subgraph package.customer:roles[ ]
|
||||
style package.customer:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:package.customer:owner[[package.customer:owner]]
|
||||
role:package.customer:admin[[package.customer:admin]]
|
||||
role:package.customer:tenant[[package.customer:tenant]]
|
||||
role:package.customer:OWNER[[package.customer:OWNER]]
|
||||
role:package.customer:ADMIN[[package.customer:ADMIN]]
|
||||
role:package.customer:TENANT[[package.customer:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
@ -23,25 +23,12 @@ subgraph package["`**package**`"]
|
||||
direction TB
|
||||
style package fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph package.customer["`**package.customer**`"]
|
||||
direction TB
|
||||
style package.customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph package.customer:roles[ ]
|
||||
style package.customer:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:package.customer:owner[[package.customer:owner]]
|
||||
role:package.customer:admin[[package.customer:admin]]
|
||||
role:package.customer:tenant[[package.customer:tenant]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph package:roles[ ]
|
||||
style package:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:package:owner[[package:owner]]
|
||||
role:package:admin[[package:admin]]
|
||||
role:package:tenant[[package:tenant]]
|
||||
role:package:OWNER[[package:OWNER]]
|
||||
role:package:ADMIN[[package:ADMIN]]
|
||||
role:package:TENANT[[package:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
@ -52,8 +39,8 @@ subgraph domain["`**domain**`"]
|
||||
subgraph domain:roles[ ]
|
||||
style domain:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:domain:owner[[domain:owner]]
|
||||
role:domain:admin[[domain:admin]]
|
||||
role:domain:OWNER[[domain:OWNER]]
|
||||
role:domain:ADMIN[[domain:ADMIN]]
|
||||
end
|
||||
|
||||
subgraph domain:permissions[ ]
|
||||
@ -67,22 +54,22 @@ subgraph domain["`**domain**`"]
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:admin -.->|XX| role:package.customer:owner
|
||||
role:package.customer:owner -.-> role:package.customer:admin
|
||||
role:package.customer:admin -.-> role:package.customer:tenant
|
||||
role:package.customer:admin -.-> role:package:owner
|
||||
role:package:owner -.-> role:package:admin
|
||||
role:package:admin -.-> role:package:tenant
|
||||
role:package:tenant -.-> role:package.customer:tenant
|
||||
role:package:admin ==> role:domain:owner
|
||||
role:domain:owner ==> role:package:tenant
|
||||
role:domain:owner ==> role:domain:admin
|
||||
role:domain:admin ==> role:package:tenant
|
||||
role:global:ADMIN -.->|XX| role:package.customer:OWNER
|
||||
role:package.customer:OWNER -.-> role:package.customer:ADMIN
|
||||
role:package.customer:ADMIN -.-> role:package.customer:TENANT
|
||||
role:package.customer:ADMIN -.-> role:package:OWNER
|
||||
role:package:OWNER -.-> role:package:ADMIN
|
||||
role:package:ADMIN -.-> role:package:TENANT
|
||||
role:package:TENANT -.-> role:package.customer:TENANT
|
||||
role:package:ADMIN ==> role:domain:OWNER
|
||||
role:domain:OWNER ==> role:package:TENANT
|
||||
role:domain:OWNER ==> role:domain:ADMIN
|
||||
role:domain:ADMIN ==> role:package:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:package:admin ==> perm:domain:INSERT
|
||||
role:domain:owner ==> perm:domain:DELETE
|
||||
role:domain:owner ==> perm:domain:UPDATE
|
||||
role:domain:admin ==> perm:domain:SELECT
|
||||
role:package:ADMIN ==> perm:domain:INSERT
|
||||
role:domain:OWNER ==> perm:domain:DELETE
|
||||
role:domain:OWNER ==> perm:domain:UPDATE
|
||||
role:domain:ADMIN ==> perm:domain:SELECT
|
||||
|
||||
```
|
||||
|
@ -40,17 +40,17 @@ begin
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testDomainOwner(NEW),
|
||||
testDomainOWNER(NEW),
|
||||
permissions => array['DELETE', 'UPDATE'],
|
||||
incomingSuperRoles => array[testPackageAdmin(newPackage)],
|
||||
outgoingSubRoles => array[testPackageTenant(newPackage)]
|
||||
incomingSuperRoles => array[testPackageADMIN(newPackage)],
|
||||
outgoingSubRoles => array[testPackageTENANT(newPackage)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testDomainAdmin(NEW),
|
||||
testDomainADMIN(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testDomainOwner(NEW)],
|
||||
outgoingSubRoles => array[testPackageTenant(newPackage)]
|
||||
incomingSuperRoles => array[testDomainOWNER(NEW)],
|
||||
outgoingSubRoles => array[testPackageTENANT(newPackage)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
@ -106,14 +106,14 @@ begin
|
||||
|
||||
if NEW.packageUuid <> OLD.packageUuid then
|
||||
|
||||
call revokeRoleFromRole(testDomainOwner(OLD), testPackageAdmin(oldPackage));
|
||||
call grantRoleToRole(testDomainOwner(NEW), testPackageAdmin(newPackage));
|
||||
call revokeRoleFromRole(testDomainOWNER(OLD), testPackageADMIN(oldPackage));
|
||||
call grantRoleToRole(testDomainOWNER(NEW), testPackageADMIN(newPackage));
|
||||
|
||||
call revokeRoleFromRole(testPackageTenant(oldPackage), testDomainOwner(OLD));
|
||||
call grantRoleToRole(testPackageTenant(newPackage), testDomainOwner(NEW));
|
||||
call revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainOWNER(OLD));
|
||||
call grantRoleToRole(testPackageTENANT(newPackage), testDomainOWNER(NEW));
|
||||
|
||||
call revokeRoleFromRole(testPackageTenant(oldPackage), testDomainAdmin(OLD));
|
||||
call grantRoleToRole(testPackageTenant(newPackage), testDomainAdmin(NEW));
|
||||
call revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainADMIN(OLD));
|
||||
call grantRoleToRole(testPackageTENANT(newPackage), testDomainADMIN(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
@ -157,7 +157,7 @@ do language plpgsql $$
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_domain'),
|
||||
testPackageAdmin(row));
|
||||
testPackageADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
@ -172,7 +172,7 @@ create or replace function test_domain_test_package_insert_tf()
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_domain'),
|
||||
testPackageAdmin(NEW));
|
||||
testPackageADMIN(NEW));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
|
@ -13,9 +13,9 @@ subgraph contact["`**contact**`"]
|
||||
subgraph contact:roles[ ]
|
||||
style contact:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:contact:owner[[contact:owner]]
|
||||
role:contact:admin[[contact:admin]]
|
||||
role:contact:referrer[[contact:referrer]]
|
||||
role:contact:OWNER[[contact:OWNER]]
|
||||
role:contact:ADMIN[[contact:ADMIN]]
|
||||
role:contact:REFERRER[[contact:REFERRER]]
|
||||
end
|
||||
|
||||
subgraph contact:permissions[ ]
|
||||
@ -29,17 +29,17 @@ subgraph contact["`**contact**`"]
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==> role:contact:owner
|
||||
user:creator ==> role:contact:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:admin ==> role:contact:owner
|
||||
role:contact:owner ==> role:contact:admin
|
||||
role:contact:admin ==> role:contact:referrer
|
||||
role:global:ADMIN ==> role:contact:OWNER
|
||||
role:contact:OWNER ==> role:contact:ADMIN
|
||||
role:contact:ADMIN ==> role:contact:REFERRER
|
||||
|
||||
%% granting permissions to roles
|
||||
role:contact:owner ==> perm:contact:DELETE
|
||||
role:contact:admin ==> perm:contact:UPDATE
|
||||
role:contact:referrer ==> perm:contact:SELECT
|
||||
role:global:guest ==> perm:contact:INSERT
|
||||
role:contact:OWNER ==> perm:contact:DELETE
|
||||
role:contact:ADMIN ==> perm:contact:UPDATE
|
||||
role:contact:REFERRER ==> perm:contact:SELECT
|
||||
role:global:GUEST ==> perm:contact:INSERT
|
||||
|
||||
```
|
||||