generated RBAC for coopshares and -assets (#27)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: #27
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig 2024-04-02 11:04:56 +02:00
parent d3ca2b7e23
commit f8fb273918
15 changed files with 809 additions and 231 deletions

View File

@ -1,21 +1,44 @@
package net.hostsharing.hsadminng.hs.office.coopassets; package net.hostsharing.hsadminng.hs.office.coopassets;
import lombok.*; import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.persistence.HasUuid;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerator;
import jakarta.persistence.*; import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
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.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify; import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@Entity @Entity
@ -89,4 +112,22 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUu
public String toShortString() { public String toShortString() {
return "%s:%+1.2f".formatted(getTaggedMemberNumber(), Optional.ofNullable(assetValue).orElse(BigDecimal.ZERO)); return "%s:%+1.2f".formatted(getTaggedMemberNumber(), Optional.ofNullable(assetValue).orElse(BigDecimal.ZERO));
} }
public static RbacView rbac() {
return rbacViewFor("coopAssetsTransaction", HsOfficeCoopAssetsTransactionEntity.class)
.withIdentityView(RbacView.SQL.projection("reference"))
.withUpdatableColumns("comment")
.importEntityAlias("membership", HsOfficeMembershipEntity.class,
dependsOnColumn("membershipUuid"),
directlyFetchedByDependsOnColumn(),
NOT_NULL)
.toRole("membership", ADMIN).grantPermission(INSERT)
.toRole("membership", ADMIN).grantPermission(UPDATE)
.toRole("membership", AGENT).grantPermission(SELECT);
}
public static void main(String[] args) throws IOException {
rbac().generateWithBaseFileName("323-hs-office-coopassets-rbac");
}
} }

View File

@ -1,17 +1,41 @@
package net.hostsharing.hsadminng.hs.office.coopshares; package net.hostsharing.hsadminng.hs.office.coopshares;
import lombok.*; import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.errors.DisplayName;
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.persistence.HasUuid;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringify;
import net.hostsharing.hsadminng.stringify.Stringifyable; import net.hostsharing.hsadminng.stringify.Stringifyable;
import jakarta.persistence.*; import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.UUID; import java.util.UUID;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
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.SQL.directlyFetchedByDependsOnColumn;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify; import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@Entity @Entity
@ -83,4 +107,22 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUu
public String toShortString() { public String toShortString() {
return "%s%+d".formatted(getMemberNumberTagged(), shareCount); return "%s%+d".formatted(getMemberNumberTagged(), shareCount);
} }
public static RbacView rbac() {
return rbacViewFor("coopSharesTransaction", HsOfficeCoopSharesTransactionEntity.class)
.withIdentityView(SQL.projection("reference"))
.withUpdatableColumns("comment")
.importEntityAlias("membership", HsOfficeMembershipEntity.class,
dependsOnColumn("membershipUuid"),
directlyFetchedByDependsOnColumn(),
NOT_NULL)
.toRole("membership", ADMIN).grantPermission(INSERT)
.toRole("membership", ADMIN).grantPermission(UPDATE)
.toRole("membership", AGENT).grantPermission(SELECT);
}
public static void main(String[] args) throws IOException {
rbac().generateWithBaseFileName("313-hs-office-coopshares-rbac");
}
} }

View File

@ -25,7 +25,6 @@ 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.Permission.SELECT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR; 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.*;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.REFERRER;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify; import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@ -142,14 +141,14 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
.createRole(OWNER, (with) -> { .createRole(OWNER, (with) -> {
with.owningUser(CREATOR); with.owningUser(CREATOR);
with.incomingSuperRole("partnerRel", ADMIN);
with.permission(DELETE);
}) })
.createSubRole(ADMIN, (with) -> { .createSubRole(ADMIN, (with) -> {
with.incomingSuperRole("partnerRel", AGENT); with.incomingSuperRole("partnerRel", ADMIN);
with.permission(DELETE);
with.permission(UPDATE); with.permission(UPDATE);
}) })
.createSubRole(REFERRER, (with) -> { .createSubRole(AGENT, (with) -> {
with.incomingSuperRole("partnerRel", AGENT);
with.outgoingSubRole("partnerRel", TENANT); with.outgoingSubRole("partnerRel", TENANT);
with.permission(SELECT); with.permission(SELECT);
}); });

View File

@ -23,7 +23,7 @@ end; $$;
Defines the transaction context. Defines the transaction context.
*/ */
create or replace procedure defineContext( create or replace procedure defineContext(
currentTask varchar(96), currentTask varchar(127),
currentRequest text = null, currentRequest text = null,
currentUser varchar(63) = null, currentUser varchar(63) = null,
assumedRoles varchar(1023) = null assumedRoles varchar(1023) = null
@ -31,8 +31,8 @@ create or replace procedure defineContext(
language plpgsql as $$ language plpgsql as $$
begin begin
currentTask := coalesce(currentTask, ''); currentTask := coalesce(currentTask, '');
assert length(currentTask) <= 96, FORMAT('currentTask must not be longer than 96 characters: "%s"', currentTask); assert length(currentTask) <= 127, FORMAT('currentTask must not be longer than 127 characters: "%s"', currentTask);
assert length(currentTask) > 8, FORMAT('currentTask must be at least 8 characters long: "%s""', currentTask); assert length(currentTask) >= 12, FORMAT('currentTask must be at least 12 characters long: "%s""', currentTask);
execute format('set local hsadminng.currentTask to %L', currentTask); execute format('set local hsadminng.currentTask to %L', currentTask);
currentRequest := coalesce(currentRequest, ''); currentRequest := coalesce(currentRequest, '');
@ -59,11 +59,11 @@ end; $$;
Raises exception if not set. Raises exception if not set.
*/ */
create or replace function currentTask() create or replace function currentTask()
returns varchar(96) returns varchar(127)
stable -- leakproof stable -- leakproof
language plpgsql as $$ language plpgsql as $$
declare declare
currentTask varchar(96); currentTask varchar(127);
begin begin
begin begin
currentTask := current_setting('hsadminng.currentTask'); currentTask := current_setting('hsadminng.currentTask');

View File

@ -28,7 +28,7 @@ create table tx_context
txTimestamp timestamp not null, txTimestamp timestamp not null,
currentUser varchar(63) not null, -- not the uuid, because users can be deleted currentUser varchar(63) not null, -- not the uuid, because users can be deleted
assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted
currentTask varchar(96) not null, currentTask varchar(127) not null,
currentRequest text not null currentRequest text not null
); );

View File

@ -81,7 +81,7 @@ subgraph membership["`**membership**`"]
role:membership:owner[[membership:owner]] role:membership:owner[[membership:owner]]
role:membership:admin[[membership:admin]] role:membership:admin[[membership:admin]]
role:membership:referrer[[membership:referrer]] role:membership:agent[[membership:agent]]
end end
subgraph membership:permissions[ ] subgraph membership:permissions[ ]
@ -144,16 +144,16 @@ role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
role:partnerRel:admin ==> role:membership:owner
role:membership:owner ==> role:membership:admin role:membership:owner ==> role:membership:admin
role:partnerRel:agent ==> role:membership:admin role:partnerRel:admin ==> role:membership:admin
role:membership:admin ==> role:membership:referrer role:membership:admin ==> role:membership:agent
role:membership:referrer ==> role:partnerRel:tenant role:partnerRel:agent ==> role:membership:agent
role:membership:agent ==> role:partnerRel:tenant
%% granting permissions to roles %% granting permissions to roles
role:global:admin ==> perm:membership:INSERT role:global:admin ==> perm:membership:INSERT
role:membership:owner ==> perm:membership:DELETE role:membership:admin ==> perm:membership:DELETE
role:membership:admin ==> perm:membership:UPDATE role:membership:admin ==> perm:membership:UPDATE
role:membership:referrer ==> perm:membership:SELECT role:membership:agent ==> perm:membership:SELECT
``` ```

View File

@ -45,23 +45,23 @@ begin
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeMembershipOwner(NEW), hsOfficeMembershipOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[hsOfficeRelationAdmin(newPartnerRel)],
userUuids => array[currentUserUuid()] userUuids => array[currentUserUuid()]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeMembershipAdmin(NEW), hsOfficeMembershipAdmin(NEW),
permissions => array['UPDATE'], permissions => array['DELETE', 'UPDATE'],
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeMembershipOwner(NEW), hsOfficeMembershipOwner(NEW),
hsOfficeRelationAgent(newPartnerRel)] hsOfficeRelationAdmin(newPartnerRel)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeMembershipReferrer(NEW), hsOfficeMembershipAgent(NEW),
permissions => array['SELECT'], permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW)], incomingSuperRoles => array[
hsOfficeMembershipAdmin(NEW),
hsOfficeRelationAgent(newPartnerRel)],
outgoingSubRoles => array[hsOfficeRelationTenant(newPartnerRel)] outgoingSubRoles => array[hsOfficeRelationTenant(newPartnerRel)]
); );

View File

@ -1,29 +1,250 @@
### hs_office_coopSharesTransaction RBAC ### rbac coopSharesTransaction
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid ```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB flowchart TB
subgraph hsOfficeMembership subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB direction TB
style hsOfficeMembership fill:#eee style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficeMembership.owner[membership.admin] subgraph membership.partnerRel.holderPerson:roles[ ]
--> role:hsOfficeMembership.admin[membership.admin] style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
--> role:hsOfficeMembership.agent[membership.agent]
--> role:hsOfficeMembership.tenant[membership.tenant]
--> role:hsOfficeMembership.guest[membership.guest]
role:hsOfficePartner.agent --> role:hsOfficeMembership.agent role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end end
subgraph hsOfficeCoopSharesTransaction subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficeMembership.admin subgraph membership.partnerRel.anchorPerson:roles[ ]
--> perm:hsOfficeCoopSharesTransaction.create{{coopSharesTx.create}} style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:hsOfficeMembership.agent role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
--> perm:hsOfficeCoopSharesTransaction.view{{coopSharesTx.view}} role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end end
subgraph coopSharesTransaction["`**coopSharesTransaction**`"]
direction TB
style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph coopSharesTransaction:permissions[ ]
style coopSharesTransaction:permissions fill:#dd4901,stroke:white
perm:coopSharesTransaction:INSERT{{coopSharesTransaction:INSERT}}
perm:coopSharesTransaction:UPDATE{{coopSharesTransaction:UPDATE}}
perm:coopSharesTransaction:SELECT{{coopSharesTransaction:SELECT}}
end
end
subgraph membership["`**membership**`"]
direction TB
style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end
subgraph membership.partnerRel["`**membership.partnerRel**`"]
direction TB
style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
subgraph membership.partnerRel:roles[ ]
style membership.partnerRel:roles fill:#99bcdb,stroke:white
role:membership.partnerRel:owner[[membership.partnerRel:owner]]
role:membership.partnerRel:admin[[membership.partnerRel:admin]]
role:membership.partnerRel:agent[[membership.partnerRel:agent]]
role:membership.partnerRel:tenant[[membership.partnerRel:tenant]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
subgraph membership:roles[ ]
style membership:roles fill:#99bcdb,stroke:white
role:membership:owner[[membership:owner]]
role:membership:admin[[membership:admin]]
role:membership:agent[[membership:agent]]
end
end
subgraph membership.partnerRel["`**membership.partnerRel**`"]
direction TB
style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
subgraph membership.partnerRel:roles[ ]
style membership.partnerRel:roles fill:#99bcdb,stroke:white
role:membership.partnerRel:owner[[membership.partnerRel:owner]]
role:membership.partnerRel:admin[[membership.partnerRel:admin]]
role:membership.partnerRel:agent[[membership.partnerRel:agent]]
role:membership.partnerRel:tenant[[membership.partnerRel:tenant]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:membership.partnerRel.anchorPerson:owner
role:membership.partnerRel.anchorPerson:owner -.-> role:membership.partnerRel.anchorPerson:admin
role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel.anchorPerson:referrer
role:global:admin -.-> role:membership.partnerRel.holderPerson:owner
role:membership.partnerRel.holderPerson:owner -.-> role:membership.partnerRel.holderPerson:admin
role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel.holderPerson:referrer
role:global:admin -.-> role:membership.partnerRel.contact:owner
role:membership.partnerRel.contact:owner -.-> role:membership.partnerRel.contact:admin
role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel.contact:referrer
role:global:admin -.-> role:membership.partnerRel:owner
role:membership.partnerRel:owner -.-> role:membership.partnerRel:admin
role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel:admin
role:membership.partnerRel:admin -.-> role:membership.partnerRel:agent
role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:agent
role:membership.partnerRel:agent -.-> role:membership.partnerRel:tenant
role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:tenant
role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel:tenant
role:membership.partnerRel:tenant -.-> role:membership.partnerRel.anchorPerson:referrer
role:membership.partnerRel:tenant -.-> role:membership.partnerRel.holderPerson:referrer
role:membership.partnerRel:tenant -.-> role:membership.partnerRel.contact:referrer
role:membership:owner -.-> role:membership:admin
role:membership.partnerRel:admin -.-> role:membership:admin
role:membership:admin -.-> role:membership:agent
role:membership.partnerRel:agent -.-> role:membership:agent
role:membership:agent -.-> role:membership.partnerRel:tenant
%% granting permissions to roles
role:membership:admin ==> perm:coopSharesTransaction:INSERT
role:membership:admin ==> perm:coopSharesTransaction:UPDATE
role:membership:agent ==> perm:coopSharesTransaction:SELECT
``` ```

View File

@ -1,125 +1,151 @@
--liquibase formatted sql --liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-OBJECT:1 endDelimiter:--// --changeset hs-office-coopsharestransaction-rbac-OBJECT:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_coopSharesTransaction'); call generateRelatedRbacObject('hs_office_coopsharestransaction');
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// --changeset hs-office-coopsharestransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeCoopSharesTransaction', 'hs_office_coopSharesTransaction'); call generateRbacRoleDescriptors('hsOfficeCoopSharesTransaction', 'hs_office_coopsharestransaction');
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-ROLES-CREATION:1 endDelimiter:--// --changeset hs-office-coopsharestransaction-rbac-insert-trigger:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
/* /*
Creates and updates the permissions for coopSharesTransaction entities. Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/ */
create or replace function hsOfficeCoopSharesTransactionRbacRolesTrigger() create or replace procedure buildRbacSystemForHsOfficeCoopSharesTransaction(
returns trigger NEW hs_office_coopsharestransaction
language plpgsql )
strict as $$ language plpgsql as $$
declare declare
newHsOfficeMembership hs_office_membership; newMembership hs_office_membership;
begin begin
call enterTriggerForObjectUuid(NEW.uuid); call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership; SELECT * FROM hs_office_membership WHERE uuid = NEW.membershipUuid INTO newMembership;
assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s', NEW.membershipUuid);
if TG_OP = 'INSERT' then call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipAgent(newMembership));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipAdmin(newMembership));
-- Each coopSharesTransaction entity belong exactly to one membership entity
-- and it makes little sense just to delegate coopSharesTransaction roles.
-- Therefore, we do not create coopSharesTransaction roles at all,
-- but instead just assign extra permissions to existing membership-roles.
-- coopsharestransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole(
getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT'])
);
else
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid); call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_coopsharestransaction row.
*/
create or replace function insertTriggerForHsOfficeCoopSharesTransaction_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeCoopSharesTransaction(NEW);
return NEW; return NEW;
end; $$; end; $$;
/* create trigger insertTriggerForHsOfficeCoopSharesTransaction_tg
An AFTER INSERT TRIGGER which creates the role structure for a new customer. after insert on hs_office_coopsharestransaction
*/
create trigger createRbacRolesForHsOfficeCoopSharesTransaction_Trigger
after insert
on hs_office_coopSharesTransaction
for each row for each row
execute procedure hsOfficeCoopSharesTransactionRbacRolesTrigger(); execute procedure insertTriggerForHsOfficeCoopSharesTransaction_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-coopsharestransaction-rbac-INSERT:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_coopSharesTransaction', 'target.reference');
--//
-- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_coopSharesTransaction', orderby => 'target.reference');
--//
-- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-NEW-CoopSharesTransaction:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/* /*
Creates a global permission for new-coopSharesTransaction and assigns it to the hostsharing admins role. Creates INSERT INTO hs_office_coopsharestransaction permissions for the related hs_office_membership rows.
*/ */
do language plpgsql $$ do language plpgsql $$
declare declare
addCustomerPermissions uuid[]; row hs_office_membership;
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin begin
call defineContext('granting global new-coopSharesTransaction permission to global admin role', null, null, null); call defineContext('create INSERT INTO hs_office_coopsharestransaction permissions for the related hs_office_membership rows');
globalAdminRoleUuid := findRoleId(globalAdmin()); FOR row IN SELECT * FROM hs_office_membership
globalObjectUuid := (select uuid from global); LOOP
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopsharestransaction']); call grantPermissionToRole(
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions); createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'),
end; hsOfficeMembershipAdmin(row));
END LOOP;
END;
$$; $$;
/** /**
Used by the trigger to prevent the add-customer to current user respectively assumed roles. Adds hs_office_coopsharestransaction INSERT permission to specified role of new hs_office_membership rows.
*/ */
create or replace function addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects() create or replace function hs_office_coopsharestransaction_hs_office_membership_insert_tf()
returns trigger returns trigger
language PLPGSQL language plpgsql
as $$ strict as $$
begin begin
raise exception '[403] new-coopsharestransaction not permitted for %', call grantPermissionToRole(
array_to_string(currentSubjects(), ';', 'null'); createPermission(NEW.uuid, 'INSERT', 'hs_office_coopsharestransaction'),
hsOfficeMembershipAdmin(NEW));
return NEW;
end; $$; end; $$;
/** -- z_... is to put it at the end of after insert triggers, to make sure the roles exist
Checks if the user or assumed roles are allowed to create a new customer. create trigger z_hs_office_coopsharestransaction_hs_office_membership_insert_tg
*/ after insert on hs_office_membership
create trigger hs_office_coopSharesTransaction_insert_trigger
before insert
on hs_office_coopSharesTransaction
for each row for each row
when ( not hasAssumedRole() ) execute procedure hs_office_coopsharestransaction_hs_office_membership_insert_tf();
execute procedure addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_coopsharestransaction,
where the check is performed by a direct role.
A direct role is a role depending on a foreign key directly available in the NEW row.
*/
create or replace function hs_office_coopsharestransaction_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_coopsharestransaction not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_coopsharestransaction_insert_permission_check_tg
before insert on hs_office_coopsharestransaction
for each row
when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopsharestransaction') )
execute procedure hs_office_coopsharestransaction_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-coopsharestransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_coopsharestransaction',
$idName$
reference
$idName$);
--//
-- ============================================================================
--changeset hs-office-coopsharestransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_coopsharestransaction',
$orderBy$
reference
$orderBy$,
$updates$
comment = new.comment
$updates$);
--// --//

View File

@ -1,29 +1,250 @@
### hs_office_coopAssetsTransaction RBAC ### rbac coopAssetsTransaction
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid ```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB flowchart TB
subgraph hsOfficeMembership subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB direction TB
style hsOfficeMembership fill:#eee style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficeMembership.owner[membership.admin] subgraph membership.partnerRel.holderPerson:roles[ ]
--> role:hsOfficeMembership.admin[membership.admin] style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
--> role:hsOfficeMembership.agent[membership.agent]
--> role:hsOfficeMembership.tenant[membership.tenant]
--> role:hsOfficeMembership.guest[membership.guest]
role:hsOfficePartner.agent --> role:hsOfficeMembership.agent role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end end
subgraph hsOfficeCoopAssetsTransaction subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficeMembership.admin subgraph membership.partnerRel.anchorPerson:roles[ ]
--> perm:hsOfficeCoopAssetsTransaction.create{{coopAssetsTx.create}} style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:hsOfficeMembership.agent role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
--> perm:hsOfficeCoopAssetsTransaction.view{{coopAssetsTx.view}} role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end end
subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"]
direction TB
style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph coopAssetsTransaction:permissions[ ]
style coopAssetsTransaction:permissions fill:#dd4901,stroke:white
perm:coopAssetsTransaction:INSERT{{coopAssetsTransaction:INSERT}}
perm:coopAssetsTransaction:UPDATE{{coopAssetsTransaction:UPDATE}}
perm:coopAssetsTransaction:SELECT{{coopAssetsTransaction:SELECT}}
end
end
subgraph membership["`**membership**`"]
direction TB
style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end
subgraph membership.partnerRel["`**membership.partnerRel**`"]
direction TB
style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
subgraph membership.partnerRel:roles[ ]
style membership.partnerRel:roles fill:#99bcdb,stroke:white
role:membership.partnerRel:owner[[membership.partnerRel:owner]]
role:membership.partnerRel:admin[[membership.partnerRel:admin]]
role:membership.partnerRel:agent[[membership.partnerRel:agent]]
role:membership.partnerRel:tenant[[membership.partnerRel:tenant]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
subgraph membership:roles[ ]
style membership:roles fill:#99bcdb,stroke:white
role:membership:owner[[membership:owner]]
role:membership:admin[[membership:admin]]
role:membership:agent[[membership:agent]]
end
end
subgraph membership.partnerRel["`**membership.partnerRel**`"]
direction TB
style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"]
direction TB
style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.holderPerson:roles[ ]
style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]]
role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]]
role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]]
end
end
subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"]
direction TB
style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.anchorPerson:roles[ ]
style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]]
role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]]
role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
subgraph membership.partnerRel:roles[ ]
style membership.partnerRel:roles fill:#99bcdb,stroke:white
role:membership.partnerRel:owner[[membership.partnerRel:owner]]
role:membership.partnerRel:admin[[membership.partnerRel:admin]]
role:membership.partnerRel:agent[[membership.partnerRel:agent]]
role:membership.partnerRel:tenant[[membership.partnerRel:tenant]]
end
end
subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"]
direction TB
style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph membership.partnerRel.contact:roles[ ]
style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white
role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]]
role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]]
role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:membership.partnerRel.anchorPerson:owner
role:membership.partnerRel.anchorPerson:owner -.-> role:membership.partnerRel.anchorPerson:admin
role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel.anchorPerson:referrer
role:global:admin -.-> role:membership.partnerRel.holderPerson:owner
role:membership.partnerRel.holderPerson:owner -.-> role:membership.partnerRel.holderPerson:admin
role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel.holderPerson:referrer
role:global:admin -.-> role:membership.partnerRel.contact:owner
role:membership.partnerRel.contact:owner -.-> role:membership.partnerRel.contact:admin
role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel.contact:referrer
role:global:admin -.-> role:membership.partnerRel:owner
role:membership.partnerRel:owner -.-> role:membership.partnerRel:admin
role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel:admin
role:membership.partnerRel:admin -.-> role:membership.partnerRel:agent
role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:agent
role:membership.partnerRel:agent -.-> role:membership.partnerRel:tenant
role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:tenant
role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel:tenant
role:membership.partnerRel:tenant -.-> role:membership.partnerRel.anchorPerson:referrer
role:membership.partnerRel:tenant -.-> role:membership.partnerRel.holderPerson:referrer
role:membership.partnerRel:tenant -.-> role:membership.partnerRel.contact:referrer
role:membership:owner -.-> role:membership:admin
role:membership.partnerRel:admin -.-> role:membership:admin
role:membership:admin -.-> role:membership:agent
role:membership.partnerRel:agent -.-> role:membership:agent
role:membership:agent -.-> role:membership.partnerRel:tenant
%% granting permissions to roles
role:membership:admin ==> perm:coopAssetsTransaction:INSERT
role:membership:admin ==> perm:coopAssetsTransaction:UPDATE
role:membership:agent ==> perm:coopAssetsTransaction:SELECT
``` ```

View File

@ -1,125 +1,151 @@
--liquibase formatted sql --liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-OBJECT:1 endDelimiter:--// --changeset hs-office-coopassetstransaction-rbac-OBJECT:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_coopAssetsTransaction'); call generateRelatedRbacObject('hs_office_coopassetstransaction');
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// --changeset hs-office-coopassetstransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeCoopAssetsTransaction', 'hs_office_coopAssetsTransaction'); call generateRbacRoleDescriptors('hsOfficeCoopAssetsTransaction', 'hs_office_coopassetstransaction');
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-ROLES-CREATION:1 endDelimiter:--// --changeset hs-office-coopassetstransaction-rbac-insert-trigger:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
/* /*
Creates and updates the permissions for coopAssetsTransaction entities. Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/ */
create or replace function hsOfficeCoopAssetsTransactionRbacRolesTrigger() create or replace procedure buildRbacSystemForHsOfficeCoopAssetsTransaction(
returns trigger NEW hs_office_coopassetstransaction
language plpgsql )
strict as $$ language plpgsql as $$
declare declare
newHsOfficeMembership hs_office_membership; newMembership hs_office_membership;
begin begin
call enterTriggerForObjectUuid(NEW.uuid); call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership; SELECT * FROM hs_office_membership WHERE uuid = NEW.membershipUuid INTO newMembership;
assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s', NEW.membershipUuid);
if TG_OP = 'INSERT' then call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipAgent(newMembership));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipAdmin(newMembership));
-- Each coopAssetsTransaction entity belong exactly to one membership entity
-- and it makes little sense just to delegate coopAssetsTransaction roles.
-- Therefore, we do not create coopAssetsTransaction roles at all,
-- but instead just assign extra permissions to existing membership-roles.
-- coopassetstransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole(
getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT'])
);
else
raise exception 'invalid usage of TRIGGER';
end if;
call leaveTriggerForObjectUuid(NEW.uuid); call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_coopassetstransaction row.
*/
create or replace function insertTriggerForHsOfficeCoopAssetsTransaction_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeCoopAssetsTransaction(NEW);
return NEW; return NEW;
end; $$; end; $$;
/* create trigger insertTriggerForHsOfficeCoopAssetsTransaction_tg
An AFTER INSERT TRIGGER which creates the role structure for a new customer. after insert on hs_office_coopassetstransaction
*/
create trigger createRbacRolesForHsOfficeCoopAssetsTransaction_Trigger
after insert
on hs_office_coopAssetsTransaction
for each row for each row
execute procedure hsOfficeCoopAssetsTransactionRbacRolesTrigger(); execute procedure insertTriggerForHsOfficeCoopAssetsTransaction_tf();
--// --//
-- ============================================================================ -- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// --changeset hs-office-coopassetstransaction-rbac-INSERT:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_coopAssetsTransaction', 'target.reference');
--//
-- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_coopAssetsTransaction', orderby => 'target.reference');
--//
-- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-NEW-CoopAssetsTransaction:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/* /*
Creates a global permission for new-coopAssetsTransaction and assigns it to the hostsharing admins role. Creates INSERT INTO hs_office_coopassetstransaction permissions for the related hs_office_membership rows.
*/ */
do language plpgsql $$ do language plpgsql $$
declare declare
addCustomerPermissions uuid[]; row hs_office_membership;
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin begin
call defineContext('granting global new-coopAssetsTransaction permission to global admin role', null, null, null); call defineContext('create INSERT INTO hs_office_coopassetstransaction permissions for the related hs_office_membership rows');
globalAdminRoleUuid := findRoleId(globalAdmin()); FOR row IN SELECT * FROM hs_office_membership
globalObjectUuid := (select uuid from global); LOOP
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopassetstransaction']); call grantPermissionToRole(
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions); createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'),
end; hsOfficeMembershipAdmin(row));
END LOOP;
END;
$$; $$;
/** /**
Used by the trigger to prevent the add-customer to current user respectively assumed roles. Adds hs_office_coopassetstransaction INSERT permission to specified role of new hs_office_membership rows.
*/ */
create or replace function addHsOfficeCoopAssetsTransactionNotAllowedForCurrentSubjects() create or replace function hs_office_coopassetstransaction_hs_office_membership_insert_tf()
returns trigger returns trigger
language PLPGSQL language plpgsql
as $$ strict as $$
begin begin
raise exception '[403] new-coopassetstransaction not permitted for %', call grantPermissionToRole(
array_to_string(currentSubjects(), ';', 'null'); createPermission(NEW.uuid, 'INSERT', 'hs_office_coopassetstransaction'),
hsOfficeMembershipAdmin(NEW));
return NEW;
end; $$; end; $$;
/** -- z_... is to put it at the end of after insert triggers, to make sure the roles exist
Checks if the user or assumed roles are allowed to create a new customer. create trigger z_hs_office_coopassetstransaction_hs_office_membership_insert_tg
*/ after insert on hs_office_membership
create trigger hs_office_coopAssetsTransaction_insert_trigger
before insert
on hs_office_coopAssetsTransaction
for each row for each row
when ( not hasAssumedRole() ) execute procedure hs_office_coopassetstransaction_hs_office_membership_insert_tf();
execute procedure addHsOfficeCoopAssetsTransactionNotAllowedForCurrentSubjects();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_coopassetstransaction,
where the check is performed by a direct role.
A direct role is a role depending on a foreign key directly available in the NEW row.
*/
create or replace function hs_office_coopassetstransaction_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_coopassetstransaction not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_coopassetstransaction_insert_permission_check_tg
before insert on hs_office_coopassetstransaction
for each row
when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopassetstransaction') )
execute procedure hs_office_coopassetstransaction_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-coopassetstransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_coopassetstransaction',
$idName$
reference
$idName$);
--//
-- ============================================================================
--changeset hs-office-coopassetstransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_coopassetstransaction',
$orderBy$
reference
$orderBy$,
$updates$
comment = new.comment
$updates$);
--// --//

View File

@ -89,7 +89,6 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream() final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream()
.map(s -> s.replace("FirstGmbH-firstcontact", "..."))
.map(s -> s.replace("hs_office_", "")) .map(s -> s.replace("hs_office_", ""))
.toList(); .toList();
@ -110,11 +109,11 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
final var all = rawRoleRepo.findAll(); final var all = rawRoleRepo.findAll();
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(initialRoleNames)); // no new roles created assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(initialRoleNames)); // no new roles created
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
.map(s -> s.replace("FirstGmbH-firstcontact", "..."))
.map(s -> s.replace("hs_office_", "")) .map(s -> s.replace("hs_office_", ""))
.containsExactlyInAnyOrder(Array.fromFormatted( .containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames, initialGrantNames,
"{ grant perm SELECT on coopassetstransaction#temprefB to role membership#M-1000101.referrer by system and assume }", "{ grant perm SELECT on coopassetstransaction#temprefB to role membership#M-1000101.agent by system and assume }",
"{ grant perm UPDATE on coopassetstransaction#temprefB to role membership#M-1000101.admin by system and assume }",
null)); null));
} }

View File

@ -111,7 +111,8 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase
.map(s -> s.replace("hs_office_", "")) .map(s -> s.replace("hs_office_", ""))
.containsExactlyInAnyOrder(Array.fromFormatted( .containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames, initialGrantNames,
"{ grant perm SELECT on coopsharestransaction#temprefB to role membership#M-1000101.referrer by system and assume }", "{ grant perm SELECT on coopsharestransaction#temprefB to role membership#M-1000101.agent by system and assume }",
"{ grant perm UPDATE on coopsharestransaction#temprefB to role membership#M-1000101.admin by system and assume }",
null)); null));
} }

View File

@ -335,10 +335,10 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle
} }
@Test @Test
void partnerRelAgent_canPatchValidityOfRelatedMembership() { void partnerRelAdmin_canPatchValidityOfRelatedMembership() {
// given // given
final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent"; final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.admin";
context.define("superuser-alex@hostsharing.net", givenPartnerAgent); context.define("superuser-alex@hostsharing.net", givenPartnerAgent);
final var givenMembership = givenSomeTemporaryMembershipBessler("First"); final var givenMembership = givenSomeTemporaryMembershipBessler("First");

View File

@ -113,29 +113,31 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
initialRoleNames, initialRoleNames,
"hs_office_membership#M-1000117.admin", "hs_office_membership#M-1000117.admin",
"hs_office_membership#M-1000117.owner", "hs_office_membership#M-1000117.owner",
"hs_office_membership#M-1000117.referrer")); "hs_office_membership#M-1000117.agent"));
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
.map(s -> s.replace("GmbH-firstcontact", "")) .map(s -> s.replace("GmbH-firstcontact", ""))
.map(s -> s.replace("hs_office_", "")) .map(s -> s.replace("hs_office_", ""))
.containsExactlyInAnyOrder(Array.fromFormatted( .containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames, initialGrantNames,
// insert
"{ grant perm INSERT into coopassetstransaction with membership#M-1000117 to role membership#M-1000117.admin by system and assume }",
"{ grant perm INSERT into coopsharestransaction with membership#M-1000117 to role membership#M-1000117.admin by system and assume }",
// owner // owner
"{ grant perm DELETE on membership#M-1000117 to role membership#M-1000117.owner by system and assume }", "{ grant perm DELETE on membership#M-1000117 to role membership#M-1000117.admin by system and assume }",
"{ grant role membership#M-1000117.owner to user superuser-alex@hostsharing.net by membership#M-1000117.owner and assume }",
// admin // admin
"{ grant perm UPDATE on membership#M-1000117 to role membership#M-1000117.admin by system and assume }", "{ grant perm UPDATE on membership#M-1000117 to role membership#M-1000117.admin by system and assume }",
"{ grant role membership#M-1000117.admin to role membership#M-1000117.owner by system and assume }", "{ grant role membership#M-1000117.admin to role membership#M-1000117.owner by system and assume }",
"{ grant role membership#M-1000117.owner to role relation#HostsharingeG-with-PARTNER-FirstGmbH.admin by system and assume }", "{ grant role membership#M-1000117.admin to role relation#HostsharingeG-with-PARTNER-FirstGmbH.admin by system and assume }",
"{ grant role membership#M-1000117.owner to user superuser-alex@hostsharing.net by membership#M-1000117.owner and assume }",
// agent // agent
"{ grant role membership#M-1000117.admin to role relation#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }", "{ grant perm SELECT on membership#M-1000117 to role membership#M-1000117.agent by system and assume }",
"{ grant role membership#M-1000117.agent to role membership#M-1000117.admin by system and assume }",
// referrer "{ grant role membership#M-1000117.agent to role relation#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }",
"{ grant perm SELECT on membership#M-1000117 to role membership#M-1000117.referrer by system and assume }", "{ grant role relation#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role membership#M-1000117.agent by system and assume }",
"{ grant role membership#M-1000117.referrer to role membership#M-1000117.admin by system and assume }",
"{ grant role relation#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role membership#M-1000117.referrer by system and assume }",
null)); null));
} }
@ -223,20 +225,20 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
} }
@Test @Test
public void membershipReferrer_canViewButNotUpdateRelatedMembership() { public void membershipAgent_canViewButNotUpdateRelatedMembership() {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var givenMembership = givenSomeTemporaryMembership("First", "13"); final var givenMembership = givenSomeTemporaryMembership("First", "13");
assertThatMembershipExistsAndIsAccessibleToCurrentContext(givenMembership); assertThatMembershipExistsAndIsAccessibleToCurrentContext(givenMembership);
assertThatMembershipIsVisibleForRole( assertThatMembershipIsVisibleForRole(
givenMembership, givenMembership,
"hs_office_membership#M-1000113.referrer"); "hs_office_membership#M-1000113.agent");
final var newValidityEnd = LocalDate.now(); final var newValidityEnd = LocalDate.now();
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
// TODO: we should test with debitor- and partner-admin as well // TODO: we should test with debitor- and partner-admin as well
context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000113.referrer"); context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000113.agent");
givenMembership.setValidity( givenMembership.setValidity(
Range.closedOpen(givenMembership.getValidity().lower(), newValidityEnd)); Range.closedOpen(givenMembership.getValidity().lower(), newValidityEnd));
return membershipRepo.save(givenMembership); return membershipRepo.save(givenMembership);