Merge remote-tracking branch 'origin/master' into add-salut-and-title-to-person
This commit is contained in:
.gitignoreREADME.mdbuild.gradle203-hs-office-contact-rbac.sql213-hs-office-person-rbac.sql220-hs-office-relationship.sql223-hs-office-relationship-rbac.md223-hs-office-relationship-rbac.sql228-hs-office-relationship-test-data.sql233-hs-office-partner-rbac.md233-hs-office-partner-rbac.sql234-hs-office-partner-details-rbac.sql243-hs-office-bankaccount-rbac.md243-hs-office-bankaccount-rbac.sql253-hs-office-sepamandate-rbac.md253-hs-office-sepamandate-rbac.sql258-hs-office-sepamandate-test-data.sql273-hs-office-debitor-rbac.md273-hs-office-debitor-rbac.sql278-hs-office-debitor-test-data.sql303-hs-office-membership-rbac.md303-hs-office-membership-rbac.sql308-hs-office-membership-test-data.sql313-hs-office-coopshares-rbac.md313-hs-office-coopshares-rbac.sql323-hs-office-coopassets-rbac.md323-hs-office-coopassets-rbac.sqldb.changelog-master.yaml
doc
etc
settings.gradlesql
src
main
java
net
hostsharing
hsadminng
context
errors
hs
office
bankaccount
contact
coopassets
coopshares
debitor
HsOfficeDebitorController.javaHsOfficeDebitorEntity.javaHsOfficeDebitorEntityPatcher.javaHsOfficeDebitorRepository.java
membership
partner
HsOfficePartnerController.javaHsOfficePartnerDetailsEntity.javaHsOfficePartnerEntity.javaHsOfficePartnerEntityPatcher.javaHsOfficePartnerRepository.java
person
relation
HsOfficeRelationController.javaHsOfficeRelationEntity.javaHsOfficeRelationEntityPatcher.javaHsOfficeRelationRepository.javaHsOfficeRelationType.java
relationship
sepamandate
mapper
persistence
rbac
rbacdef
InsertTriggerGenerator.javaPostgresTriggerReference.javaRbacIdentityViewGenerator.javaRbacObjectGenerator.javaRbacRestrictedViewGenerator.javaRbacRoleDescriptorsGenerator.javaRbacView.javaRbacViewMermaidFlowchartGenerator.javaRbacViewPostgresGenerator.javaRolesGrantsAndPermissionsGenerator.javaStringWriter.javapackage-info.java
rbacgrant
RawRbacGrantEntity.javaRawRbacGrantRepository.javaRbacGrantController.javaRbacGrantEntity.javaRbacGrantsDiagramService.java
rbacobject
rbacrole
rbacuser
stringify
test
resources
api-definition
hs-office
api-mappings.yamlhs-office-debitor-schemas.yamlhs-office-membership-schemas.yamlhs-office-partner-schemas.yamlhs-office-relation-schemas.yamlhs-office-relations-with-uuid.yamlhs-office-relations.yamlhs-office.yaml
rbac
db
changelog
0-basis
000-template.sql001-last-row-count.sql002-int-to-var.sql003-random-in-range.sql004-jsonb-changes-delta.sql005-uuid-ossp-extension.sql006-numeric-hash-functions.sql007-table-columns.sql009-check-environment.sql010-context.sql020-audit-log.sql
057-rbac-role-builder.sql1-rbac
1050-rbac-base.sql1051-rbac-user-grant.sql1054-rbac-context.sql1055-rbac-views.sql1056-rbac-trigger-context.sql1057-rbac-role-builder.sql1058-rbac-generators.sql1059-rbac-statistics.sql1080-rbac-global.sql
113-test-customer-rbac.sql123-test-package-rbac.sql133-test-domain-rbac.sql2-test
201-test-customer
2010-test-customer.sql2013-test-customer-rbac.md2013-test-customer-rbac.sql2018-test-customer-test-data.sql
202-test-package
2020-test-package.sql2023-test-package-rbac.md2023-test-package-rbac.sql2028-test-package-test-data.sql
203-test-domain
5-hs-office
501-contact
5010-hs-office-contact.sql5013-hs-office-contact-rbac.md5013-hs-office-contact-rbac.sql5016-hs-office-contact-migration.sql5018-hs-office-contact-test-data.sql
502-person
5020-hs-office-person.sql5023-hs-office-person-rbac.md5023-hs-office-person-rbac.sql5028-hs-office-person-test-data.sql
503-relation
5030-hs-office-relation.sql5033-hs-office-relation-rbac.md5033-hs-office-relation-rbac.sql5038-hs-office-relation-test-data.sql
504-partner
5040-hs-office-partner.sql5043-hs-office-partner-rbac.md5043-hs-office-partner-rbac.sql5044-hs-office-partner-details-rbac.md5044-hs-office-partner-details-rbac.sql5046-hs-office-partner-migration.sql5048-hs-office-partner-test-data.sql
505-bankaccount
5050-hs-office-bankaccount.sql5053-hs-office-bankaccount-rbac.md5053-hs-office-bankaccount-rbac.sql5058-hs-office-bankaccount-test-data.sql
506-debitor
5060-hs-office-debitor.sql5063-hs-office-debitor-rbac.md5063-hs-office-debitor-rbac.sql5068-hs-office-debitor-test-data.sql
507-sepamandate
5070-hs-office-sepamandate.sql5073-hs-office-sepamandate-rbac.md5073-hs-office-sepamandate-rbac.sql5076-hs-office-sepamandate-migration.sql5078-hs-office-sepamandate-test-data.sql
510-membership
5100-hs-office-membership.sql5103-hs-office-membership-rbac.md5103-hs-office-membership-rbac.sql5108-hs-office-membership-test-data.sql
511-coopshares
5110-hs-office-coopshares.sql5113-hs-office-coopshares-rbac.md5113-hs-office-coopshares-rbac.sql5116-hs-office-coopshares-migration.sql5118-hs-office-coopshares-test-data.sql
512-coopassets
test
java
net
hostsharing
hsadminng
arch
context
hs
office
bankaccount
contact
coopassets
HsOfficeCoopAssetsTransactionControllerAcceptanceTest.javaHsOfficeCoopAssetsTransactionEntityUnitTest.javaHsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java
coopshares
HsOfficeCoopSharesTransactionControllerAcceptanceTest.javaHsOfficeCoopSharesTransactionRepositoryIntegrationTest.java
debitor
HsOfficeDebitorControllerAcceptanceTest.javaHsOfficeDebitorEntityPatcherUnitTest.javaHsOfficeDebitorEntityUnitTest.javaHsOfficeDebitorRepositoryIntegrationTest.javaTestHsOfficeDebitor.java
membership
HsOfficeMembershipControllerAcceptanceTest.javaHsOfficeMembershipControllerRestTest.javaHsOfficeMembershipEntityPatcherUnitTest.javaHsOfficeMembershipEntityUnitTest.javaHsOfficeMembershipRepositoryIntegrationTest.javaTestHsMembership.java
migration
partner
HsOfficePartnerControllerAcceptanceTest.javaHsOfficePartnerControllerRestTest.javaHsOfficePartnerEntityPatcherUnitTest.javaHsOfficePartnerEntityUnitTest.javaHsOfficePartnerRepositoryIntegrationTest.javaTestHsOfficePartner.java
person
relation
HsOfficeRelationControllerAcceptanceTest.javaHsOfficeRelationEntityPatcherUnitTest.javaHsOfficeRelationEntityUnitTest.javaHsOfficeRelationRepositoryIntegrationTest.java
relationship
sepamandate
HsOfficeSepaMandateControllerAcceptanceTest.javaHsOfficeSepaMandateEntityPatcherUnitTest.javaHsOfficeSepaMandateRepositoryIntegrationTest.java
test
mapper
rbac
rbacgrant
RbacGrantControllerAcceptanceTest.javaRbacGrantEntityUnitTest.javaRbacGrantRepositoryIntegrationTest.javaRbacGrantsDiagramServiceIntegrationTest.java
rbacrole
RawRbacObjectEntity.javaRawRbacObjectRepository.javaRawRbacRoleEntity.javaRbacRoleControllerAcceptanceTest.javaRbacRoleControllerRestTest.javaRbacRoleRepositoryIntegrationTest.javaTestRbacRole.java
rbacuser
test
test
resources
tools
@@ -23,7 +23,7 @@ map:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/persons/{personUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/relationships/{relationshipUUID}:
|
||||
/api/hs/office/relations/{relationUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/bankaccounts/{bankAccountUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
|
@@ -9,6 +9,8 @@ components:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
debitorRel:
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
debitorNumber:
|
||||
type: integer
|
||||
format: int32
|
||||
@@ -21,8 +23,6 @@ components:
|
||||
maximum: 99
|
||||
partner:
|
||||
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartner'
|
||||
billingContact:
|
||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||
billable:
|
||||
type: boolean
|
||||
vatId:
|
||||
@@ -43,7 +43,7 @@ components:
|
||||
HsOfficeDebitorPatch:
|
||||
type: object
|
||||
properties:
|
||||
billingContactUuid:
|
||||
debitorRelUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
@@ -75,14 +75,11 @@ components:
|
||||
HsOfficeDebitorInsert:
|
||||
type: object
|
||||
properties:
|
||||
partnerUuid:
|
||||
debitorRel:
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationInsert'
|
||||
debitorRelUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: false
|
||||
billingContactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: false
|
||||
debitorNumberSuffix:
|
||||
type: integer
|
||||
format: int8
|
||||
@@ -105,9 +102,7 @@ components:
|
||||
defaultPrefix:
|
||||
type: string
|
||||
pattern: '^[a-z]{3}$'
|
||||
|
||||
required:
|
||||
- partnerUuid
|
||||
- billingContactUuid
|
||||
- debitorNumberSuffix
|
||||
- defaultPrefix
|
||||
- billable
|
||||
|
@@ -46,10 +46,6 @@ components:
|
||||
HsOfficeMembershipPatch:
|
||||
type: object
|
||||
properties:
|
||||
mainDebitorUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
validTo:
|
||||
type: string
|
||||
format: date
|
||||
@@ -69,10 +65,6 @@ components:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: false
|
||||
mainDebitorUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: false
|
||||
memberNumberSuffix:
|
||||
type: string
|
||||
minLength: 2
|
||||
@@ -95,7 +87,6 @@ components:
|
||||
required:
|
||||
- partnerUuid
|
||||
- memberNumberSuffix
|
||||
- mainDebitorUuid
|
||||
- validFrom
|
||||
- membershipFeeBillable
|
||||
additionalProperties: false
|
||||
|
@@ -14,10 +14,8 @@ components:
|
||||
format: int8
|
||||
minimum: 10000
|
||||
maximum: 99999
|
||||
person:
|
||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||
contact:
|
||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||
partnerRel:
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
details:
|
||||
$ref: '#/components/schemas/HsOfficePartnerDetails'
|
||||
|
||||
@@ -52,11 +50,7 @@ components:
|
||||
HsOfficePartnerPatch:
|
||||
type: object
|
||||
properties:
|
||||
personUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
contactUuid:
|
||||
partnerRelUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
@@ -96,38 +90,31 @@ components:
|
||||
format: int8
|
||||
minimum: 10000
|
||||
maximum: 99999
|
||||
partnerRole:
|
||||
$ref: '#/components/schemas/HsOfficePartnerRoleInsert'
|
||||
personUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
contactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
partnerRel:
|
||||
$ref: '#/components/schemas/HsOfficePartnerRelInsert'
|
||||
details:
|
||||
$ref: '#/components/schemas/HsOfficePartnerDetailsInsert'
|
||||
required:
|
||||
- partnerNumber
|
||||
- personUuid
|
||||
- contactUuid
|
||||
- partnerRel
|
||||
- details
|
||||
|
||||
HsOfficePartnerRoleInsert:
|
||||
HsOfficePartnerRelInsert:
|
||||
type: object
|
||||
nullable: false
|
||||
properties:
|
||||
relAnchorUuid:
|
||||
anchorUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relHolderUuid:
|
||||
holderUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
contactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
required:
|
||||
- relAnchorUuid
|
||||
- relHolderUuid
|
||||
- anchorUuid
|
||||
- holderUuid
|
||||
- relContactUuid
|
||||
|
||||
HsOfficePartnerDetailsInsert:
|
||||
|
@@ -3,37 +3,37 @@ components:
|
||||
|
||||
schemas:
|
||||
|
||||
HsOfficeRelationshipType:
|
||||
HsOfficeRelationType:
|
||||
type: string
|
||||
enum:
|
||||
- UNKNOWN
|
||||
- PARTNER
|
||||
- EX_PARTNER
|
||||
- REPRESENTATIVE,
|
||||
- DEBITOR
|
||||
- REPRESENTATIVE
|
||||
- VIP_CONTACT
|
||||
- ACCOUNTING,
|
||||
- OPERATIONS
|
||||
- SUBSCRIBER
|
||||
|
||||
HsOfficeRelationship:
|
||||
HsOfficeRelation:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relAnchor:
|
||||
anchor:
|
||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||
relHolder:
|
||||
holder:
|
||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||
relType:
|
||||
type:
|
||||
type: string
|
||||
relMark:
|
||||
mark:
|
||||
type: string
|
||||
nullable: true
|
||||
contact:
|
||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||
|
||||
HsOfficeRelationshipPatch:
|
||||
HsOfficeRelationPatch:
|
||||
type: object
|
||||
properties:
|
||||
contactUuid:
|
||||
@@ -41,25 +41,26 @@ components:
|
||||
format: uuid
|
||||
nullable: true
|
||||
|
||||
HsOfficeRelationshipInsert:
|
||||
HsOfficeRelationInsert:
|
||||
type: object
|
||||
properties:
|
||||
relAnchorUuid:
|
||||
anchorUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relHolderUuid:
|
||||
holderUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relType:
|
||||
type:
|
||||
type: string
|
||||
nullable: true
|
||||
relMark:
|
||||
mark:
|
||||
type: string
|
||||
nullable: true
|
||||
contactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
required:
|
||||
- relAnchorUuid
|
||||
- relHolderUuid
|
||||
- relType
|
||||
- relContactUuid
|
||||
- anchorUuid
|
||||
- holderUuid
|
||||
- type
|
||||
- contactUuid
|
@@ -1,25 +1,25 @@
|
||||
get:
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
description: 'Fetch a single person relationship by its uuid, if visible for the current subject.'
|
||||
operationId: getRelationshipByUuid
|
||||
- hs-office-relations
|
||||
description: 'Fetch a single person relation by its uuid, if visible for the current subject.'
|
||||
operationId: getRelationByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationshipUUID
|
||||
- name: relationUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the relationship to fetch.
|
||||
description: UUID of the relation to fetch.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
@@ -28,13 +28,13 @@ get:
|
||||
|
||||
patch:
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
description: 'Updates a single person relationship by its uuid, if permitted for the current subject.'
|
||||
operationId: patchRelationship
|
||||
- hs-office-relations
|
||||
description: 'Updates a single person relation by its uuid, if permitted for the current subject.'
|
||||
operationId: patchRelation
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationshipUUID
|
||||
- name: relationUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
@@ -44,14 +44,14 @@ patch:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipPatch'
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationPatch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
@@ -59,19 +59,19 @@ patch:
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
description: 'Delete a single person relationship by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteRelationshipByUuid
|
||||
- hs-office-relations
|
||||
description: 'Delete a single person relation by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteRelationByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationshipUUID
|
||||
- name: relationUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the relationship to delete.
|
||||
description: UUID of the relation to delete.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
@@ -1,9 +1,9 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) person relationships for a given person.
|
||||
description: Returns the list of (optionally filtered) person relationships of a given person and which are visible to the current user or any of it's assumed roles.
|
||||
summary: Returns a list of (optionally filtered) person relations for a given person.
|
||||
description: Returns the list of (optionally filtered) person relations of a given person and which are visible to the current user or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
operationId: listRelationships
|
||||
- hs-office-relations
|
||||
operationId: listRelations
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
@@ -13,13 +13,13 @@ get:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Prefix of name properties from relHolder or contact to filter the results.
|
||||
- name: relationshipType
|
||||
description: Prefix of name properties from holder or contact to filter the results.
|
||||
- name: relationType
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipType'
|
||||
description: Prefix of name properties from relHolder or contact to filter the results.
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationType'
|
||||
description: Prefix of name properties from holder or contact to filter the results.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@@ -28,17 +28,17 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
post:
|
||||
summary: Adds a new person relationship.
|
||||
summary: Adds a new person relation.
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
operationId: addRelationship
|
||||
- hs-office-relations
|
||||
operationId: addRelation
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
@@ -46,7 +46,7 @@ post:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipInsert'
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationInsert'
|
||||
required: true
|
||||
responses:
|
||||
"201":
|
||||
@@ -54,7 +54,7 @@ post:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
@@ -35,13 +35,13 @@ paths:
|
||||
$ref: "./hs-office-persons-with-uuid.yaml"
|
||||
|
||||
|
||||
# Relationships
|
||||
# Relations
|
||||
|
||||
/api/hs/office/relationships:
|
||||
$ref: "./hs-office-relationships.yaml"
|
||||
/api/hs/office/relations:
|
||||
$ref: "./hs-office-relations.yaml"
|
||||
|
||||
/api/hs/office/relationships/{relationshipUUID}:
|
||||
$ref: "./hs-office-relationships-with-uuid.yaml"
|
||||
/api/hs/office/relations/{relationUUID}:
|
||||
$ref: "./hs-office-relations-with-uuid.yaml"
|
||||
|
||||
|
||||
# BankAccounts
|
||||
|
@@ -19,8 +19,11 @@ components:
|
||||
roleType:
|
||||
type: string
|
||||
enum:
|
||||
- owner
|
||||
- admin
|
||||
- tenant
|
||||
- OWNER
|
||||
- ADMIN
|
||||
- AGENT
|
||||
- TENANT
|
||||
- REFERRER
|
||||
- GUEST
|
||||
roleName:
|
||||
type: string
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- NUMERIC-HASH-FUNCTIONS
|
||||
--changeset hash:1 endDelimiter:--//
|
||||
--changeset numeric-hash-functions:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create function bigIntHash(text) returns bigint as $$
|
@@ -0,0 +1,20 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- TABLE-COLUMNS-FUNCTION
|
||||
--changeset table-columns-function:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function columnsNames( tableName text )
|
||||
returns text
|
||||
stable
|
||||
language 'plpgsql' as $$
|
||||
declare columns text[];
|
||||
begin
|
||||
columns := (select array(select column_name::text
|
||||
from information_schema.columns
|
||||
where table_name = tableName));
|
||||
return array_to_string(columns, ', ');
|
||||
end; $$
|
||||
--//
|
@@ -10,10 +10,10 @@
|
||||
This function will be overwritten by later changesets.
|
||||
*/
|
||||
create procedure contextDefined(
|
||||
currentTask varchar,
|
||||
currentRequest varchar,
|
||||
currentUser varchar,
|
||||
assumedRoles varchar
|
||||
currentTask varchar(127),
|
||||
currentRequest text,
|
||||
currentUser varchar(63),
|
||||
assumedRoles varchar(1023)
|
||||
)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@@ -23,22 +23,27 @@ end; $$;
|
||||
Defines the transaction context.
|
||||
*/
|
||||
create or replace procedure defineContext(
|
||||
currentTask varchar,
|
||||
currentRequest varchar = null,
|
||||
currentUser varchar = null,
|
||||
assumedRoles varchar = null
|
||||
currentTask varchar(127),
|
||||
currentRequest text = null,
|
||||
currentUser varchar(63) = null,
|
||||
assumedRoles varchar(1023) = null
|
||||
)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
currentTask := coalesce(currentTask, '');
|
||||
assert length(currentTask) <= 127, FORMAT('currentTask must not be longer than 127 characters: "%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);
|
||||
|
||||
currentRequest := coalesce(currentRequest, '');
|
||||
execute format('set local hsadminng.currentRequest to %L', currentRequest);
|
||||
|
||||
currentUser := coalesce(currentUser, '');
|
||||
assert length(currentUser) <= 63, FORMAT('currentUser must not be longer than 63 characters: "%s"', currentUser);
|
||||
execute format('set local hsadminng.currentUser to %L', currentUser);
|
||||
|
||||
assumedRoles := coalesce(assumedRoles, '');
|
||||
assert length(assumedRoles) <= 1023, FORMAT('assumedRoles must not be longer than 1023 characters: "%s"', assumedRoles);
|
||||
execute format('set local hsadminng.assumedRoles to %L', assumedRoles);
|
||||
|
||||
call contextDefined(currentTask, currentRequest, currentUser, assumedRoles);
|
||||
@@ -54,11 +59,11 @@ end; $$;
|
||||
Raises exception if not set.
|
||||
*/
|
||||
create or replace function currentTask()
|
||||
returns varchar(96)
|
||||
returns varchar(127)
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar(96);
|
||||
currentTask varchar(127);
|
||||
begin
|
||||
begin
|
||||
currentTask := current_setting('hsadminng.currentTask');
|
||||
@@ -82,11 +87,11 @@ end; $$;
|
||||
Raises exception if not set.
|
||||
*/
|
||||
create or replace function currentRequest()
|
||||
returns varchar(512)
|
||||
returns text
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentRequest varchar(512);
|
||||
currentRequest text;
|
||||
begin
|
||||
begin
|
||||
currentRequest := current_setting('hsadminng.currentRequest');
|
||||
@@ -130,22 +135,11 @@ end; $$;
|
||||
or empty array, if not set.
|
||||
*/
|
||||
create or replace function assumedRoles()
|
||||
returns varchar(63)[]
|
||||
returns varchar(1023)[]
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentSubject varchar(63);
|
||||
begin
|
||||
begin
|
||||
currentSubject := current_setting('hsadminng.assumedRoles');
|
||||
exception
|
||||
when others then
|
||||
return array []::varchar[];
|
||||
end;
|
||||
if (currentSubject = '') then
|
||||
return array []::varchar[];
|
||||
end if;
|
||||
return string_to_array(currentSubject, ';');
|
||||
return string_to_array(current_setting('hsadminng.assumedRoles', true), ';');
|
||||
end; $$;
|
||||
|
||||
create or replace function cleanIdentifier(rawIdentifier varchar)
|
||||
@@ -155,7 +149,7 @@ create or replace function cleanIdentifier(rawIdentifier varchar)
|
||||
declare
|
||||
cleanIdentifier varchar;
|
||||
begin
|
||||
cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._:]+', '', 'g');
|
||||
cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._]+', '', 'g');
|
||||
return cleanIdentifier;
|
||||
end; $$;
|
||||
|
||||
@@ -213,17 +207,17 @@ begin
|
||||
end ; $$;
|
||||
|
||||
create or replace function currentSubjects()
|
||||
returns varchar(63)[]
|
||||
returns varchar(1023)[]
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
assumedRoles varchar(63)[];
|
||||
assumedRoles varchar(1023)[];
|
||||
begin
|
||||
assumedRoles := assumedRoles();
|
||||
if array_length(assumedRoles, 1) > 0 then
|
||||
return assumedRoles();
|
||||
return assumedRoles;
|
||||
else
|
||||
return array [currentUser()]::varchar(63)[];
|
||||
return array [currentUser()]::varchar(1023)[];
|
||||
end if;
|
||||
end; $$;
|
||||
|
@@ -27,9 +27,9 @@ create table tx_context
|
||||
txId bigint not null,
|
||||
txTimestamp timestamp not null,
|
||||
currentUser varchar(63) not null, -- not the uuid, because users can be deleted
|
||||
assumedRoles varchar not null, -- not the uuids, because roles can be deleted
|
||||
currentTask varchar(96) not null,
|
||||
currentRequest varchar(512) not null
|
||||
assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted
|
||||
currentTask varchar(127) not null,
|
||||
currentRequest text not null
|
||||
);
|
||||
|
||||
create index on tx_context using brin (txTimestamp);
|
@@ -1,88 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
-- PERMISSIONS
|
||||
--changeset rbac-role-builder-to-uuids:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function toPermissionUuids(forObjectUuid uuid, permitOps RbacOp[])
|
||||
returns uuid[]
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
return createPermissions(forObjectUuid, permitOps);
|
||||
end; $$;
|
||||
|
||||
create or replace function toRoleUuids(roleDescriptors RbacRoleDescriptor[])
|
||||
returns uuid[]
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
superRoleDescriptor RbacRoleDescriptor;
|
||||
superRoleUuids uuid[] := array []::uuid[];
|
||||
begin
|
||||
foreach superRoleDescriptor in array roleDescriptors
|
||||
loop
|
||||
if superRoleDescriptor is not null then
|
||||
superRoleUuids := superRoleUuids || getRoleId(superRoleDescriptor, 'fail');
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return superRoleUuids;
|
||||
end; $$;
|
||||
|
||||
|
||||
-- =================================================================
|
||||
-- CREATE ROLE
|
||||
--changeset rbac-role-builder-create-role:1 endDelimiter:--//
|
||||
-- -----------------------------------------------------------------
|
||||
|
||||
create or replace function createRoleWithGrants(
|
||||
roleDescriptor RbacRoleDescriptor,
|
||||
permissions RbacOp[] = array[]::RbacOp[],
|
||||
incomingSuperRoles RbacRoleDescriptor[] = array[]::RbacRoleDescriptor[],
|
||||
outgoingSubRoles RbacRoleDescriptor[] = array[]::RbacRoleDescriptor[],
|
||||
userUuids uuid[] = array[]::uuid[],
|
||||
grantedByRole RbacRoleDescriptor = null
|
||||
)
|
||||
returns uuid
|
||||
called on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
roleUuid uuid;
|
||||
superRoleUuid uuid;
|
||||
subRoleUuid uuid;
|
||||
userUuid uuid;
|
||||
grantedByRoleUuid uuid;
|
||||
begin
|
||||
roleUuid := createRole(roleDescriptor);
|
||||
|
||||
if cardinality(permissions) >0 then
|
||||
call grantPermissionsToRole(roleUuid, toPermissionUuids(roleDescriptor.objectuuid, permissions));
|
||||
end if;
|
||||
|
||||
foreach superRoleUuid in array toRoleUuids(incomingSuperRoles)
|
||||
loop
|
||||
call grantRoleToRole(roleUuid, superRoleUuid);
|
||||
end loop;
|
||||
|
||||
foreach subRoleUuid in array toRoleUuids(outgoingSubRoles)
|
||||
loop
|
||||
call grantRoleToRole(subRoleUuid, roleUuid);
|
||||
end loop;
|
||||
|
||||
if cardinality(userUuids) > 0 then
|
||||
if grantedByRole is null then
|
||||
raise exception 'to directly assign users to roles, grantingRole has to be given';
|
||||
end if;
|
||||
grantedByRoleUuid := getRoleId(grantedByRole, 'fail');
|
||||
foreach userUuid in array userUuids
|
||||
loop
|
||||
call grantRoleToUserUnchecked(grantedByRoleUuid, roleUuid, userUuid);
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
return roleUuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
@@ -86,29 +86,6 @@ create or replace function findRbacUserId(userName varchar)
|
||||
language sql as $$
|
||||
select uuid from RbacUser where name = userName
|
||||
$$;
|
||||
|
||||
create type RbacWhenNotExists as enum ('fail', 'create');
|
||||
|
||||
create or replace function getRbacUserId(userName varchar, whenNotExists RbacWhenNotExists)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
userUuid uuid;
|
||||
begin
|
||||
userUuid = findRbacUserId(userName);
|
||||
if (userUuid is null) then
|
||||
if (whenNotExists = 'fail') then
|
||||
raise exception 'RbacUser with name="%" not found', userName;
|
||||
end if;
|
||||
if (whenNotExists = 'create') then
|
||||
userUuid = createRbacUser(userName);
|
||||
end if;
|
||||
end if;
|
||||
return userUuid;
|
||||
end;
|
||||
$$;
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
@@ -187,7 +164,7 @@ end; $$;
|
||||
|
||||
*/
|
||||
|
||||
create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest');
|
||||
create type RbacRoleType as enum ('OWNER', 'ADMIN', 'AGENT', 'TENANT', 'GUEST', 'REFERRER');
|
||||
|
||||
create table RbacRole
|
||||
(
|
||||
@@ -203,15 +180,33 @@ create type RbacRoleDescriptor as
|
||||
(
|
||||
objectTable varchar(63), -- for human readability and easier debugging
|
||||
objectUuid uuid,
|
||||
roleType RbacRoleType
|
||||
roleType RbacRoleType,
|
||||
assumed boolean
|
||||
);
|
||||
|
||||
create or replace function roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType)
|
||||
create or replace function assumed()
|
||||
returns boolean
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select true;
|
||||
$$;
|
||||
|
||||
create or replace function unassumed()
|
||||
returns boolean
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select false;
|
||||
$$;
|
||||
|
||||
|
||||
create or replace function roleDescriptor(
|
||||
objectTable varchar(63), objectUuid uuid, roleType RbacRoleType,
|
||||
assumed boolean = true) -- just for DSL readability, belongs actually to the grant
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select objectTable, objectUuid, roleType::RbacRoleType;
|
||||
select objectTable, objectUuid, roleType::RbacRoleType, assumed;
|
||||
$$;
|
||||
|
||||
create or replace function createRole(roleDescriptor RbacRoleDescriptor)
|
||||
@@ -254,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);
|
||||
@@ -275,21 +270,17 @@ create or replace function findRoleId(roleDescriptor RbacRoleDescriptor)
|
||||
select uuid from RbacRole where objectUuid = roleDescriptor.objectUuid and roleType = roleDescriptor.roleType;
|
||||
$$;
|
||||
|
||||
create or replace function getRoleId(roleDescriptor RbacRoleDescriptor, whenNotExists RbacWhenNotExists)
|
||||
create or replace function getRoleId(roleDescriptor RbacRoleDescriptor)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
roleUuid uuid;
|
||||
begin
|
||||
roleUuid = findRoleId(roleDescriptor);
|
||||
assert roleDescriptor is not null, 'roleDescriptor must not be null';
|
||||
|
||||
roleUuid := findRoleId(roleDescriptor);
|
||||
if (roleUuid is null) then
|
||||
if (whenNotExists = 'fail') then
|
||||
raise exception 'RbacRole "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
|
||||
end if;
|
||||
if (whenNotExists = 'create') then
|
||||
roleUuid = createRole(roleDescriptor);
|
||||
end if;
|
||||
raise exception 'RbacRole "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
|
||||
end if;
|
||||
return roleUuid;
|
||||
end;
|
||||
@@ -365,38 +356,68 @@ create trigger deleteRbacRolesOfRbacObject_Trigger
|
||||
/*
|
||||
|
||||
*/
|
||||
create domain RbacOp as varchar(67)
|
||||
create domain RbacOp as varchar(67) -- TODO: shorten to 8, once the deprecated values are gone
|
||||
check (
|
||||
VALUE = '*'
|
||||
or VALUE = 'delete'
|
||||
or VALUE = 'edit'
|
||||
or VALUE = 'view'
|
||||
or VALUE = 'assume'
|
||||
VALUE = 'DELETE'
|
||||
or VALUE = 'UPDATE'
|
||||
or VALUE = 'SELECT'
|
||||
or VALUE = 'INSERT'
|
||||
or VALUE = 'ASSUME'
|
||||
-- TODO: all values below are deprecated, use insert with table
|
||||
or VALUE ~ '^add-[a-z]+$'
|
||||
or VALUE ~ '^new-[a-z-]+$'
|
||||
);
|
||||
|
||||
create table RbacPermission
|
||||
(
|
||||
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
||||
objectUuid uuid not null references RbacObject,
|
||||
op RbacOp not null,
|
||||
unique (objectUuid, op)
|
||||
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
||||
objectUuid uuid not null references RbacObject,
|
||||
op RbacOp not null,
|
||||
opTableName varchar(60)
|
||||
);
|
||||
|
||||
ALTER TABLE RbacPermission
|
||||
ADD CONSTRAINT RbacPermission_uc UNIQUE NULLS NOT DISTINCT (objectUuid, op, opTableName);
|
||||
|
||||
call create_journal('RbacPermission');
|
||||
|
||||
create or replace function permissionExists(forObjectUuid uuid, forOp RbacOp)
|
||||
returns bool
|
||||
language sql as $$
|
||||
select exists(
|
||||
select op
|
||||
from RbacPermission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and p.op in ('*', forOp)
|
||||
);
|
||||
$$;
|
||||
create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
language plpgsql as $$
|
||||
declare
|
||||
permissionUuid uuid;
|
||||
begin
|
||||
if (forObjectUuid is null) then
|
||||
raise exception 'forObjectUuid must not be null';
|
||||
end if;
|
||||
if (forOp = 'INSERT' and forOpTableName is null) then
|
||||
raise exception 'INSERT permissions needs forOpTableName';
|
||||
end if;
|
||||
if (forOp <> 'INSERT' and forOpTableName is not null) then
|
||||
raise exception 'forOpTableName must only be specified for ops: [INSERT]'; -- currently no other
|
||||
end if;
|
||||
|
||||
permissionUuid := (
|
||||
select uuid from RbacPermission
|
||||
where objectUuid = forObjectUuid
|
||||
and op = forOp and opTableName is not distinct from forOpTableName);
|
||||
if (permissionUuid is null) then
|
||||
insert into RbacReference ("type")
|
||||
values ('RbacPermission')
|
||||
returning uuid into permissionUuid;
|
||||
begin
|
||||
insert into RbacPermission (uuid, objectUuid, op, opTableName)
|
||||
values (permissionUuid, forObjectUuid, forOp, forOpTableName);
|
||||
exception
|
||||
when others then
|
||||
raise exception 'insert into RbacPermission (uuid, objectUuid, op, opTableName)
|
||||
values (%, %, %, %);', permissionUuid, forObjectUuid, forOp, forOpTableName;
|
||||
end;
|
||||
end if;
|
||||
return permissionUuid;
|
||||
end; $$;
|
||||
|
||||
-- TODO: deprecated, remove and amend all usages to createPermission
|
||||
create or replace function createPermissions(forObjectUuid uuid, permitOps RbacOp[])
|
||||
returns uuid[]
|
||||
language plpgsql as $$
|
||||
@@ -407,9 +428,6 @@ begin
|
||||
if (forObjectUuid is null) then
|
||||
raise exception 'forObjectUuid must not be null';
|
||||
end if;
|
||||
if (array_length(permitOps, 1) > 1 and '*' = any (permitOps)) then
|
||||
raise exception '"*" operation must not be assigned along with other operations: %', permitOps;
|
||||
end if;
|
||||
|
||||
for i in array_lower(permitOps, 1)..array_upper(permitOps, 1)
|
||||
loop
|
||||
@@ -430,7 +448,19 @@ begin
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function findPermissionId(forObjectUuid uuid, forOp RbacOp)
|
||||
create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select uuid
|
||||
from RbacPermission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and (forOp = 'SELECT' or p.op = forOp) -- all other RbacOp include 'SELECT'
|
||||
and p.opTableName = forOpTableName
|
||||
$$;
|
||||
|
||||
create or replace function findPermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
@@ -439,25 +469,46 @@ select uuid
|
||||
from RbacPermission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and p.op = forOp
|
||||
and p.opTableName = forOpTableName
|
||||
$$;
|
||||
|
||||
create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp)
|
||||
create or replace function getPermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
permissionId uuid;
|
||||
permissionUuid uuid;
|
||||
begin
|
||||
permissionId := findPermissionId(forObjectUuid, forOp);
|
||||
if permissionId is null and forOp <> '*' then
|
||||
permissionId := findPermissionId(forObjectUuid, '*');
|
||||
end if;
|
||||
return permissionId;
|
||||
end $$;
|
||||
|
||||
select uuid into permissionUuid
|
||||
from RbacPermission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and p.op = forOp
|
||||
and forOpTableName is null or p.opTableName = forOpTableName;
|
||||
assert permissionUuid is not null,
|
||||
format('permission %s %s for object UUID %s cannot be found', forOp, forOpTableName, forObjectUuid);
|
||||
return permissionUuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-duplicate-role-grant-exception:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure raiseDuplicateRoleGrantException(subRoleId uuid, superRoleId uuid)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
subRoleIdName text;
|
||||
superRoleIdName text;
|
||||
begin
|
||||
select roleIdName from rbacRole_ev where uuid=subRoleId into subRoleIdName;
|
||||
select roleIdName from rbacRole_ev where uuid=superRoleId into superRoleIdName;
|
||||
raise exception '[400] Duplicate role grant detected: role % (%) already granted to % (%)', subRoleId, subRoleIdName, superRoleId, superRoleIdName;
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-GRANTS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
@@ -552,6 +603,18 @@ select exists(
|
||||
);
|
||||
$$;
|
||||
|
||||
create or replace function hasInsertPermission(objectUuid uuid, forOp RbacOp, tableName text )
|
||||
returns BOOL
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
permissionUuid uuid;
|
||||
begin
|
||||
permissionUuid = findPermissionId(objectUuid, forOp, tableName);
|
||||
return permissionUuid is not null;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function hasGlobalRoleGranted(userUuid uuid)
|
||||
returns bool
|
||||
stable -- leakproof
|
||||
@@ -566,6 +629,27 @@ select exists(
|
||||
);
|
||||
$$;
|
||||
|
||||
create or replace procedure grantPermissionToRole(permissionUuid uuid, roleUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
|
||||
perform assertReferenceType('permissionId (descendant)', permissionUuid, 'RbacPermission');
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
|
||||
values (currentTriggerObjectUuid(), roleUuid, permissionUuid, true)
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace procedure grantPermissionToRole(permissionUuid uuid, roleDesc RbacRoleDescriptor)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call grantPermissionToRole(permissionUuid, findRoleId(roleDesc));
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- TODO: deprecated, remove and use grantPermissionToRole(...)
|
||||
create or replace procedure grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@@ -591,7 +675,7 @@ begin
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
|
||||
if isGranted(subRoleId, superRoleId) then
|
||||
raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
||||
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
end if;
|
||||
|
||||
insert
|
||||
@@ -607,6 +691,11 @@ declare
|
||||
superRoleId uuid;
|
||||
subRoleId uuid;
|
||||
begin
|
||||
-- TODO: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
|
||||
if superRole.objectUuid is null or subRole.objectuuid is null then
|
||||
return;
|
||||
end if;
|
||||
|
||||
superRoleId := findRoleId(superRole);
|
||||
subRoleId := findRoleId(subRole);
|
||||
|
||||
@@ -614,7 +703,7 @@ begin
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
|
||||
if isGranted(subRoleId, superRoleId) then
|
||||
raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
||||
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
end if;
|
||||
|
||||
insert
|
||||
@@ -629,6 +718,7 @@ declare
|
||||
superRoleId uuid;
|
||||
subRoleId uuid;
|
||||
begin
|
||||
if ( superRoleId is null ) then return; end if;
|
||||
superRoleId := findRoleId(superRole);
|
||||
if ( subRoleId is null ) then return; end if;
|
||||
subRoleId := findRoleId(subRole);
|
||||
@@ -637,7 +727,7 @@ begin
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
|
||||
if isGranted(subRoleId, superRoleId) then
|
||||
raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
||||
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
end if;
|
||||
|
||||
insert
|
||||
@@ -661,11 +751,39 @@ begin
|
||||
if (isGranted(superRoleId, subRoleId)) then
|
||||
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
|
||||
else
|
||||
raise exception 'cannot revoke role % (%) from % (% because it is not granted',
|
||||
raise exception 'cannot revoke role % (%) from % (%) because it is not granted',
|
||||
subRole, subRoleId, superRole, superRoleId;
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
create or replace procedure revokePermissionFromRole(permissionId UUID, superRole RbacRoleDescriptor)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
superRoleId uuid;
|
||||
permissionOp text;
|
||||
objectTable text;
|
||||
objectUuid uuid;
|
||||
begin
|
||||
superRoleId := findRoleId(superRole);
|
||||
|
||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||
perform assertReferenceType('permission (descendant)', permissionId, 'RbacPermission');
|
||||
|
||||
if (isGranted(superRoleId, permissionId)) then
|
||||
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = permissionId;
|
||||
else
|
||||
select p.op, o.objectTable, o.uuid
|
||||
from rbacGrants g
|
||||
join rbacPermission p on p.uuid=g.descendantUuid
|
||||
join rbacobject o on o.uuid=p.objectUuid
|
||||
where g.uuid=permissionId
|
||||
into permissionOp, objectTable, objectUuid;
|
||||
|
||||
raise exception 'cannot revoke permission % (% on %#% (%) from % (%)) because it is not granted',
|
||||
permissionId, permissionOp, objectTable, objectUuid, permissionId, superRole, superRoleId;
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
@@ -697,7 +815,7 @@ begin
|
||||
select descendantUuid
|
||||
from grants) as granted
|
||||
join RbacPermission perm
|
||||
on granted.descendantUuid = perm.uuid and perm.op in ('*', requiredOp)
|
||||
on granted.descendantUuid = perm.uuid and (requiredOp = 'SELECT' or perm.op = requiredOp)
|
||||
join RbacObject obj on obj.uuid = perm.objectUuid and obj.objectTable = forObjectTable
|
||||
limit maxObjects + 1;
|
||||
|
||||
@@ -789,6 +907,5 @@ do $$
|
||||
create role restricted;
|
||||
grant all privileges on all tables in schema public to restricted;
|
||||
end if;
|
||||
end $$
|
||||
end $$;
|
||||
--//
|
||||
|
@@ -30,24 +30,35 @@ begin
|
||||
insert
|
||||
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, userUuid, roleUuid, doAssume);
|
||||
-- TODO.spec: What should happen on mupltiple grants? What if options (doAssume) are not the same?
|
||||
-- TODO.spec: What should happen on multiple grants? What if options (doAssume) are not the same?
|
||||
-- Most powerful or latest grant wins? What about managed?
|
||||
-- on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
grantedByRoleIdName text;
|
||||
grantedRoleIdName text;
|
||||
begin
|
||||
perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Access to granted-by-role % forbidden for %', grantedByRoleUuid, currentSubjects();
|
||||
end if;
|
||||
assert grantedByRoleUuid is not null, 'grantedByRoleUuid must not be null';
|
||||
assert grantedRoleUuid is not null, 'grantedRoleUuid must not be null';
|
||||
assert userUuid is not null, 'userUuid must not be null';
|
||||
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
|
||||
raise exception '[403] Access to granted-by-role % (%) forbidden for % (%)',
|
||||
grantedByRoleIdName, grantedByRoleUuid, currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
if NOT isGranted(grantedByRoleUuid, grantedRoleUuid) then
|
||||
raise exception '[403] Access to granted role % forbidden for %', grantedRoleUuid, currentSubjects();
|
||||
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
|
||||
select roleIdName from rbacRole_ev where uuid=grantedRoleUuid into grantedRoleIdName;
|
||||
raise exception '[403] Access to granted role % (%) forbidden for % (%)',
|
||||
grantedRoleIdName, grantedRoleUuid, grantedByRoleIdName, grantedByRoleUuid;
|
||||
end if;
|
||||
|
||||
insert
|
||||
@@ -99,4 +110,17 @@ begin
|
||||
where g.ascendantUuid = userUuid and g.descendantUuid = grantedRoleUuid
|
||||
and g.grantedByRoleUuid = revokeRoleFromUser.grantedByRoleUuid;
|
||||
end; $$;
|
||||
--/
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-user-grant-REVOKE-PERMISSION-FROM-ROLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure revokePermissionFromRole(permissionUuid uuid, superRoleUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise INFO 'delete from RbacGrants where ascendantUuid = % and descendantUuid = %', superRoleUuid, permissionUuid;
|
||||
delete from RbacGrants as g
|
||||
where g.ascendantUuid = superRoleUuid and g.descendantUuid = permissionUuid;
|
||||
end; $$;
|
||||
--//
|
@@ -50,20 +50,23 @@ 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);
|
||||
|
||||
objectUuidToAssume = findObjectUuidByIdName(objectTableToAssume, objectNameToAssume);
|
||||
if objectUuidToAssume is null then
|
||||
raise exception '[401] object % cannot be found in table %', objectNameToAssume, objectTableToAssume;
|
||||
end if;
|
||||
|
||||
select uuid as roleuuidToAssume
|
||||
select uuid
|
||||
from RbacRole r
|
||||
where r.objectUuid = objectUuidToAssume
|
||||
and r.roleType = roleTypeToAssume
|
||||
into roleUuidToAssume;
|
||||
if roleUuidToAssume is null then
|
||||
raise exception '[403] role % not accessible for user %', roleName, currentSubjects();
|
||||
raise exception '[403] role % does not exist or is not accessible for user %', roleName, currentUser();
|
||||
end if;
|
||||
if not isGranted(currentUserUuid, roleUuidToAssume) then
|
||||
raise exception '[403] user % has no permission to assume role %', currentUser(), roleName;
|
||||
@@ -82,10 +85,10 @@ end; $$;
|
||||
This function will be overwritten by later changesets.
|
||||
*/
|
||||
create or replace procedure contextDefined(
|
||||
currentTask varchar,
|
||||
currentRequest varchar,
|
||||
currentUser varchar,
|
||||
assumedRoles varchar
|
||||
currentTask varchar(127),
|
||||
currentRequest text,
|
||||
currentUser varchar(63),
|
||||
assumedRoles varchar(1023)
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
@@ -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,12 +57,13 @@ 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,
|
||||
x.ascendantUuid as ascendantUuid,
|
||||
x.descendantUuid as descendantUuid,
|
||||
x.op as permOp, x.optablename as permOpTableName,
|
||||
x.assumed
|
||||
from (
|
||||
select g.uuid as grantUuid,
|
||||
@@ -70,17 +71,21 @@ 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,
|
||||
|
||||
coalesce(
|
||||
'role ' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || '.' || dr.roletype,
|
||||
'perm ' || dp.op || ' on ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
|
||||
( case
|
||||
when dro is not null
|
||||
then ('role:' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || ':' || dr.roletype)
|
||||
when dp.op = 'INSERT'
|
||||
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
|
||||
from rbacgrants as g
|
||||
dro.objectTable, dro.uuid,
|
||||
dp.op, dp.optablename
|
||||
from rbacgrants as g
|
||||
|
||||
left outer join rbacrole as ar on ar.uuid = g.ascendantUuid
|
||||
left outer join rbacobject as aro on aro.uuid = ar.objectuuid
|
||||
@@ -110,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 (
|
||||
@@ -322,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
|
||||
@@ -337,11 +342,9 @@ grant all privileges on RbacOwnGrantedPermissions_rv to ${HSADMINNG_POSTGRES_RES
|
||||
/*
|
||||
Returns all permissions granted to the given user,
|
||||
which are also visible to the current user or assumed roles.
|
||||
|
||||
|
||||
*/
|
||||
create or replace function grantedPermissions(targetUserUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, objectTable varchar, objectIdName varchar, objectUuid uuid)
|
||||
*/
|
||||
create or replace function grantedPermissionsRaw(targetUserUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@@ -356,12 +359,14 @@ begin
|
||||
|
||||
return query select
|
||||
xp.roleUuid,
|
||||
(xp.roleObjectTable || '#' || xp.roleObjectIdName || '.' || xp.roleType) as roleName,
|
||||
xp.permissionUuid, xp.op, xp.permissionObjectTable, xp.permissionObjectIdName, xp.permissionObjectUuid
|
||||
(xp.roleObjectTable || '#' || xp.roleObjectIdName || ':' || xp.roleType) as roleName,
|
||||
xp.permissionUuid, xp.op, xp.opTableName,
|
||||
xp.permissionObjectTable, xp.permissionObjectIdName, xp.permissionObjectUuid
|
||||
from (select
|
||||
r.uuid as roleUuid, r.roletype, ro.objectTable as roleObjectTable,
|
||||
findIdNameByObjectUuid(ro.objectTable, ro.uuid) as roleObjectIdName,
|
||||
p.uuid as permissionUuid, p.op, po.objecttable as permissionObjectTable,
|
||||
p.uuid as permissionUuid, p.op, p.opTableName,
|
||||
po.objecttable as permissionObjectTable,
|
||||
findIdNameByObjectUuid(po.objectTable, po.uuid) as permissionObjectIdName,
|
||||
po.uuid as permissionObjectUuid
|
||||
from queryPermissionsGrantedToSubjectId( targetUserUuid) as p
|
||||
@@ -373,4 +378,15 @@ begin
|
||||
) xp;
|
||||
-- @formatter:on
|
||||
end; $$;
|
||||
|
||||
create or replace function grantedPermissions(targetUserUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select * from grantedPermissionsRaw(targetUserUuid)
|
||||
union all
|
||||
select roleUuid, roleName, permissionUuid, 'SELECT'::RbacOp, opTableName, objectTable, objectIdName, objectUuid
|
||||
from grantedPermissionsRaw(targetUserUuid)
|
||||
where op <> 'SELECT'::RbacOp;
|
||||
$$;
|
||||
--//
|
@@ -0,0 +1,67 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- =================================================================
|
||||
-- CREATE ROLE
|
||||
--changeset rbac-role-builder-create-role:1 endDelimiter:--//
|
||||
-- -----------------------------------------------------------------
|
||||
|
||||
create or replace function createRoleWithGrants(
|
||||
roleDescriptor RbacRoleDescriptor,
|
||||
permissions RbacOp[] = array[]::RbacOp[],
|
||||
incomingSuperRoles RbacRoleDescriptor[] = array[]::RbacRoleDescriptor[],
|
||||
outgoingSubRoles RbacRoleDescriptor[] = array[]::RbacRoleDescriptor[],
|
||||
userUuids uuid[] = array[]::uuid[],
|
||||
grantedByRole RbacRoleDescriptor = null
|
||||
)
|
||||
returns uuid
|
||||
called on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
roleUuid uuid;
|
||||
permission RbacOp;
|
||||
permissionUuid uuid;
|
||||
subRoleDesc RbacRoleDescriptor;
|
||||
superRoleDesc RbacRoleDescriptor;
|
||||
subRoleUuid uuid;
|
||||
superRoleUuid uuid;
|
||||
userUuid uuid;
|
||||
userGrantsByRoleUuid uuid;
|
||||
begin
|
||||
roleUuid := createRole(roleDescriptor);
|
||||
|
||||
foreach permission in array permissions
|
||||
loop
|
||||
permissionUuid := createPermission(roleDescriptor.objectuuid, permission);
|
||||
call grantPermissionToRole(permissionUuid, roleUuid);
|
||||
end loop;
|
||||
|
||||
foreach superRoleDesc in array array_remove(incomingSuperRoles, null)
|
||||
loop
|
||||
superRoleUuid := getRoleId(superRoleDesc);
|
||||
call grantRoleToRole(roleUuid, superRoleUuid, superRoleDesc.assumed);
|
||||
end loop;
|
||||
|
||||
foreach subRoleDesc in array array_remove(outgoingSubRoles, null)
|
||||
loop
|
||||
subRoleUuid := getRoleId(subRoleDesc);
|
||||
call grantRoleToRole(subRoleUuid, roleUuid, subRoleDesc.assumed);
|
||||
end loop;
|
||||
|
||||
if cardinality(userUuids) > 0 then
|
||||
-- direct grants to users need a grantedByRole which can revoke the grant
|
||||
if grantedByRole is null then
|
||||
userGrantsByRoleUuid := roleUuid; -- TODO.spec: or do we want to require an explicit userGrantsByRoleUuid?
|
||||
else
|
||||
userGrantsByRoleUuid := getRoleId(grantedByRole);
|
||||
end if;
|
||||
foreach userUuid in array userUuids
|
||||
loop
|
||||
call grantRoleToUserUnchecked(userGrantsByRoleUuid, roleUuid, userUuid);
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
return roleUuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
@@ -13,8 +13,7 @@ declare
|
||||
begin
|
||||
createInsertTriggerSQL = format($sql$
|
||||
create trigger createRbacObjectFor_%s_Trigger
|
||||
before insert
|
||||
on %s
|
||||
before insert on %s
|
||||
for each row
|
||||
execute procedure insertRelatedRbacObject();
|
||||
$sql$, targetTable, targetTable);
|
||||
@@ -36,50 +35,59 @@ end; $$;
|
||||
--changeset rbac-generators-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure generateRbacRoleDescriptors(prefix text, targetTable text)
|
||||
create procedure generateRbacRoleDescriptors(prefix text, targetTable text)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sql text;
|
||||
begin
|
||||
sql = format($sql$
|
||||
create or replace function %1$sOwner(entity %2$s)
|
||||
create or replace function %1$sOwner(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'owner');
|
||||
return roleDescriptor('%2$s', entity.uuid, 'OWNER', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sAdmin(entity %2$s)
|
||||
create or replace function %1$sAdmin(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'admin');
|
||||
return roleDescriptor('%2$s', entity.uuid, 'ADMIN', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sAgent(entity %2$s)
|
||||
create or replace function %1$sAgent(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'agent');
|
||||
return roleDescriptor('%2$s', entity.uuid, 'AGENT', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sTenant(entity %2$s)
|
||||
create or replace function %1$sTenant(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'tenant');
|
||||
return roleDescriptor('%2$s', entity.uuid, 'TENANT', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sGuest(entity %2$s)
|
||||
-- TODO: remove guest role
|
||||
create or replace function %1$sGuest(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'guest');
|
||||
return roleDescriptor('%2$s', entity.uuid, 'GUEST', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sReferrer(entity %2$s)
|
||||
returns RbacRoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'REFERRER');
|
||||
end; $f$;
|
||||
|
||||
$sql$, prefix, targetTable);
|
||||
@@ -92,7 +100,7 @@ end; $$;
|
||||
--changeset rbac-generators-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure generateRbacIdentityView(targetTable text, idNameExpression text)
|
||||
create or replace procedure generateRbacIdentityViewFromQuery(targetTable text, sqlQuery text)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sql text;
|
||||
@@ -101,11 +109,9 @@ begin
|
||||
|
||||
-- create a view to the target main table which maps an idName to the objectUuid
|
||||
sql = format($sql$
|
||||
create or replace view %1$s_iv as
|
||||
select target.uuid, cleanIdentifier(%2$s) as idName
|
||||
from %1$s as target;
|
||||
create or replace view %1$s_iv as %2$s;
|
||||
grant all privileges on %1$s_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
$sql$, targetTable, idNameExpression);
|
||||
$sql$, targetTable, sqlQuery);
|
||||
execute sql;
|
||||
|
||||
-- creates a function which maps an idName to the objectUuid
|
||||
@@ -130,6 +136,20 @@ begin
|
||||
$sql$, targetTable);
|
||||
execute sql;
|
||||
end; $$;
|
||||
|
||||
create or replace procedure generateRbacIdentityViewFromProjection(targetTable text, sqlProjection text)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sqlQuery text;
|
||||
begin
|
||||
targettable := lower(targettable);
|
||||
|
||||
sqlQuery = format($sql$
|
||||
select target.uuid, cleanIdentifier(%2$s) as idName
|
||||
from %1$s as target;
|
||||
$sql$, targetTable, sqlProjection);
|
||||
call generateRbacIdentityViewFromQuery(targetTable, sqlQuery);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
@@ -137,21 +157,25 @@ end; $$;
|
||||
--changeset rbac-generators-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null)
|
||||
create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null, columnNames text = '*')
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sql text;
|
||||
newColumns text;
|
||||
begin
|
||||
targetTable := lower(targetTable);
|
||||
if columnNames = '*' then
|
||||
columnNames := columnsNames(targetTable);
|
||||
end if;
|
||||
|
||||
/*
|
||||
Creates a restricted view based on the 'view' permission of the current subject.
|
||||
Creates a restricted view based on the 'SELECT' permission of the current subject.
|
||||
*/
|
||||
sql := format($sql$
|
||||
set session session authorization default;
|
||||
create view %1$s_rv as
|
||||
with accessibleObjects as (
|
||||
select queryAccessibleObjectUuidsOfSubjectIds('view', '%1$s', currentSubjectsUuids())
|
||||
select queryAccessibleObjectUuidsOfSubjectIds('SELECT', '%1$s', currentSubjectsUuids())
|
||||
)
|
||||
select target.*
|
||||
from %1$s as target
|
||||
@@ -164,20 +188,21 @@ begin
|
||||
/**
|
||||
Instead of insert trigger function for the restricted view.
|
||||
*/
|
||||
newColumns := 'new.' || replace(columnNames, ',', ', new.');
|
||||
sql := format($sql$
|
||||
create or replace function %1$sInsert()
|
||||
returns trigger
|
||||
language plpgsql as $f$
|
||||
declare
|
||||
newTargetRow %1$s;
|
||||
begin
|
||||
insert
|
||||
into %1$s
|
||||
values (new.*)
|
||||
returning * into newTargetRow;
|
||||
return newTargetRow;
|
||||
end; $f$;
|
||||
$sql$, targetTable);
|
||||
create or replace function %1$sInsert()
|
||||
returns trigger
|
||||
language plpgsql as $f$
|
||||
declare
|
||||
newTargetRow %1$s;
|
||||
begin
|
||||
insert
|
||||
into %1$s (%2$s)
|
||||
values (%3$s)
|
||||
returning * into newTargetRow;
|
||||
return newTargetRow;
|
||||
end; $f$;
|
||||
$sql$, targetTable, columnNames, newColumns);
|
||||
execute sql;
|
||||
|
||||
/*
|
||||
@@ -200,7 +225,7 @@ begin
|
||||
returns trigger
|
||||
language plpgsql as $f$
|
||||
begin
|
||||
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('delete', '%1$s', currentSubjectsUuids())) then
|
||||
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('DELETE', '%1$s', currentSubjectsUuids())) then
|
||||
delete from %1$s p where p.uuid = old.uuid;
|
||||
return old;
|
||||
end if;
|
||||
@@ -223,7 +248,7 @@ begin
|
||||
|
||||
/**
|
||||
Instead of update trigger function for the restricted view
|
||||
based on the 'edit' permission of the current subject.
|
||||
based on the 'UPDATE' permission of the current subject.
|
||||
*/
|
||||
if columnUpdates is not null then
|
||||
sql := format($sql$
|
||||
@@ -231,7 +256,7 @@ begin
|
||||
returns trigger
|
||||
language plpgsql as $f$
|
||||
begin
|
||||
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('edit', '%1$s', currentSubjectsUuids())) then
|
||||
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('UPDATE', '%1$s', currentSubjectsUuids())) then
|
||||
update %1$s
|
||||
set %2$s
|
||||
where uuid = old.uuid;
|
@@ -22,6 +22,19 @@ grant select on global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-IS-GLOBAL-ADMIN:1 endDelimiter:--//
|
||||
-- ------------------------------------------------------------------
|
||||
|
||||
create or replace function isGlobalAdmin()
|
||||
returns boolean
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return isGranted(currentSubjectsUuids(), findRoleId(globalAdmin()));
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-HAS-GLOBAL-PERMISSION:1 endDelimiter:--//
|
||||
-- ------------------------------------------------------------------
|
||||
@@ -96,18 +109,41 @@ commit;
|
||||
/*
|
||||
A global administrator role.
|
||||
*/
|
||||
create or replace function globalAdmin()
|
||||
create or replace function globalAdmin(assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType;
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'ADMIN'::RbacRoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating global admin role', null, null, null);
|
||||
select createRole(globalAdmin());
|
||||
call defineContext('creating role:global#global:ADMIN', null, null, null);
|
||||
select createRole(globalAdmin());
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-GUEST-ROLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A global guest role.
|
||||
*/
|
||||
create or replace function globalGuest(assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'GUEST'::RbacRoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating role:global#global:guest', null, null, null);
|
||||
select createRole(globalGuest());
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-ADMIN-USERS:1 context:dev,tc endDelimiter:--//
|
@@ -1,145 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_customer');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testCustomer', 'test_customer');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles and their assignments for a new customer for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function createRbacRolesForTestCustomer()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
testCustomerOwnerUuid uuid;
|
||||
customerAdminUuid uuid;
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
-- the owner role with full access for Hostsharing administrators
|
||||
testCustomerOwnerUuid = createRoleWithGrants(
|
||||
testCustomerOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
-- the admin role for the customer's admins, who can view and add products
|
||||
customerAdminUuid = createRoleWithGrants(
|
||||
testCustomerAdmin(NEW),
|
||||
permissions => array['view', 'add-package'],
|
||||
-- NO auto assume for customer owner to avoid exploding permissions for administrators
|
||||
userUuids => array[getRbacUserId(NEW.adminUserName, 'create')], -- implicitly ignored if null
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
-- allow the customer owner role (thus administrators) to assume the customer admin role
|
||||
call grantRoleToRole(customerAdminUuid, testCustomerOwnerUuid, false);
|
||||
|
||||
-- the tenant role which later can be used by owners+admins of sub-objects
|
||||
perform createRoleWithGrants(
|
||||
testCustomerTenant(NEW),
|
||||
permissions => array['view']
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
|
||||
drop trigger if exists createRbacRolesForTestCustomer_Trigger on test_customer;
|
||||
create trigger createRbacRolesForTestCustomer_Trigger
|
||||
after insert
|
||||
on test_customer
|
||||
for each row
|
||||
execute procedure createRbacRolesForTestCustomer();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('test_customer', $idName$
|
||||
target.prefix
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_customer', 'target.prefix',
|
||||
$updates$
|
||||
reference = new.reference,
|
||||
prefix = new.prefix,
|
||||
adminUserName = new.adminUserName
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-ADD-CUSTOMER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for add-customer and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global add-customer permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['add-customer']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addTestCustomerNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] add-customer not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to add a new customer.
|
||||
*/
|
||||
create trigger test_customer_insert_trigger
|
||||
before insert
|
||||
on test_customer
|
||||
for each row
|
||||
when ( not hasGlobalPermission('add-customer') )
|
||||
execute procedure addTestCustomerNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,109 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_package');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testPackage', 'test_package');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the roles and their assignments for a new package for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
create or replace function createRbacRolesForTestPackage()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
parentCustomer test_customer;
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from test_customer as c where c.uuid = NEW.customerUuid into parentCustomer;
|
||||
|
||||
-- an owner role is created and assigned to the customer's admin role
|
||||
perform createRoleWithGrants(
|
||||
testPackageOwner(NEW),
|
||||
permissions => array ['*'],
|
||||
incomingSuperRoles => array[testCustomerAdmin(parentCustomer)]
|
||||
);
|
||||
|
||||
-- an owner role is created and assigned to the package owner role
|
||||
perform createRoleWithGrants(
|
||||
testPackageAdmin(NEW),
|
||||
permissions => array ['add-domain'],
|
||||
incomingSuperRoles => array[testPackageOwner(NEW)]
|
||||
);
|
||||
|
||||
-- and a package tenant role is created and assigned to the package admin as well
|
||||
perform createRoleWithGrants(
|
||||
testPackageTenant(NEW),
|
||||
permissions => array['view'],
|
||||
incomingsuperroles => array[testPackageAdmin(NEW)],
|
||||
outgoingSubRoles => array[testCustomerTenant(parentCustomer)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new package.
|
||||
*/
|
||||
|
||||
create trigger createRbacRolesForTestPackage_Trigger
|
||||
after insert
|
||||
on test_package
|
||||
for each row
|
||||
execute procedure createRbacRolesForTestPackage();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('test_package', 'target.name');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a view to the customer main table which maps the identifying name
|
||||
(in this case, the prefix) to the objectUuid.
|
||||
*/
|
||||
-- drop view if exists test_package_rv;
|
||||
-- create or replace view test_package_rv as
|
||||
-- select target.*
|
||||
-- from test_package as target
|
||||
-- where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'test_package', currentSubjectsUuids()))
|
||||
-- order by target.name;
|
||||
-- grant all privileges on test_package_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
|
||||
call generateRbacRestrictedView('test_package', 'target.name',
|
||||
$updates$
|
||||
version = new.version,
|
||||
customerUuid = new.customerUuid,
|
||||
name = new.name,
|
||||
description = new.description
|
||||
$updates$);
|
||||
|
||||
--//
|
||||
|
||||
|
@@ -1,117 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_domain');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testDomain', 'test_domain');
|
||||
|
||||
create or replace function createTestDomainTenantRoleIfNotExists(domain test_domain)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
domainTenantRoleDesc RbacRoleDescriptor;
|
||||
domainTenantRoleUuid uuid;
|
||||
begin
|
||||
domainTenantRoleDesc = testdomainTenant(domain);
|
||||
domainTenantRoleUuid = findRoleId(domainTenantRoleDesc);
|
||||
if domainTenantRoleUuid is not null then
|
||||
return domainTenantRoleUuid;
|
||||
end if;
|
||||
|
||||
return createRoleWithGrants(
|
||||
domainTenantRoleDesc,
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[testdomainAdmin(domain)]
|
||||
);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the roles and their assignments for a new domain for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function createRbacRulesForTestDomain()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
parentPackage test_package;
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from test_package where uuid = NEW.packageUuid into parentPackage;
|
||||
|
||||
-- an owner role is created and assigned to the package's admin group
|
||||
perform createRoleWithGrants(
|
||||
testDomainOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[testPackageAdmin(parentPackage)]
|
||||
);
|
||||
|
||||
-- and a domain admin role is created and assigned to the domain owner as well
|
||||
perform createRoleWithGrants(
|
||||
testDomainAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[testDomainOwner(NEW)],
|
||||
outgoingSubRoles => array[testPackageTenant(parentPackage)]
|
||||
);
|
||||
|
||||
-- a tenent role is only created on demand
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new domain.
|
||||
*/
|
||||
drop trigger if exists createRbacRulesForTestDomain_Trigger on test_domain;
|
||||
create trigger createRbacRulesForTestDomain_Trigger
|
||||
after insert
|
||||
on test_domain
|
||||
for each row
|
||||
execute procedure createRbacRulesForTestDomain();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('test_domain', $idName$
|
||||
target.name
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a view to the customer main table which maps the identifying name
|
||||
(in this case, the prefix) to the objectUuid.
|
||||
*/
|
||||
drop view if exists test_domain_rv;
|
||||
create or replace view test_domain_rv as
|
||||
select target.*
|
||||
from test_domain as target
|
||||
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'domain', currentSubjectsUuids()));
|
||||
grant all privileges on test_domain_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
@@ -0,0 +1,45 @@
|
||||
### rbac customer
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph customer["`**customer**`"]
|
||||
direction TB
|
||||
style customer fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph customer:roles[ ]
|
||||
style customer:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:customer:OWNER[[customer:OWNER]]
|
||||
role:customer:ADMIN[[customer:ADMIN]]
|
||||
role:customer:TENANT[[customer:TENANT]]
|
||||
end
|
||||
|
||||
subgraph customer:permissions[ ]
|
||||
style customer:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:customer:INSERT{{customer:INSERT}}
|
||||
perm:customer:DELETE{{customer:DELETE}}
|
||||
perm:customer:UPDATE{{customer:UPDATE}}
|
||||
perm:customer:SELECT{{customer:SELECT}}
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==>|XX| role:customer:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN ==>|XX| role:customer:OWNER
|
||||
role:customer:OWNER ==> role:customer:ADMIN
|
||||
role:customer:ADMIN ==> role:customer:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:ADMIN ==> perm:customer:INSERT
|
||||
role:customer:OWNER ==> perm:customer:DELETE
|
||||
role:customer:ADMIN ==> perm:customer:UPDATE
|
||||
role:customer:TENANT ==> perm:customer:SELECT
|
||||
|
||||
```
|
163
src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql
Normal file
163
src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql
Normal file
@@ -0,0 +1,163 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_customer');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testCustomer', 'test_customer');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForTestCustomer(
|
||||
NEW test_customer
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testCustomerOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN(unassumed())],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testCustomerADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[testCustomerOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testCustomerTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testCustomerADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new test_customer row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForTestCustomer_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForTestCustomer(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForTestCustomer_tg
|
||||
after insert on test_customer
|
||||
for each row
|
||||
execute procedure insertTriggerForTestCustomer_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO test_customer permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_customer permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_customer'),
|
||||
globalADMIN());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds test_customer INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function test_customer_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_customer'),
|
||||
globalADMIN());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_test_customer_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure test_customer_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_customer,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function test_customer_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into test_customer not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_customer_insert_permission_check_tg
|
||||
before insert on test_customer
|
||||
for each row
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure test_customer_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('test_customer',
|
||||
$idName$
|
||||
prefix
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_customer',
|
||||
$orderBy$
|
||||
reference
|
||||
$orderBy$,
|
||||
$updates$
|
||||
reference = new.reference,
|
||||
prefix = new.prefix,
|
||||
adminUserName = new.adminUserName
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -28,17 +28,28 @@ declare
|
||||
currentTask varchar;
|
||||
custRowId uuid;
|
||||
custAdminName varchar;
|
||||
custAdminUuid uuid;
|
||||
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();
|
||||
custAdminName = 'customer-admin@' || custPrefix || '.example.com';
|
||||
custAdminUuid = createRbacUser(custAdminName);
|
||||
|
||||
insert
|
||||
into test_customer (reference, prefix, adminUserName)
|
||||
values (custReference, custPrefix, custAdminName);
|
||||
|
||||
select * into newCust
|
||||
from test_customer where reference=custReference;
|
||||
call grantRoleToUser(
|
||||
getRoleId(testCustomerOwner(newCust)),
|
||||
getRoleId(testCustomerAdmin(newCust)),
|
||||
custAdminUuid,
|
||||
true);
|
||||
end; $$;
|
||||
--//
|
||||
|
@@ -0,0 +1,59 @@
|
||||
### rbac package
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph package["`**package**`"]
|
||||
direction TB
|
||||
style package fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph package:roles[ ]
|
||||
style package:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:package:OWNER[[package:OWNER]]
|
||||
role:package:ADMIN[[package:ADMIN]]
|
||||
role:package:TENANT[[package:TENANT]]
|
||||
end
|
||||
|
||||
subgraph package:permissions[ ]
|
||||
style package:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:package:INSERT{{package:INSERT}}
|
||||
perm:package:DELETE{{package:DELETE}}
|
||||
perm:package:UPDATE{{package:UPDATE}}
|
||||
perm:package:SELECT{{package:SELECT}}
|
||||
end
|
||||
end
|
||||
|
||||
subgraph customer["`**customer**`"]
|
||||
direction TB
|
||||
style customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph customer:roles[ ]
|
||||
style customer:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:customer:OWNER[[customer:OWNER]]
|
||||
role:customer:ADMIN[[customer:ADMIN]]
|
||||
role:customer:TENANT[[customer:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.->|XX| role:customer:OWNER
|
||||
role:customer:OWNER -.-> role:customer:ADMIN
|
||||
role:customer:ADMIN -.-> role:customer:TENANT
|
||||
role:customer:ADMIN ==> role:package:OWNER
|
||||
role:package:OWNER ==> role:package:ADMIN
|
||||
role:package:ADMIN ==> role:package:TENANT
|
||||
role:package:TENANT ==> role:customer:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:customer:ADMIN ==> perm:package:INSERT
|
||||
role:package:OWNER ==> perm:package:DELETE
|
||||
role:package:OWNER ==> perm:package:UPDATE
|
||||
role:package:TENANT ==> perm:package:SELECT
|
||||
|
||||
```
|
@@ -0,0 +1,230 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_package');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testPackage', 'test_package');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForTestPackage(
|
||||
NEW test_package
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newCustomer test_customer;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM test_customer WHERE uuid = NEW.customerUuid INTO newCustomer;
|
||||
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s', NEW.customerUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testPackageOWNER(NEW),
|
||||
permissions => array['DELETE', 'UPDATE'],
|
||||
incomingSuperRoles => array[testCustomerADMIN(newCustomer)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testPackageADMIN(NEW),
|
||||
incomingSuperRoles => array[testPackageOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testPackageTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testPackageADMIN(NEW)],
|
||||
outgoingSubRoles => array[testCustomerTENANT(newCustomer)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new test_package row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForTestPackage_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForTestPackage(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForTestPackage_tg
|
||||
after insert on test_package
|
||||
for each row
|
||||
execute procedure insertTriggerForTestPackage_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-update-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||
*/
|
||||
|
||||
create or replace procedure updateRbacRulesForTestPackage(
|
||||
OLD test_package,
|
||||
NEW test_package
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
oldCustomer test_customer;
|
||||
newCustomer test_customer;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM test_customer WHERE uuid = OLD.customerUuid INTO oldCustomer;
|
||||
assert oldCustomer.uuid is not null, format('oldCustomer must not be null for OLD.customerUuid = %s', OLD.customerUuid);
|
||||
|
||||
SELECT * FROM test_customer WHERE uuid = NEW.customerUuid INTO newCustomer;
|
||||
assert newCustomer.uuid is not null, format('newCustomer must not be null for NEW.customerUuid = %s', NEW.customerUuid);
|
||||
|
||||
|
||||
if NEW.customerUuid <> OLD.customerUuid then
|
||||
|
||||
call revokeRoleFromRole(testPackageOWNER(OLD), testCustomerADMIN(oldCustomer));
|
||||
call grantRoleToRole(testPackageOWNER(NEW), testCustomerADMIN(newCustomer));
|
||||
|
||||
call revokeRoleFromRole(testCustomerTENANT(oldCustomer), testPackageTENANT(OLD));
|
||||
call grantRoleToRole(testCustomerTENANT(newCustomer), testPackageTENANT(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to re-wire the grant structure for a new test_package row.
|
||||
*/
|
||||
|
||||
create or replace function updateTriggerForTestPackage_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call updateRbacRulesForTestPackage(OLD, NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger updateTriggerForTestPackage_tg
|
||||
after update on test_package
|
||||
for each row
|
||||
execute procedure updateTriggerForTestPackage_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO test_package permissions for the related test_customer rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row test_customer;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_package permissions for the related test_customer rows');
|
||||
|
||||
FOR row IN SELECT * FROM test_customer
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_package'),
|
||||
testCustomerADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds test_package INSERT permission to specified role of new test_customer rows.
|
||||
*/
|
||||
create or replace function test_package_test_customer_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_package'),
|
||||
testCustomerADMIN(NEW));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_test_package_test_customer_insert_tg
|
||||
after insert on test_customer
|
||||
for each row
|
||||
execute procedure test_package_test_customer_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_package,
|
||||
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 test_package_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into test_package not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_package_insert_permission_check_tg
|
||||
before insert on test_package
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.customerUuid, 'INSERT', 'test_package') )
|
||||
execute procedure test_package_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('test_package',
|
||||
$idName$
|
||||
name
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_package',
|
||||
$orderBy$
|
||||
name
|
||||
$orderBy$,
|
||||
$updates$
|
||||
version = new.version,
|
||||
customerUuid = new.customerUuid,
|
||||
description = new.description
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -25,8 +25,8 @@ begin
|
||||
cust.uuid;
|
||||
|
||||
custAdminUser = 'customer-admin@' || cust.prefix || '.example.com';
|
||||
custAdminRole = 'test_customer#' || cust.prefix || '.admin';
|
||||
call defineContext(currentTask, null, custAdminUser, custAdminRole);
|
||||
custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN';
|
||||
call defineContext(currentTask, null, 'superuser-fran@hostsharing.net', custAdminRole);
|
||||
raise notice 'task: % by % as %', currentTask, custAdminUser, custAdminRole;
|
||||
|
||||
insert
|
||||
@@ -35,7 +35,7 @@ begin
|
||||
returning * into pac;
|
||||
|
||||
call grantRoleToUser(
|
||||
getRoleId(testCustomerAdmin(cust), 'fail'),
|
||||
getRoleId(testCustomerAdmin(cust)),
|
||||
findRoleId(testPackageAdmin(pac)),
|
||||
createRbacUser('pac-admin-' || pacName || '@' || cust.prefix || '.example.com'),
|
||||
true);
|
@@ -0,0 +1,75 @@
|
||||
### rbac domain
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
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["`**package**`"]
|
||||
direction TB
|
||||
style package fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
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]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph domain["`**domain**`"]
|
||||
direction TB
|
||||
style domain fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph domain:roles[ ]
|
||||
style domain:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:domain:OWNER[[domain:OWNER]]
|
||||
role:domain:ADMIN[[domain:ADMIN]]
|
||||
end
|
||||
|
||||
subgraph domain:permissions[ ]
|
||||
style domain:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:domain:INSERT{{domain:INSERT}}
|
||||
perm:domain:DELETE{{domain:DELETE}}
|
||||
perm:domain:UPDATE{{domain:UPDATE}}
|
||||
perm:domain:SELECT{{domain:SELECT}}
|
||||
end
|
||||
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
|
||||
|
||||
%% 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
|
||||
|
||||
```
|
@@ -0,0 +1,229 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_domain');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testDomain', 'test_domain');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForTestDomain(
|
||||
NEW test_domain
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newPackage test_package;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM test_package WHERE uuid = NEW.packageUuid INTO newPackage;
|
||||
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s', NEW.packageUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testDomainOWNER(NEW),
|
||||
permissions => array['DELETE', 'UPDATE'],
|
||||
incomingSuperRoles => array[testPackageADMIN(newPackage)],
|
||||
outgoingSubRoles => array[testPackageTENANT(newPackage)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
testDomainADMIN(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testDomainOWNER(NEW)],
|
||||
outgoingSubRoles => array[testPackageTENANT(newPackage)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new test_domain row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForTestDomain_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForTestDomain(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForTestDomain_tg
|
||||
after insert on test_domain
|
||||
for each row
|
||||
execute procedure insertTriggerForTestDomain_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-update-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||
*/
|
||||
|
||||
create or replace procedure updateRbacRulesForTestDomain(
|
||||
OLD test_domain,
|
||||
NEW test_domain
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
oldPackage test_package;
|
||||
newPackage test_package;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM test_package WHERE uuid = OLD.packageUuid INTO oldPackage;
|
||||
assert oldPackage.uuid is not null, format('oldPackage must not be null for OLD.packageUuid = %s', OLD.packageUuid);
|
||||
|
||||
SELECT * FROM test_package WHERE uuid = NEW.packageUuid INTO newPackage;
|
||||
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s', NEW.packageUuid);
|
||||
|
||||
|
||||
if NEW.packageUuid <> OLD.packageUuid then
|
||||
|
||||
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), testDomainADMIN(OLD));
|
||||
call grantRoleToRole(testPackageTENANT(newPackage), testDomainADMIN(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to re-wire the grant structure for a new test_domain row.
|
||||
*/
|
||||
|
||||
create or replace function updateTriggerForTestDomain_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call updateRbacRulesForTestDomain(OLD, NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger updateTriggerForTestDomain_tg
|
||||
after update on test_domain
|
||||
for each row
|
||||
execute procedure updateTriggerForTestDomain_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO test_domain permissions for the related test_package rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row test_package;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_domain permissions for the related test_package rows');
|
||||
|
||||
FOR row IN SELECT * FROM test_package
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_domain'),
|
||||
testPackageADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds test_domain INSERT permission to specified role of new test_package rows.
|
||||
*/
|
||||
create or replace function test_domain_test_package_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_domain'),
|
||||
testPackageADMIN(NEW));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_test_domain_test_package_insert_tg
|
||||
after insert on test_package
|
||||
for each row
|
||||
execute procedure test_domain_test_package_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_domain,
|
||||
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 test_domain_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into test_domain not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_domain_insert_permission_check_tg
|
||||
before insert on test_domain
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.packageUuid, 'INSERT', 'test_domain') )
|
||||
execute procedure test_domain_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('test_domain',
|
||||
$idName$
|
||||
name
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_domain',
|
||||
$orderBy$
|
||||
name
|
||||
$orderBy$,
|
||||
$updates$
|
||||
version = new.version,
|
||||
packageUuid = new.packageUuid,
|
||||
description = new.description
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -1,141 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_contact');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles and their assignments for a new contact for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function createRbacRolesForHsOfficeContact()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()],
|
||||
userUuids => array[currentUserUuid()],
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[hsOfficeContactOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficeContactAdmin(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[hsOfficeContactTenant(NEW)]
|
||||
);
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
|
||||
create trigger createRbacRolesForHsOfficeContact_Trigger
|
||||
after insert
|
||||
on hs_office_contact
|
||||
for each row
|
||||
execute procedure createRbacRolesForHsOfficeContact();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityView('hs_office_contact', $idName$
|
||||
target.label
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_contact', 'target.label',
|
||||
$updates$
|
||||
label = new.label,
|
||||
postalAddress = new.postalAddress,
|
||||
emailAddresses = new.emailAddresses,
|
||||
phoneNumbers = new.phoneNumbers
|
||||
$updates$);
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-NEW-CONTACT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-contact and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid;
|
||||
begin
|
||||
call defineContext('granting global new-contact permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-contact']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeContactNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-contact not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_contact_insert_trigger
|
||||
before insert
|
||||
on hs_office_contact
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new contacts
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeContactNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,139 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_person');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the roles and their assignments for a new person for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
create or replace function createRbacRolesForHsOfficePerson()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()],
|
||||
userUuids => array[currentUserUuid()],
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
-- TODO: who is admin? the person itself? is it allowed for the person itself or a representative to edit the data?
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficePersonAdmin(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[hsOfficePersonTenant(NEW)]
|
||||
);
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
|
||||
create trigger createRbacRolesForHsOfficePerson_Trigger
|
||||
after insert
|
||||
on hs_office_person
|
||||
for each row
|
||||
execute procedure createRbacRolesForHsOfficePerson();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_person', $idName$
|
||||
concat(target.tradeName, target.familyName, target.givenName)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_person', 'concat(target.tradeName, target.familyName, target.givenName)',
|
||||
$updates$
|
||||
personType = new.personType,
|
||||
tradeName = new.tradeName,
|
||||
givenName = new.givenName,
|
||||
familyName = new.familyName
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-NEW-PERSON:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-person and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-person permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-person']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficePersonNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-person not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_person_insert_trigger
|
||||
before insert
|
||||
on hs_office_person
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new persons
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficePersonNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,36 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficeRelationshipType AS ENUM (
|
||||
'UNKNOWN',
|
||||
'PARTNER',
|
||||
'EX_PARTNER',
|
||||
'REPRESENTATIVE',
|
||||
'VIP_CONTACT',
|
||||
'ACCOUNTING',
|
||||
'OPERATIONS',
|
||||
'SUBSCRIBER');
|
||||
|
||||
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT;
|
||||
|
||||
create table if not exists hs_office_relationship
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
|
||||
relAnchorUuid uuid not null references hs_office_person(uuid),
|
||||
relHolderUuid uuid not null references hs_office_person(uuid),
|
||||
contactUuid uuid references hs_office_contact(uuid),
|
||||
relType HsOfficeRelationshipType not null,
|
||||
relMark varchar(24)
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_relationship');
|
||||
--//
|
@@ -1,192 +0,0 @@
|
||||
### hs_office_relationship RBAC
|
||||
|
||||
```mermaid
|
||||
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeContact
|
||||
direction TB
|
||||
style hsOfficeContact fill:#eee
|
||||
|
||||
role:hsOfficeContact.admin[contact.admin]
|
||||
--> role:hsOfficeContact.tenant[contact.tenant]
|
||||
--> role:hsOfficeContact.guest[contact.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficePerson
|
||||
direction TB
|
||||
style hsOfficePerson fill:#eee
|
||||
|
||||
role:hsOfficePerson.admin[person.admin]
|
||||
--> role:hsOfficePerson.tenant[person.tenant]
|
||||
--> role:hsOfficePerson.guest[person.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficeRelationship
|
||||
|
||||
role:hsOfficePerson#relAnchor.admin[person#anchor.admin]
|
||||
--- role:hsOfficePerson.admin
|
||||
|
||||
role:hsOfficeRelationship.owner[relationship.owner]
|
||||
%% permissions
|
||||
role:hsOfficeRelationship.owner --> perm:hsOfficeRelationship.*{{relationship.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficeRelationship.owner
|
||||
role:hsOfficePersonAdmin#relAnchor.admin
|
||||
end
|
||||
```
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- the owner role with full access for admins of the relAnchor global admins
|
||||
ownerRole = createRole(
|
||||
hsOfficeRelationshipOwner(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
|
||||
beneathRoles(array[
|
||||
globalAdmin(),
|
||||
hsOfficePersonAdmin(newRelAnchor)])
|
||||
);
|
||||
|
||||
-- the admin role with full access for the owner
|
||||
adminRole = createRole(
|
||||
hsOfficeRelationshipAdmin(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
|
||||
beneathRole(ownerRole)
|
||||
);
|
||||
|
||||
-- the tenant role for those related users who can view the data
|
||||
perform createRole(
|
||||
hsOfficeRelationshipTenant,
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
|
||||
beneathRoles(array[
|
||||
hsOfficePersonAdmin(newRelAnchor),
|
||||
hsOfficePersonAdmin(newRelHolder),
|
||||
hsOfficeContactAdmin(newContact)]),
|
||||
withSubRoles(array[
|
||||
hsOfficePersonTenant(newRelAnchor),
|
||||
hsOfficePersonTenant(newRelHolder),
|
||||
hsOfficeContactTenant(newContact)])
|
||||
);
|
||||
|
||||
-- anchor and holder admin roles need each others tenant role
|
||||
-- to be able to see the joined relationship
|
||||
call grantRoleToRole(hsOfficePersonTenant(newRelAnchor), hsOfficePersonAdmin(newRelHolder));
|
||||
call grantRoleToRole(hsOfficePersonTenant(newRelHolder), hsOfficePersonAdmin(newRelAnchor));
|
||||
call grantRoleToRoleIfNotNull(hsOfficePersonTenant(newRelHolder), hsOfficeContactAdmin(newContact));
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.contactUuid <> NEW.contactUuid then
|
||||
-- nothing but the contact can be updated,
|
||||
-- in other cases, a new relationship needs to be created and the old updated
|
||||
|
||||
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
|
||||
|
||||
call revokeRoleFromRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(oldContact) );
|
||||
call grantRoleToRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(newContact) );
|
||||
|
||||
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeRelationshipTenant );
|
||||
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeRelationshipTenant );
|
||||
end if;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeRelationship_Trigger
|
||||
after insert
|
||||
on hs_office_relationship
|
||||
for each row
|
||||
execute procedure hsOfficeRelationshipRbacRolesTrigger();
|
||||
|
||||
/*
|
||||
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
|
||||
*/
|
||||
create trigger updateRbacRolesForHsOfficeRelationship_Trigger
|
||||
after update
|
||||
on hs_office_relationship
|
||||
for each row
|
||||
execute procedure hsOfficeRelationshipRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_relationship', $idName$
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.relAnchorUuid)
|
||||
|| '-with-' || target.relType || '-' ||
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_relationship',
|
||||
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
|
||||
$updates$
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
-- TODO: exception if one tries to amend any other column
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-NEW-RELATHIONSHIP:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-relationship and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-relationship permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-relationship']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeRelationshipNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-relationship not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_relationship_insert_trigger
|
||||
before insert
|
||||
on hs_office_relationship
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new relationships
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeRelationshipNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,192 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_relationship');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeRelationship', 'hs_office_relationship');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for relationship entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeRelationshipRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
hsOfficeRelationshipTenant RbacRoleDescriptor;
|
||||
newRelAnchor hs_office_person;
|
||||
newRelHolder hs_office_person;
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
hsOfficeRelationshipTenant := hsOfficeRelationshipTenant(NEW);
|
||||
|
||||
select * from hs_office_person as p where p.uuid = NEW.relAnchorUuid into newRelAnchor;
|
||||
select * from hs_office_person as p where p.uuid = NEW.relHolderUuid into newRelHolder;
|
||||
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[
|
||||
globalAdmin(),
|
||||
hsOfficePersonAdmin(newRelAnchor)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[hsOfficeRelationshipOwner(NEW)]
|
||||
);
|
||||
|
||||
-- the tenant role for those related users who can view the data
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationshipTenant,
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeRelationshipAdmin(NEW),
|
||||
hsOfficePersonAdmin(newRelAnchor),
|
||||
hsOfficePersonAdmin(newRelHolder),
|
||||
hsOfficeContactAdmin(newContact)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficePersonTenant(newRelAnchor),
|
||||
hsOfficePersonTenant(newRelHolder),
|
||||
hsOfficeContactTenant(newContact)]
|
||||
);
|
||||
|
||||
-- anchor and holder admin roles need each others tenant role
|
||||
-- to be able to see the joined relationship
|
||||
-- TODO: this can probably be avoided through agent+guest roles
|
||||
call grantRoleToRole(hsOfficePersonTenant(newRelAnchor), hsOfficePersonAdmin(newRelHolder));
|
||||
call grantRoleToRole(hsOfficePersonTenant(newRelHolder), hsOfficePersonAdmin(newRelAnchor));
|
||||
call grantRoleToRoleIfNotNull(hsOfficePersonTenant(newRelHolder), hsOfficeContactAdmin(newContact));
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.contactUuid <> NEW.contactUuid then
|
||||
-- nothing but the contact can be updated,
|
||||
-- in other cases, a new relationship needs to be created and the old updated
|
||||
|
||||
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
|
||||
|
||||
call revokeRoleFromRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(oldContact) );
|
||||
call grantRoleToRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(newContact) );
|
||||
|
||||
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeRelationshipTenant );
|
||||
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeRelationshipTenant );
|
||||
end if;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeRelationship_Trigger
|
||||
after insert
|
||||
on hs_office_relationship
|
||||
for each row
|
||||
execute procedure hsOfficeRelationshipRbacRolesTrigger();
|
||||
|
||||
/*
|
||||
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
|
||||
*/
|
||||
create trigger updateRbacRolesForHsOfficeRelationship_Trigger
|
||||
after update
|
||||
on hs_office_relationship
|
||||
for each row
|
||||
execute procedure hsOfficeRelationshipRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_relationship', $idName$
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.relAnchorUuid)
|
||||
|| '-with-' || target.relType || '-' ||
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_relationship',
|
||||
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
|
||||
$updates$
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
-- TODO: exception if one tries to amend any other column
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-rbac-NEW-RELATHIONSHIP:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-relationship and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-relationship permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-relationship']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeRelationshipNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-relationship not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_relationship_insert_trigger
|
||||
before insert
|
||||
on hs_office_relationship
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new relationships
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeRelationshipNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,104 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single relationship test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeRelationshipTestData(
|
||||
holderPersonName varchar,
|
||||
relationshipType HsOfficeRelationshipType,
|
||||
anchorPersonTradeName varchar,
|
||||
contactLabel varchar,
|
||||
mark varchar default null)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
anchorPerson hs_office_person;
|
||||
holderPerson hs_office_person;
|
||||
contact hs_office_contact;
|
||||
|
||||
begin
|
||||
idName := cleanIdentifier( anchorPersonTradeName || '-' || holderPersonName);
|
||||
currentTask := 'creating relationship test-data ' || idName;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select p.* from hs_office_person p where p.tradeName = anchorPersonTradeName into anchorPerson;
|
||||
if anchorPerson is null then
|
||||
raise exception 'anchorPerson "%" not found', anchorPersonTradeName;
|
||||
end if;
|
||||
|
||||
select p.* from hs_office_person p
|
||||
where p.tradeName = holderPersonName or p.familyName = holderPersonName
|
||||
into holderPerson;
|
||||
if holderPerson is null then
|
||||
raise exception 'holderPerson "%" not found', holderPersonName;
|
||||
end if;
|
||||
|
||||
select c.* from hs_office_contact c where c.label = contactLabel into contact;
|
||||
if contact is null then
|
||||
raise exception 'contact "%" not found', contactLabel;
|
||||
end if;
|
||||
|
||||
raise notice 'creating test relationship: %', idName;
|
||||
raise notice '- using anchor person (%): %', anchorPerson.uuid, anchorPerson;
|
||||
raise notice '- using holder person (%): %', holderPerson.uuid, holderPerson;
|
||||
raise notice '- using contact (%): %', contact.uuid, contact;
|
||||
insert
|
||||
into hs_office_relationship (uuid, relanchoruuid, relholderuuid, reltype, relmark, contactUuid)
|
||||
values (uuid_generate_v4(), anchorPerson.uuid, holderPerson.uuid, relationshipType, mark, contact.uuid);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
/*
|
||||
Creates a range of test relationship for mass data generation.
|
||||
*/
|
||||
create or replace procedure createHsOfficeRelationshipTestData(
|
||||
startCount integer, -- count of auto generated rows before the run
|
||||
endCount integer -- count of auto generated rows after the run
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
person hs_office_person;
|
||||
contact hs_office_contact;
|
||||
begin
|
||||
for t in startCount..endCount
|
||||
loop
|
||||
select p.* from hs_office_person p where tradeName = intToVarChar(t, 4) into person;
|
||||
select c.* from hs_office_contact c where c.label = intToVarChar(t, 4) || '#' || t into contact;
|
||||
|
||||
call createHsOfficeRelationshipTestData(person.uuid, contact.uuid, 'REPRESENTATIVE');
|
||||
commit;
|
||||
end loop;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeRelationshipTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
|
||||
call createHsOfficeRelationshipTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
||||
|
||||
call createHsOfficeRelationshipTestData('Second e.K.', 'PARTNER', 'Hostsharing eG', 'second contact');
|
||||
call createHsOfficeRelationshipTestData('Smith', 'REPRESENTATIVE', 'Second e.K.', 'second contact');
|
||||
|
||||
call createHsOfficeRelationshipTestData('Third OHG', 'PARTNER', 'Hostsharing eG', 'third contact');
|
||||
call createHsOfficeRelationshipTestData('Tucker', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
||||
|
||||
call createHsOfficeRelationshipTestData('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact');
|
||||
call createHsOfficeRelationshipTestData('Fouler', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
||||
|
||||
call createHsOfficeRelationshipTestData('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact');
|
||||
call createHsOfficeRelationshipTestData('Smith', 'SUBSCRIBER', 'Third OHG', 'third contact', 'members-announce');
|
||||
end;
|
||||
$$;
|
||||
--//
|
@@ -1,78 +0,0 @@
|
||||
### hs_office_partner RBAC
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeContact
|
||||
direction TB
|
||||
style hsOfficeContact fill:#eee
|
||||
|
||||
role:hsOfficeContact.admin[contact.admin]
|
||||
--> role:hsOfficeContact.tenant[contact.tenant]
|
||||
--> role:hsOfficeContact.guest[contact.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficePerson
|
||||
direction TB
|
||||
style hsOfficePerson fill:#eee
|
||||
|
||||
role:hsOfficePerson.admin[person.admin]
|
||||
--> role:hsOfficePerson.tenant[person.tenant]
|
||||
--> role:hsOfficePerson.guest[person.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficePartnerDetails
|
||||
direction TB
|
||||
|
||||
perm:hsOfficePartnerDetails.*{{partner.*}}
|
||||
perm:hsOfficePartnerDetails.edit{{partner.edit}}
|
||||
perm:hsOfficePartnerDetails.view{{partner.view}}
|
||||
end
|
||||
|
||||
subgraph hsOfficePartner
|
||||
|
||||
role:hsOfficePartner.owner[partner.owner]
|
||||
%% permissions
|
||||
role:hsOfficePartner.owner --> perm:hsOfficePartner.*{{partner.*}}
|
||||
role:hsOfficePartner.owner --> perm:hsOfficePartnerDetails.*{{partner.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficePartner.owner
|
||||
|
||||
role:hsOfficePartner.admin[partner.admin]
|
||||
%% permissions
|
||||
role:hsOfficePartner.admin --> perm:hsOfficePartner.edit{{partner.edit}}
|
||||
role:hsOfficePartner.admin --> perm:hsOfficePartnerDetails.edit{{partner.edit}}
|
||||
%% incoming
|
||||
role:hsOfficePartner.owner ---> role:hsOfficePartner.admin
|
||||
%% outgoing
|
||||
role:hsOfficePartner.admin --> role:hsOfficePerson.tenant
|
||||
role:hsOfficePartner.admin --> role:hsOfficeContact.tenant
|
||||
|
||||
role:hsOfficePartner.agent[partner.agent]
|
||||
%% permissions
|
||||
role:hsOfficePartner.agent --> perm:hsOfficePartnerDetails.view{{partner.view}}
|
||||
%% incoming
|
||||
role:hsOfficePartner.admin ---> role:hsOfficePartner.agent
|
||||
role:hsOfficePerson.admin --> role:hsOfficePartner.agent
|
||||
role:hsOfficeContact.admin --> role:hsOfficePartner.agent
|
||||
|
||||
role:hsOfficePartner.tenant[partner.tenant]
|
||||
%% incoming
|
||||
role:hsOfficePartner.agent --> role:hsOfficePartner.tenant
|
||||
%% outgoing
|
||||
role:hsOfficePartner.tenant --> role:hsOfficePerson.guest
|
||||
role:hsOfficePartner.tenant --> role:hsOfficeContact.guest
|
||||
|
||||
role:hsOfficePartner.guest[partner.guest]
|
||||
%% permissions
|
||||
role:hsOfficePartner.guest --> perm:hsOfficePartner.view{{partner.view}}
|
||||
%% incoming
|
||||
role:hsOfficePartner.tenant --> role:hsOfficePartner.guest
|
||||
end
|
||||
```
|
@@ -1,256 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_partner');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for partner entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficePartnerRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
oldPartnerRole hs_office_relationship;
|
||||
newPartnerRole hs_office_relationship;
|
||||
|
||||
oldPerson hs_office_person;
|
||||
newPerson hs_office_person;
|
||||
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from hs_office_relationship as r where r.uuid = NEW.partnerroleuuid into newPartnerRole;
|
||||
select * from hs_office_person as p where p.uuid = NEW.personUuid into newPerson;
|
||||
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- === ATTENTION: code generated from related Mermaid flowchart: ===
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerOwner(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newPartnerRole),
|
||||
hsOfficePersonTenant(newPerson),
|
||||
hsOfficeContactTenant(newContact)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerAdmin(NEW),
|
||||
hsOfficeRelationshipAdmin(newPartnerRole),
|
||||
hsOfficePersonAdmin(newPerson),
|
||||
hsOfficeContactAdmin(newContact)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerTenant(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePartnerAgent(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeRelationshipTenant(newPartnerRole),
|
||||
hsOfficePersonGuest(newPerson),
|
||||
hsOfficeContactGuest(newContact)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePartnerGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[hsOfficePartnerTenant(NEW)]
|
||||
);
|
||||
|
||||
-- === END of code generated from Mermaid flowchart. ===
|
||||
|
||||
-- Each partner-details entity belong exactly to one partner entity
|
||||
-- and it makes little sense just to delegate partner-details roles.
|
||||
-- Therefore, we did not model partner-details roles,
|
||||
-- but instead just assign extra permissions to existing partner-roles.
|
||||
|
||||
--Attention: Cannot be in partner-details because of insert order (partner is not in database yet)
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficePartnerOwner(NEW), 'fail'),
|
||||
createPermissions(NEW.detailsUuid, array ['*'])
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
getRoleId(hsOfficePartnerAdmin(NEW), 'fail'),
|
||||
createPermissions(NEW.detailsUuid, array ['edit'])
|
||||
);
|
||||
|
||||
call grantPermissionsToRole(
|
||||
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
|
||||
-- Do NOT grant view permission on partner-details to hsOfficePartnerTENANT!
|
||||
-- Otherwise package-admins etc. would be able to read the data.
|
||||
getRoleId(hsOfficePartnerAgent(NEW), 'fail'),
|
||||
createPermissions(NEW.detailsUuid, array ['view'])
|
||||
);
|
||||
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.partnerRoleUuid <> NEW.partnerRoleUuid then
|
||||
select * from hs_office_relationship as r where r.uuid = OLD.partnerRoleUuid into oldPartnerRole;
|
||||
|
||||
call revokeRoleFromRole(hsOfficeRelationshipTenant(oldPartnerRole), hsOfficePartnerAdmin(OLD));
|
||||
call grantRoleToRole(hsOfficeRelationshipTenant(newPartnerRole), hsOfficePartnerAdmin(NEW));
|
||||
|
||||
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficeRelationshipAdmin(oldPartnerRole));
|
||||
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeRelationshipAdmin(newPartnerRole));
|
||||
|
||||
call revokeRoleFromRole(hsOfficeRelationshipGuest(oldPartnerRole), hsOfficePartnerTenant(OLD));
|
||||
call grantRoleToRole(hsOfficeRelationshipGuest(newPartnerRole), hsOfficePartnerTenant(NEW));
|
||||
end if;
|
||||
|
||||
if OLD.personUuid <> NEW.personUuid then
|
||||
select * from hs_office_person as p where p.uuid = OLD.personUuid into oldPerson;
|
||||
|
||||
call revokeRoleFromRole(hsOfficePersonTenant(oldPerson), hsOfficePartnerAdmin(OLD));
|
||||
call grantRoleToRole(hsOfficePersonTenant(newPerson), hsOfficePartnerAdmin(NEW));
|
||||
|
||||
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficePersonAdmin(oldPerson));
|
||||
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficePersonAdmin(newPerson));
|
||||
|
||||
call revokeRoleFromRole(hsOfficePersonGuest(oldPerson), hsOfficePartnerTenant(OLD));
|
||||
call grantRoleToRole(hsOfficePersonGuest(newPerson), hsOfficePartnerTenant(NEW));
|
||||
end if;
|
||||
|
||||
if OLD.contactUuid <> NEW.contactUuid then
|
||||
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
|
||||
|
||||
call revokeRoleFromRole(hsOfficeContactTenant(oldContact), hsOfficePartnerAdmin(OLD));
|
||||
call grantRoleToRole(hsOfficeContactTenant(newContact), hsOfficePartnerAdmin(NEW));
|
||||
|
||||
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficeContactAdmin(oldContact));
|
||||
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeContactAdmin(newContact));
|
||||
|
||||
call revokeRoleFromRole(hsOfficeContactGuest(oldContact), hsOfficePartnerTenant(OLD));
|
||||
call grantRoleToRole(hsOfficeContactGuest(newContact), hsOfficePartnerTenant(NEW));
|
||||
end if;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficePartner_Trigger
|
||||
after insert
|
||||
on hs_office_partner
|
||||
for each row
|
||||
execute procedure hsOfficePartnerRbacRolesTrigger();
|
||||
|
||||
/*
|
||||
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
|
||||
*/
|
||||
create trigger updateRbacRolesForHsOfficePartner_Trigger
|
||||
after update
|
||||
on hs_office_partner
|
||||
for each row
|
||||
execute procedure hsOfficePartnerRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_partner', $idName$
|
||||
partnerNumber || ':' ||
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.personuuid)
|
||||
|| '-' ||
|
||||
(select idName from hs_office_contact_iv c where c.uuid = target.contactuuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_partner',
|
||||
'(select idName from hs_office_person_iv p where p.uuid = target.personUuid)',
|
||||
$updates$
|
||||
partnerRoleUuid = new.partnerRoleUuid,
|
||||
personUuid = new.personUuid,
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-NEW-PARTNER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-partner and assigns it to the Hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-partner permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-partner']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficePartnerNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-partner not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_partner_insert_trigger
|
||||
before insert
|
||||
on hs_office_partner
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new partners
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficePartnerNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,86 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_partner_details');
|
||||
--//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_partner_details', $idName$
|
||||
(select idName || '-details' from hs_office_partner_iv partner_iv
|
||||
join hs_office_partner partner on (partner_iv.uuid = partner.uuid)
|
||||
where partner.detailsUuid = target.uuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_partner_details',
|
||||
'target.uuid', -- no specific order required
|
||||
$updates$
|
||||
registrationOffice = new.registrationOffice,
|
||||
registrationNumber = new.registrationNumber,
|
||||
birthPlace = new.birthPlace,
|
||||
birthName = new.birthName,
|
||||
birthday = new.birthday,
|
||||
dateOfDeath = new.dateOfDeath
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-NEW-CONTACT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-partner-details and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-partner-details permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-partner-details']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- TODO.refa: the code below could be moved to a generator, maybe even the code above.
|
||||
-- Additionally, the code below is not neccesary for all entities, specifiy when it is!
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-partner-details to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficePartnerDetailsNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-partner-details not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create new partner-details.
|
||||
*/
|
||||
create trigger hs_office_partner_details_insert_trigger
|
||||
before insert
|
||||
on hs_office_partner_details
|
||||
for each row
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficePartnerDetailsNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,40 +0,0 @@
|
||||
### hs_office_bankaccount RBAC Roles
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style hsOfficeBankAccount fill: #e9f7ef
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeBankAccount
|
||||
direction TB
|
||||
style hsOfficeBankAccount fill: #e9f7ef
|
||||
|
||||
user:hsOfficeBankAccount.creator([bankAccount.creator])
|
||||
|
||||
role:hsOfficeBankAccount.owner[[bankAccount.owner]]
|
||||
%% permissions
|
||||
role:hsOfficeBankAccount.owner --> perm:hsOfficeBankAccount.*{{hsOfficeBankAccount.delete}}
|
||||
%% incoming
|
||||
role:global.admin --> role:hsOfficeBankAccount.owner
|
||||
user:hsOfficeBankAccount.creator ---> role:hsOfficeBankAccount.owner
|
||||
|
||||
role:hsOfficeBankAccount.admin[[bankAccount.admin]]
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.owner ---> role:hsOfficeBankAccount.admin
|
||||
|
||||
role:hsOfficeBankAccount.tenant[[bankAccount.tenant]]
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.admin ---> role:hsOfficeBankAccount.tenant
|
||||
|
||||
role:hsOfficeBankAccount.guest[[bankAccount.guest]]
|
||||
%% permissions
|
||||
role:hsOfficeBankAccount.guest --> perm:hsOfficeBankAccount.view{{hsOfficeBankAccount.view}}
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.tenant ---> role:hsOfficeBankAccount.guest
|
||||
end
|
||||
```
|
||||
|
@@ -1,139 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_bankaccount');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeBankAccount', 'hs_office_bankaccount');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles and their assignments for a new bankaccount for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace function createRbacRolesForHsOfficeBankAccount()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP <> 'INSERT' then
|
||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||
end if;
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountOwner(NEW),
|
||||
permissions => array['delete'],
|
||||
incomingSuperRoles => array[globalAdmin()],
|
||||
userUuids => array[currentUserUuid()],
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountAdmin(NEW),
|
||||
incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[hsOfficeBankAccountTenant(NEW)]
|
||||
);
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
|
||||
create trigger createRbacRolesForHsOfficeBankAccount_Trigger
|
||||
after insert
|
||||
on hs_office_bankaccount
|
||||
for each row
|
||||
execute procedure createRbacRolesForHsOfficeBankAccount();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityView('hs_office_bankaccount', $idName$
|
||||
target.holder
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_bankaccount', 'target.holder',
|
||||
$updates$
|
||||
holder = new.holder,
|
||||
iban = new.iban,
|
||||
bic = new.bic
|
||||
$updates$);
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-NEW-BANKACCOUNT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-bankaccount and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-bankaccount permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-bankaccount']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeBankAccountNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-bankaccount not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_bankaccount_insert_trigger
|
||||
before insert
|
||||
on hs_office_bankaccount
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new bankaccounts
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeBankAccountNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,71 +0,0 @@
|
||||
### hs_office_sepaMandate RBAC
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeBankAccount
|
||||
direction TB
|
||||
style hsOfficeBankAccount fill:#eee
|
||||
|
||||
role:hsOfficeBankAccount.owner[bankAccount.owner]
|
||||
--> role:hsOfficeBankAccount.admin[bankAccount.admin]
|
||||
--> role:hsOfficeBankAccount.tenant[bankAccount.tenant]
|
||||
--> role:hsOfficeBankAccount.guest[bankAccount.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficeDebitor
|
||||
direction TB
|
||||
style hsOfficeDebitor fill:#eee
|
||||
|
||||
role:hsOfficeDebitor.owner[debitor.admin]
|
||||
--> role:hsOfficeDebitor.admin[debitor.admin]
|
||||
--> role:hsOfficeDebitor.agent[debitor.agent]
|
||||
--> role:hsOfficeDebitor.tenant[debitor.tenant]
|
||||
--> role:hsOfficeDebitor.guest[debitor.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficeSepaMandate
|
||||
|
||||
role:hsOfficeSepaMandate.owner[sepaMandate.owner]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.owner --> perm:hsOfficeSepaMandate.*{{sepaMandate.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficeSepaMandate.owner
|
||||
|
||||
role:hsOfficeSepaMandate.admin[sepaMandate.admin]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.admin --> perm:hsOfficeSepaMandate.edit{{sepaMandate.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.owner ---> role:hsOfficeSepaMandate.admin
|
||||
|
||||
role:hsOfficeSepaMandate.agent[sepaMandate.agent]
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.admin ---> role:hsOfficeSepaMandate.agent
|
||||
role:hsOfficeDebitor.admin --> role:hsOfficeSepaMandate.agent
|
||||
role:hsOfficeBankAccount.admin --> role:hsOfficeSepaMandate.agent
|
||||
%% outgoing
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeDebitor.tenant
|
||||
role:hsOfficeSepaMandate.admin --> role:hsOfficeBankAccount.tenant
|
||||
|
||||
role:hsOfficeSepaMandate.tenant[sepaMandate.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeSepaMandate.tenant
|
||||
%% outgoing
|
||||
role:hsOfficeSepaMandate.tenant --> role:hsOfficeDebitor.guest
|
||||
role:hsOfficeSepaMandate.tenant --> role:hsOfficeBankAccount.guest
|
||||
|
||||
role:hsOfficeSepaMandate.guest[sepaMandate.guest]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.guest --> perm:hsOfficeSepaMandate.view{{sepaMandate.view}}
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.tenant --> role:hsOfficeSepaMandate.guest
|
||||
end
|
||||
|
||||
|
||||
```
|
@@ -1,158 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_sepamandate');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeSepaMandate', 'hs_office_sepamandate');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for sepaMandate entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeSepaMandateRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
newHsOfficeDebitor hs_office_debitor;
|
||||
newHsOfficeBankAccount hs_office_bankAccount;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from hs_office_debitor as p where p.uuid = NEW.debitorUuid into newHsOfficeDebitor;
|
||||
select * from hs_office_bankAccount as c where c.uuid = NEW.bankAccountUuid into newHsOfficeBankAccount;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- === ATTENTION: code generated from related Mermaid flowchart: ===
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)],
|
||||
outgoingSubRoles => array[hsOfficeBankAccountTenant(newHsOfficeBankAccount)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAgent(NEW),
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW), hsOfficeDebitorAdmin(newHsOfficeDebitor), hsOfficeBankAccountAdmin(newHsOfficeBankAccount)],
|
||||
outgoingSubRoles => array[hsOfficeDebitorTenant(newHsOfficeDebitor)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateAgent(NEW)],
|
||||
outgoingSubRoles => array[hsOfficeDebitorGuest(newHsOfficeDebitor), hsOfficeBankAccountGuest(newHsOfficeBankAccount)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateTenant(NEW)]
|
||||
);
|
||||
|
||||
-- === END of code generated from Mermaid flowchart. ===
|
||||
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeSepaMandate_Trigger
|
||||
after insert
|
||||
on hs_office_sepamandate
|
||||
for each row
|
||||
execute procedure hsOfficeSepaMandateRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_sepamandate', idNameExpression => 'target.reference');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_sepamandate',
|
||||
orderby => 'target.reference',
|
||||
columnUpdates => $updates$
|
||||
reference = new.reference,
|
||||
agreement = new.agreement,
|
||||
validity = new.validity
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-NEW-SepaMandate:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-sepaMandate and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-sepaMandate permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-sepamandate']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeSepaMandateNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-sepaMandate not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_sepamandate_insert_trigger
|
||||
before insert
|
||||
on hs_office_sepamandate
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new sepaMandates
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeSepaMandateNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,51 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepaMandate-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single sepaMandate test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeSepaMandateTestData( tradeNameAndHolderName varchar )
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
relatedDebitor hs_office_debitor;
|
||||
relatedBankAccount hs_office_bankAccount;
|
||||
begin
|
||||
idName := cleanIdentifier( tradeNameAndHolderName);
|
||||
currentTask := 'creating SEPA-mandate test-data ' || idName;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select debitor.* from hs_office_debitor debitor
|
||||
join hs_office_partner parter on parter.uuid = debitor.partnerUuid
|
||||
join hs_office_person person on person.uuid = parter.personUuid
|
||||
where person.tradeName = tradeNameAndHolderName into relatedDebitor;
|
||||
select c.* from hs_office_bankAccount c where c.holder = tradeNameAndHolderName into relatedBankAccount;
|
||||
|
||||
raise notice 'creating test SEPA-mandate: %', idName;
|
||||
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
|
||||
raise notice '- using bankAccount (%): %', relatedBankAccount.uuid, relatedBankAccount;
|
||||
insert
|
||||
into hs_office_sepamandate (uuid, debitoruuid, bankAccountuuid, reference, agreement, validity)
|
||||
values (uuid_generate_v4(), relatedDebitor.uuid, relatedBankAccount.uuid, 'ref'||idName, '20220930', daterange('20221001' , '20261231', '[]'));
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepaMandate-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeSepaMandateTestData('First GmbH');
|
||||
call createHsOfficeSepaMandateTestData('Second e.K.');
|
||||
call createHsOfficeSepaMandateTestData('Third OHG');
|
||||
end;
|
||||
$$;
|
||||
--//
|
@@ -1,250 +0,0 @@
|
||||
### hs_office_debitor RBAC Roles
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph office
|
||||
style office fill:#eee
|
||||
|
||||
subgraph sepa
|
||||
|
||||
subgraph bankaccount
|
||||
style bankaccount fill: #e9f7ef
|
||||
|
||||
user:hsOfficeBankAccount.creator([bankaccount.creator])
|
||||
|
||||
role:hsOfficeBankAccount.owner[bankaccount.owner]
|
||||
%% permissions
|
||||
role:hsOfficeBankAccount.owner --> perm:hsOfficeBankAccount.*{{bankaccount.*}}
|
||||
%% incoming
|
||||
role:global.admin --> role:hsOfficeBankAccount.owner
|
||||
user:hsOfficeBankAccount.creator ---> role:hsOfficeBankAccount.owner
|
||||
|
||||
role:hsOfficeBankAccount.admin[bankaccount.admin]
|
||||
%% permissions
|
||||
role:hsOfficeBankAccount.admin --> perm:hsOfficeBankAccount.edit{{bankaccount.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.owner ---> role:hsOfficeBankAccount.admin
|
||||
|
||||
role:hsOfficeBankAccount.tenant[bankaccount.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.admin ---> role:hsOfficeBankAccount.tenant
|
||||
|
||||
role:hsOfficeBankAccount.guest[bankaccount.guest]
|
||||
%% permissions
|
||||
role:hsOfficeBankAccount.guest --> perm:hsOfficeBankAccount.view{{bankaccount.view}}
|
||||
%% incoming
|
||||
role:hsOfficeBankAccount.tenant ---> role:hsOfficeBankAccount.guest
|
||||
end
|
||||
|
||||
subgraph hsOfficeSepaMandate
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
subgraph contact
|
||||
style contact fill: #e9f7ef
|
||||
|
||||
user:hsOfficeContact.creator([contact.creator])
|
||||
|
||||
role:hsOfficeContact.owner[contact.owner]
|
||||
%% permissions
|
||||
role:hsOfficeContact.owner --> perm:hsOfficeContact.*{{contact.*}}
|
||||
%% incoming
|
||||
role:global.admin --> role:hsOfficeContact.owner
|
||||
user:hsOfficeContact.creator ---> role:hsOfficeContact.owner
|
||||
|
||||
role:hsOfficeContact.admin[contact.admin]
|
||||
%% permissions
|
||||
role:hsOfficeContact.admin ---> perm:hsOfficeContact.edit{{contact.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeContact.owner ---> role:hsOfficeContact.admin
|
||||
|
||||
role:hsOfficeContact.tenant[contact.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeContact.admin ----> role:hsOfficeContact.tenant
|
||||
|
||||
role:hsOfficeContact.guest[contact.guest]
|
||||
%% permissions
|
||||
role:hsOfficeContact.guest --> perm:hsOfficeContact.view{{contact.view}}
|
||||
%% incoming
|
||||
role:hsOfficeContact.tenant ---> role:hsOfficeContact.guest
|
||||
end
|
||||
|
||||
subgraph partner-person
|
||||
|
||||
subgraph person
|
||||
style person fill: #e9f7ef
|
||||
|
||||
user:hsOfficePerson.creator([personcreator])
|
||||
|
||||
role:hsOfficePerson.owner[person.owner]
|
||||
%% permissions
|
||||
role:hsOfficePerson.owner --> perm:hsOfficePerson.*{{person.*}}
|
||||
%% incoming
|
||||
user:hsOfficePerson.creator ---> role:hsOfficePerson.owner
|
||||
role:global.admin --> role:hsOfficePerson.owner
|
||||
|
||||
role:hsOfficePerson.admin[person.admin]
|
||||
%% permissions
|
||||
role:hsOfficePerson.admin --> perm:hsOfficePerson.edit{{person.edit}}
|
||||
%% incoming
|
||||
role:hsOfficePerson.owner ---> role:hsOfficePerson.admin
|
||||
|
||||
role:hsOfficePerson.tenant[person.tenant]
|
||||
%% incoming
|
||||
role:hsOfficePerson.admin -----> role:hsOfficePerson.tenant
|
||||
|
||||
role:hsOfficePerson.guest[person.guest]
|
||||
%% permissions
|
||||
role:hsOfficePerson.guest --> perm:hsOfficePerson.edit{{person.view}}
|
||||
%% incoming
|
||||
role:hsOfficePerson.tenant ---> role:hsOfficePerson.guest
|
||||
end
|
||||
|
||||
subgraph partner
|
||||
|
||||
role:hsOfficePartner.owner[partner.owner]
|
||||
%% permissions
|
||||
role:hsOfficePartner.owner --> perm:hsOfficePartner.*{{partner.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficePartner.owner
|
||||
|
||||
role:hsOfficePartner.admin[partner.admin]
|
||||
%% permissions
|
||||
role:hsOfficePartner.admin --> perm:hsOfficePartner.edit{{partner.edit}}
|
||||
%% incoming
|
||||
role:hsOfficePartner.owner ---> role:hsOfficePartner.admin
|
||||
%% outgoing
|
||||
role:hsOfficePartner.admin --> role:hsOfficePerson.tenant
|
||||
role:hsOfficePartner.admin --> role:hsOfficeContact.tenant
|
||||
|
||||
role:hsOfficePartner.agent[partner.agent]
|
||||
%% incoming
|
||||
role:hsOfficePartner.admin --> role:hsOfficePartner.agent
|
||||
role:hsOfficePerson.admin --> role:hsOfficePartner.agent
|
||||
role:hsOfficeContact.admin --> role:hsOfficePartner.agent
|
||||
|
||||
role:hsOfficePartner.tenant[partner.tenant]
|
||||
%% incoming
|
||||
role:hsOfficePartner.agent ---> role:hsOfficePartner.tenant
|
||||
%% outgoing
|
||||
role:hsOfficePartner.tenant --> role:hsOfficePerson.guest
|
||||
role:hsOfficePartner.tenant --> role:hsOfficeContact.guest
|
||||
|
||||
role:hsOfficePartner.guest[partner.guest]
|
||||
%% permissions
|
||||
role:hsOfficePartner.guest --> perm:hsOfficePartner.view{{partner.view}}
|
||||
%% incoming
|
||||
role:hsOfficePartner.tenant ---> role:hsOfficePartner.guest
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
subgraph debitor
|
||||
style debitor stroke-width:6px
|
||||
|
||||
user:hsOfficeDebitor.creator([debitor.creator])
|
||||
%% created by role
|
||||
user:hsOfficeDebitor.creator --> role:hsOfficePartner.agent
|
||||
|
||||
role:hsOfficeDebitor.owner[debitor.owner]
|
||||
%% permissions
|
||||
role:hsOfficeDebitor.owner --> perm:hsOfficeDebitor.*{{debitor.*}}
|
||||
%% incoming
|
||||
user:hsOfficeDebitor.creator --> role:hsOfficeDebitor.owner
|
||||
role:global.admin --> role:hsOfficeDebitor.owner
|
||||
|
||||
role:hsOfficeDebitor.admin[debitor.admin]
|
||||
%% permissions
|
||||
role:hsOfficeDebitor.admin --> perm:hsOfficeDebitor.edit{{debitor.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeDebitor.owner ---> role:hsOfficeDebitor.admin
|
||||
|
||||
role:hsOfficeDebitor.agent[debitor.agent]
|
||||
%% incoming
|
||||
role:hsOfficeDebitor.admin ---> role:hsOfficeDebitor.agent
|
||||
role:hsOfficePartner.admin --> role:hsOfficeDebitor.agent
|
||||
%% outgoing
|
||||
role:hsOfficeDebitor.agent --> role:hsOfficeBankAccount.tenant
|
||||
|
||||
role:hsOfficeDebitor.tenant[debitor.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeDebitor.agent ---> role:hsOfficeDebitor.tenant
|
||||
role:hsOfficePartner.agent --> role:hsOfficeDebitor.tenant
|
||||
role:hsOfficeBankAccount.admin --> role:hsOfficeDebitor.tenant
|
||||
%% outgoing
|
||||
role:hsOfficeDebitor.tenant --> role:hsOfficePartner.tenant
|
||||
role:hsOfficeDebitor.tenant --> role:hsOfficeContact.guest
|
||||
|
||||
role:hsOfficeDebitor.guest[debitor.guest]
|
||||
%% permissions
|
||||
role:hsOfficeDebitor.guest --> perm:hsOfficeDebitor.view{{debitor.view}}
|
||||
%% incoming
|
||||
role:hsOfficeDebitor.tenant --> role:hsOfficeDebitor.guest
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
subgraph hsOfficeSepaMandate
|
||||
|
||||
role:hsOfficeSepaMandate.owner[sepaMandate.owner]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.owner --> perm:hsOfficeSepaMandate.*{{sepaMandate.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficeSepaMandate.owner
|
||||
|
||||
role:hsOfficeSepaMandate.admin[sepaMandate.admin]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.admin --> perm:hsOfficeSepaMandate.edit{{sepaMandate.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.owner ---> role:hsOfficeSepaMandate.admin
|
||||
|
||||
role:hsOfficeSepaMandate.agent[sepaMandate.agent]
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.admin ---> role:hsOfficeSepaMandate.agent
|
||||
role:hsOfficeDebitor.admin --> role:hsOfficeSepaMandate.agent
|
||||
role:hsOfficeBankAccount.admin --> role:hsOfficeSepaMandate.agent
|
||||
%% outgoing
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeDebitor.tenant
|
||||
role:hsOfficeSepaMandate.admin --> role:hsOfficeBankAccount.tenant
|
||||
|
||||
role:hsOfficeSepaMandate.tenant[sepaMandate.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.agent --> role:hsOfficeSepaMandate.tenant
|
||||
%% outgoing
|
||||
role:hsOfficeSepaMandate.tenant --> role:hsOfficeDebitor.guest
|
||||
role:hsOfficeSepaMandate.tenant --> role:hsOfficeBankAccount.guest
|
||||
|
||||
role:hsOfficeSepaMandate.guest[sepaMandate.guest]
|
||||
%% permissions
|
||||
role:hsOfficeSepaMandate.guest --> perm:hsOfficeSepaMandate.view{{sepaMandate.view}}
|
||||
%% incoming
|
||||
role:hsOfficeSepaMandate.tenant --> role:hsOfficeSepaMandate.guest
|
||||
end
|
||||
|
||||
subgraph hosting
|
||||
style hosting fill:#eee
|
||||
|
||||
subgraph package
|
||||
style package fill: #e9f7ef
|
||||
|
||||
role:package.owner[package.owner]
|
||||
--> role:package.admin[package.admin]
|
||||
--> role:package.tenant[package.tenant]
|
||||
|
||||
role:hsOfficeDebitor.agent --> role:package.owner
|
||||
role:package.admin --> role:hsOfficeDebitor.tenant
|
||||
role:hsOfficePartner.tenant --> role:hsOfficeDebitor.guest
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
```
|
||||
|
@@ -1,247 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_debitor');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeDebitor', 'hs_office_debitor');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for debitor entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeDebitorRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
hsOfficeDebitorTenant RbacRoleDescriptor;
|
||||
oldPartner hs_office_partner;
|
||||
newPartner hs_office_partner;
|
||||
newPerson hs_office_person;
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
newBankAccount hs_office_bankaccount;
|
||||
oldBankAccount hs_office_bankaccount;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
|
||||
|
||||
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newPartner;
|
||||
select * from hs_office_person as p where p.uuid = newPartner.personUuid into newPerson;
|
||||
select * from hs_office_contact as c where c.uuid = NEW.billingContactUuid into newContact;
|
||||
select * from hs_office_bankaccount as b where b.uuid = NEW.refundBankAccountUuid into newBankAccount;
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()],
|
||||
userUuids => array[currentUserUuid()],
|
||||
grantedByRole => globalAdmin()
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[hsOfficeDebitorOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorAgent(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeDebitorAdmin(NEW),
|
||||
hsOfficePartnerAdmin(newPartner),
|
||||
hsOfficeContactAdmin(newContact)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeBankAccountTenant(newBankaccount)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorTenant(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeDebitorAgent(NEW),
|
||||
hsOfficePartnerAgent(newPartner),
|
||||
hsOfficeBankAccountAdmin(newBankaccount)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficePartnerTenant(newPartner),
|
||||
hsOfficeContactGuest(newContact),
|
||||
hsOfficeBankAccountGuest(newBankaccount)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeDebitorGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeDebitorTenant(NEW)]
|
||||
);
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.partnerUuid <> NEW.partnerUuid then
|
||||
select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner;
|
||||
|
||||
call revokeRoleFromRole(hsOfficeDebitorAgent(OLD), hsOfficePartnerAdmin(oldPartner));
|
||||
call grantRoleToRole(hsOfficeDebitorAgent(NEW), hsOfficePartnerAdmin(newPartner));
|
||||
|
||||
call revokeRoleFromRole(hsOfficeDebitorTenant(OLD), hsOfficePartnerAgent(oldPartner));
|
||||
call grantRoleToRole(hsOfficeDebitorTenant(NEW), hsOfficePartnerAgent(newPartner));
|
||||
|
||||
call revokeRoleFromRole(hsOfficePartnerTenant(oldPartner), hsOfficeDebitorTenant(OLD));
|
||||
call grantRoleToRole(hsOfficePartnerTenant(newPartner), hsOfficeDebitorTenant(NEW));
|
||||
end if;
|
||||
|
||||
if OLD.billingContactUuid <> NEW.billingContactUuid then
|
||||
select * from hs_office_contact as c where c.uuid = OLD.billingContactUuid into oldContact;
|
||||
|
||||
call revokeRoleFromRole(hsOfficeDebitorAgent(OLD), hsOfficeContactAdmin(oldContact));
|
||||
call grantRoleToRole(hsOfficeDebitorAgent(NEW), hsOfficeContactAdmin(newContact));
|
||||
|
||||
call revokeRoleFromRole(hsOfficeContactGuest(oldContact), hsOfficeDebitorTenant(OLD));
|
||||
call grantRoleToRole(hsOfficeContactGuest(newContact), hsOfficeDebitorTenant(NEW));
|
||||
end if;
|
||||
|
||||
if (OLD.refundBankAccountUuid is not null or NEW.refundBankAccountUuid is not null) and
|
||||
( OLD.refundBankAccountUuid is null or NEW.refundBankAccountUuid is null or
|
||||
OLD.refundBankAccountUuid <> NEW.refundBankAccountUuid ) then
|
||||
|
||||
select * from hs_office_bankaccount as b where b.uuid = OLD.refundBankAccountUuid into oldBankAccount;
|
||||
|
||||
if oldBankAccount is not null then
|
||||
call revokeRoleFromRole(hsOfficeBankAccountTenant(oldBankaccount), hsOfficeDebitorAgent(OLD));
|
||||
end if;
|
||||
if newBankAccount is not null then
|
||||
call grantRoleToRole(hsOfficeBankAccountTenant(newBankaccount), hsOfficeDebitorAgent(NEW));
|
||||
end if;
|
||||
|
||||
if oldBankAccount is not null then
|
||||
call revokeRoleFromRole(hsOfficeDebitorTenant(OLD), hsOfficeBankAccountAdmin(oldBankaccount));
|
||||
end if;
|
||||
if newBankAccount is not null then
|
||||
call grantRoleToRole(hsOfficeDebitorTenant(NEW), hsOfficeBankAccountAdmin(newBankaccount));
|
||||
end if;
|
||||
|
||||
if oldBankAccount is not null then
|
||||
call revokeRoleFromRole(hsOfficeBankAccountGuest(oldBankaccount), hsOfficeDebitorTenant(OLD));
|
||||
end if;
|
||||
if newBankAccount is not null then
|
||||
call grantRoleToRole(hsOfficeBankAccountGuest(newBankaccount), hsOfficeDebitorTenant(NEW));
|
||||
end if;
|
||||
end if;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new debitor.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeDebitor_Trigger
|
||||
after insert
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
execute procedure hsOfficeDebitorRbacRolesTrigger();
|
||||
|
||||
/*
|
||||
An AFTER UPDATE TRIGGER which updates the role structure of a debitor.
|
||||
*/
|
||||
create trigger updateRbacRolesForHsOfficeDebitor_Trigger
|
||||
after update
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
execute procedure hsOfficeDebitorRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_debitor', $idName$
|
||||
'#' ||
|
||||
(select partnerNumber from hs_office_partner p where p.uuid = target.partnerUuid) ||
|
||||
to_char(debitorNumberSuffix, 'fm00') ||
|
||||
':' || (select split_part(idName, ':', 2) from hs_office_partner_iv pi where pi.uuid = target.partnerUuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_debitor', 'target.debitorNumberSuffix',
|
||||
$updates$
|
||||
partnerUuid = new.partnerUuid, -- TODO: remove? should never do anything
|
||||
billable = new.billable,
|
||||
billingContactUuid = new.billingContactUuid,
|
||||
debitorNumberSuffix = new.debitorNumberSuffix, -- TODO: Should it be allowed to updated this value?
|
||||
refundBankAccountUuid = new.refundBankAccountUuid,
|
||||
vatId = new.vatId,
|
||||
vatCountryCode = new.vatCountryCode,
|
||||
vatBusiness = new.vatBusiness,
|
||||
vatreversecharge = new.vatreversecharge,
|
||||
defaultPrefix = new.defaultPrefix -- TODO: Should it be allowed to updated this value?
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-NEW-DEBITOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-debitor and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addDebitorPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-debitor permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addDebitorPermissions := createPermissions(globalObjectUuid, array ['new-debitor']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addDebitorPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-debitor to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeDebitorNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-debitor not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new debitor.
|
||||
*/
|
||||
create trigger hs_office_debitor_insert_trigger
|
||||
before insert
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new debitors
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeDebitorNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,57 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single debitor test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeDebitorTestData(
|
||||
debitorNumberSuffix numeric(5),
|
||||
partnerTradeName varchar,
|
||||
billingContactLabel varchar,
|
||||
defaultPrefix varchar
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
relatedPartner hs_office_partner;
|
||||
relatedContact hs_office_contact;
|
||||
relatedBankAccountUuid uuid;
|
||||
begin
|
||||
idName := cleanIdentifier( partnerTradeName|| '-' || billingContactLabel);
|
||||
currentTask := 'creating debitor test-data ' || idName;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select partner.* from hs_office_partner partner
|
||||
join hs_office_person person on person.uuid = partner.personUuid
|
||||
where person.tradeName = partnerTradeName into relatedPartner;
|
||||
select c.* from hs_office_contact c where c.label = billingContactLabel into relatedContact;
|
||||
select b.uuid from hs_office_bankaccount b where b.holder = partnerTradeName into relatedBankAccountUuid;
|
||||
|
||||
raise notice 'creating test debitor: % (#%)', idName, debitorNumberSuffix;
|
||||
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
|
||||
raise notice '- using billingContact (%): %', relatedContact.uuid, relatedContact;
|
||||
insert
|
||||
into hs_office_debitor (uuid, partneruuid, debitornumbersuffix, billable, billingcontactuuid, vatbusiness, vatreversecharge, refundbankaccountuuid, defaultprefix)
|
||||
values (uuid_generate_v4(), relatedPartner.uuid, debitorNumberSuffix, true, relatedContact.uuid, true, false, relatedBankAccountUuid, defaultPrefix);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeDebitorTestData(11, 'First GmbH', 'first contact', 'fir');
|
||||
call createHsOfficeDebitorTestData(12, 'Second e.K.', 'second contact', 'sec');
|
||||
call createHsOfficeDebitorTestData(13, 'Third OHG', 'third contact', 'thi');
|
||||
end;
|
||||
$$;
|
||||
--//
|
@@ -1,75 +0,0 @@
|
||||
### hs_office_membership RBAC
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph global
|
||||
style global fill:#eee
|
||||
|
||||
role:global.admin[global.admin]
|
||||
end
|
||||
|
||||
subgraph hsOfficeDebitor
|
||||
direction TB
|
||||
style hsOfficeDebitor fill:#eee
|
||||
|
||||
role:hsOfficeDebitor.owner[debitor.owner]
|
||||
--> role:hsOfficeDebitor.admin[debitor.admin]
|
||||
--> role:hsOfficeDebitor.tenant[debitor.tenant]
|
||||
--> role:hsOfficeDebitor.guest[debitor.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficePartner
|
||||
direction TB
|
||||
style hsOfficePartner fill:#eee
|
||||
|
||||
role:hsOfficePartner.owner[partner.admin]
|
||||
--> role:hsOfficePartner.admin[partner.admin]
|
||||
--> role:hsOfficePartner.agent[partner.agent]
|
||||
--> role:hsOfficePartner.tenant[partner.tenant]
|
||||
--> role:hsOfficePartner.guest[partner.guest]
|
||||
end
|
||||
|
||||
subgraph hsOfficeMembership
|
||||
|
||||
role:hsOfficeMembership.owner[membership.owner]
|
||||
%% permissions
|
||||
role:hsOfficeMembership.owner --> perm:hsOfficeMembership.*{{membership.*}}
|
||||
%% incoming
|
||||
role:global.admin ---> role:hsOfficeMembership.owner
|
||||
|
||||
role:hsOfficeMembership.admin[membership.admin]
|
||||
%% permissions
|
||||
role:hsOfficeMembership.admin --> perm:hsOfficeMembership.edit{{membership.edit}}
|
||||
%% incoming
|
||||
role:hsOfficeMembership.owner ---> role:hsOfficeMembership.admin
|
||||
|
||||
role:hsOfficeMembership.agent[membership.agent]
|
||||
%% incoming
|
||||
role:hsOfficeMembership.admin ---> role:hsOfficeMembership.agent
|
||||
role:hsOfficePartner.admin --> role:hsOfficeMembership.agent
|
||||
role:hsOfficeDebitor.admin --> role:hsOfficeMembership.agent
|
||||
%% outgoing
|
||||
role:hsOfficeMembership.agent --> role:hsOfficePartner.tenant
|
||||
role:hsOfficeMembership.agent --> role:hsOfficeDebitor.tenant
|
||||
|
||||
role:hsOfficeMembership.tenant[membership.tenant]
|
||||
%% incoming
|
||||
role:hsOfficeMembership.agent --> role:hsOfficeMembership.tenant
|
||||
role:hsOfficePartner.agent --> role:hsOfficeMembership.tenant
|
||||
role:hsOfficeDebitor.agent --> role:hsOfficeMembership.tenant
|
||||
%% outgoing
|
||||
role:hsOfficeMembership.tenant --> role:hsOfficePartner.guest
|
||||
role:hsOfficeMembership.tenant --> role:hsOfficeDebitor.guest
|
||||
|
||||
role:hsOfficeMembership.guest[membership.guest]
|
||||
%% permissions
|
||||
role:hsOfficeMembership.guest --> perm:hsOfficeMembership.view{{membership.view}}
|
||||
%% incoming
|
||||
role:hsOfficeMembership.tenant --> role:hsOfficeMembership.guest
|
||||
role:hsOfficePartner.tenant --> role:hsOfficeMembership.guest
|
||||
role:hsOfficeDebitor.tenant --> role:hsOfficeMembership.guest
|
||||
end
|
||||
|
||||
|
||||
```
|
@@ -1,162 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_membership');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeMembership', 'hs_office_membership');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for membership entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeMembershipRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
newHsOfficePartner hs_office_partner;
|
||||
newHsOfficeDebitor hs_office_debitor;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner;
|
||||
select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- === ATTENTION: code generated from related Mermaid flowchart: ===
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeMembershipOwner(NEW),
|
||||
permissions => array['*'],
|
||||
incomingSuperRoles => array[globalAdmin()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeMembershipAdmin(NEW),
|
||||
permissions => array['edit'],
|
||||
incomingSuperRoles => array[hsOfficeMembershipOwner(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeMembershipAgent(NEW),
|
||||
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficePartnerAdmin(newHsOfficePartner), hsOfficeDebitorAdmin(newHsOfficeDebitor)],
|
||||
outgoingSubRoles => array[hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeMembershipTenant(NEW),
|
||||
incomingSuperRoles => array[hsOfficeMembershipAgent(NEW), hsOfficePartnerAgent(newHsOfficePartner), hsOfficeDebitorAgent(newHsOfficeDebitor)],
|
||||
outgoingSubRoles => array[hsOfficePartnerGuest(newHsOfficePartner), hsOfficeDebitorGuest(newHsOfficeDebitor)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeMembershipGuest(NEW),
|
||||
permissions => array['view'],
|
||||
incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
|
||||
);
|
||||
|
||||
-- === END of code generated from Mermaid flowchart. ===
|
||||
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeMembership_Trigger
|
||||
after insert
|
||||
on hs_office_membership
|
||||
for each row
|
||||
execute procedure hsOfficeMembershipRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_membership', idNameExpression => $idName$
|
||||
'#' ||
|
||||
(select partnerNumber from hs_office_partner p where p.uuid = target.partnerUuid) ||
|
||||
memberNumberSuffix ||
|
||||
':' || (select split_part(idName, ':', 2) from hs_office_partner_iv p where p.uuid = target.partnerUuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_membership',
|
||||
orderby => 'target.memberNumberSuffix',
|
||||
columnUpdates => $updates$
|
||||
validity = new.validity,
|
||||
reasonForTermination = new.reasonForTermination,
|
||||
membershipFeeBillable = new.membershipFeeBillable
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-rbac-NEW-Membership:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-membership and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-membership permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-membership']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeMembershipNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-membership not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_membership_insert_trigger
|
||||
before insert
|
||||
on hs_office_membership
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new memberships
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeMembershipNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,56 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single membership test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeMembershipTestData(
|
||||
forPartnerTradeName varchar,
|
||||
forMainDebitorNumberSuffix numeric,
|
||||
newMemberNumberSuffix char(2) )
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
relatedPartner hs_office_partner;
|
||||
relatedDebitor hs_office_debitor;
|
||||
begin
|
||||
idName := cleanIdentifier( forPartnerTradeName || '#' || forMainDebitorNumberSuffix);
|
||||
currentTask := 'creating Membership test-data ' || idName;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select partner.* from hs_office_partner partner
|
||||
join hs_office_person person on person.uuid = partner.personUuid
|
||||
where person.tradeName = forPartnerTradeName into relatedPartner;
|
||||
select d.* from hs_office_debitor d
|
||||
where d.partneruuid = relatedPartner.uuid
|
||||
and d.debitorNumberSuffix = forMainDebitorNumberSuffix
|
||||
into relatedDebitor;
|
||||
|
||||
raise notice 'creating test Membership: %', idName;
|
||||
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
|
||||
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
|
||||
insert
|
||||
into hs_office_membership (uuid, partneruuid, maindebitoruuid, memberNumberSuffix, validity, reasonfortermination)
|
||||
values (uuid_generate_v4(), relatedPartner.uuid, relatedDebitor.uuid, newMemberNumberSuffix, daterange('20221001' , null, '[]'), 'NONE');
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-membership-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeMembershipTestData('First GmbH', 11, '01');
|
||||
call createHsOfficeMembershipTestData('Second e.K.', 12, '02');
|
||||
call createHsOfficeMembershipTestData('Third OHG', 13, '03');
|
||||
end;
|
||||
$$;
|
||||
--//
|
@@ -1,29 +0,0 @@
|
||||
### hs_office_coopSharesTransaction RBAC
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph hsOfficeMembership
|
||||
direction TB
|
||||
style hsOfficeMembership fill:#eee
|
||||
|
||||
role:hsOfficeMembership.owner[membership.admin]
|
||||
--> role:hsOfficeMembership.admin[membership.admin]
|
||||
--> role:hsOfficeMembership.agent[membership.agent]
|
||||
--> role:hsOfficeMembership.tenant[membership.tenant]
|
||||
--> role:hsOfficeMembership.guest[membership.guest]
|
||||
|
||||
role:hsOfficePartner.agent --> role:hsOfficeMembership.agent
|
||||
end
|
||||
|
||||
subgraph hsOfficeCoopSharesTransaction
|
||||
|
||||
role:hsOfficeMembership.admin
|
||||
--> perm:hsOfficeCoopSharesTransaction.create{{coopSharesTx.create}}
|
||||
|
||||
role:hsOfficeMembership.agent
|
||||
--> perm:hsOfficeCoopSharesTransaction.view{{coopSharesTx.view}}
|
||||
end
|
||||
|
||||
|
||||
```
|
@@ -1,126 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopSharesTransaction-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_coopSharesTransaction');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopSharesTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeCoopSharesTransaction', 'hs_office_coopSharesTransaction');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopSharesTransaction-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the permissions for coopSharesTransaction entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeCoopSharesTransactionRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
newHsOfficeMembership hs_office_membership;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- 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(hsOfficeMembershipTenant(newHsOfficeMembership), 'fail'),
|
||||
createPermissions(NEW.uuid, array ['view'])
|
||||
);
|
||||
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeCoopSharesTransaction_Trigger
|
||||
after insert
|
||||
on hs_office_coopSharesTransaction
|
||||
for each row
|
||||
execute procedure hsOfficeCoopSharesTransactionRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopSharesTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_coopSharesTransaction',
|
||||
idNameExpression => '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.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-coopSharesTransaction permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopsharestransaction']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-coopsharestransaction not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_coopSharesTransaction_insert_trigger
|
||||
before insert
|
||||
on hs_office_coopSharesTransaction
|
||||
for each row
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@@ -1,29 +0,0 @@
|
||||
### hs_office_coopAssetsTransaction RBAC
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
|
||||
subgraph hsOfficeMembership
|
||||
direction TB
|
||||
style hsOfficeMembership fill:#eee
|
||||
|
||||
role:hsOfficeMembership.owner[membership.admin]
|
||||
--> role:hsOfficeMembership.admin[membership.admin]
|
||||
--> role:hsOfficeMembership.agent[membership.agent]
|
||||
--> role:hsOfficeMembership.tenant[membership.tenant]
|
||||
--> role:hsOfficeMembership.guest[membership.guest]
|
||||
|
||||
role:hsOfficePartner.agent --> role:hsOfficeMembership.agent
|
||||
end
|
||||
|
||||
subgraph hsOfficeCoopAssetsTransaction
|
||||
|
||||
role:hsOfficeMembership.admin
|
||||
--> perm:hsOfficeCoopAssetsTransaction.create{{coopAssetsTx.create}}
|
||||
|
||||
role:hsOfficeMembership.agent
|
||||
--> perm:hsOfficeCoopAssetsTransaction.view{{coopAssetsTx.view}}
|
||||
end
|
||||
|
||||
|
||||
```
|
@@ -1,126 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopAssetsTransaction-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_coopAssetsTransaction');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopAssetsTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeCoopAssetsTransaction', 'hs_office_coopAssetsTransaction');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopAssetsTransaction-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the permissions for coopAssetsTransaction entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeCoopAssetsTransactionRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
newHsOfficeMembership hs_office_membership;
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- 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(hsOfficeMembershipTenant(newHsOfficeMembership), 'fail'),
|
||||
createPermissions(NEW.uuid, array ['view'])
|
||||
);
|
||||
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeCoopAssetsTransaction_Trigger
|
||||
after insert
|
||||
on hs_office_coopAssetsTransaction
|
||||
for each row
|
||||
execute procedure hsOfficeCoopAssetsTransactionRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-coopAssetsTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_coopAssetsTransaction',
|
||||
idNameExpression => '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.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addCustomerPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-coopAssetsTransaction permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopassetstransaction']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeCoopAssetsTransactionNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-coopassetstransaction not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new customer.
|
||||
*/
|
||||
create trigger hs_office_coopAssetsTransaction_insert_trigger
|
||||
before insert
|
||||
on hs_office_coopAssetsTransaction
|
||||
for each row
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeCoopAssetsTransactionNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
45
src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.md
Normal file
45
src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.md
Normal file
@@ -0,0 +1,45 @@
|
||||
### rbac contact
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph contact["`**contact**`"]
|
||||
direction TB
|
||||
style contact fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
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]]
|
||||
end
|
||||
|
||||
subgraph contact:permissions[ ]
|
||||
style contact:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:contact:DELETE{{contact:DELETE}}
|
||||
perm:contact:UPDATE{{contact:UPDATE}}
|
||||
perm:contact:SELECT{{contact:SELECT}}
|
||||
perm:contact:INSERT{{contact:INSERT}}
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
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
|
||||
|
||||
%% 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
|
||||
|
||||
```
|
146
src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql
Normal file
146
src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql
Normal file
@@ -0,0 +1,146 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_contact');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficeContact(
|
||||
NEW hs_office_contact
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeContactOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeContactREFERRER(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficeContactADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_contact row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficeContact_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficeContact(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficeContact_tg
|
||||
after insert on hs_office_contact
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficeContact_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_contact permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_contact permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_contact'),
|
||||
globalGUEST());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_contact INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_contact_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'),
|
||||
globalGUEST());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_contact_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_contact_global_insert_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_contact',
|
||||
$idName$
|
||||
label
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_contact',
|
||||
$orderBy$
|
||||
label
|
||||
$orderBy$,
|
||||
$updates$
|
||||
label = new.label,
|
||||
postalAddress = new.postalAddress,
|
||||
emailAddresses = new.emailAddresses,
|
||||
phoneNumbers = new.phoneNumbers
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -24,7 +24,6 @@ create table if not exists hs_office_person
|
||||
givenName varchar(48),
|
||||
familyName varchar(48)
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
@@ -0,0 +1,45 @@
|
||||
### rbac person
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph person["`**person**`"]
|
||||
direction TB
|
||||
style person fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph person:roles[ ]
|
||||
style person:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:person:OWNER[[person:OWNER]]
|
||||
role:person:ADMIN[[person:ADMIN]]
|
||||
role:person:REFERRER[[person:REFERRER]]
|
||||
end
|
||||
|
||||
subgraph person:permissions[ ]
|
||||
style person:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:person:INSERT{{person:INSERT}}
|
||||
perm:person:DELETE{{person:DELETE}}
|
||||
perm:person:UPDATE{{person:UPDATE}}
|
||||
perm:person:SELECT{{person:SELECT}}
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==> role:person:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN ==> role:person:OWNER
|
||||
role:person:OWNER ==> role:person:ADMIN
|
||||
role:person:ADMIN ==> role:person:REFERRER
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:GUEST ==> perm:person:INSERT
|
||||
role:person:OWNER ==> perm:person:DELETE
|
||||
role:person:ADMIN ==> perm:person:UPDATE
|
||||
role:person:REFERRER ==> perm:person:SELECT
|
||||
|
||||
```
|
146
src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql
Normal file
146
src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql
Normal file
@@ -0,0 +1,146 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_person');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficePerson(
|
||||
NEW hs_office_person
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficePersonOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficePersonREFERRER(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficePersonADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_person row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficePerson_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficePerson(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficePerson_tg
|
||||
after insert on hs_office_person
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficePerson_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_person permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_person permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_person'),
|
||||
globalGUEST());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_person INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_person_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_person'),
|
||||
globalGUEST());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_person_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_person_global_insert_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_person',
|
||||
$idName$
|
||||
concat(tradeName, familyName, givenName)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_person',
|
||||
$orderBy$
|
||||
concat(tradeName, familyName, givenName)
|
||||
$orderBy$,
|
||||
$updates$
|
||||
personType = new.personType,
|
||||
tradeName = new.tradeName,
|
||||
givenName = new.givenName,
|
||||
familyName = new.familyName
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -28,7 +28,7 @@ begin
|
||||
call defineContext(currentTask, null, emailAddr);
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
raise notice 'creating test person: %', fullName;
|
||||
raise notice 'creating test person: % by %', fullName, emailAddr;
|
||||
insert
|
||||
into hs_office_person (persontype, tradename, givenname, familyname)
|
||||
values (newPersonType, newTradeName, newGivenName, newFamilyName);
|
||||
@@ -67,9 +67,10 @@ do language plpgsql $$
|
||||
call createHsOfficePersonTestData('NP', null, 'Fouler', 'Ellie');
|
||||
call createHsOfficePersonTestData('LP', 'Second e.K.', 'Smith', 'Peter');
|
||||
call createHsOfficePersonTestData('IF', 'Third OHG');
|
||||
call createHsOfficePersonTestData('IF', 'Fourth eG');
|
||||
call createHsOfficePersonTestData('LP', 'Fourth eG');
|
||||
call createHsOfficePersonTestData('UF', 'Erben Bessler', 'Mel', 'Bessler');
|
||||
call createHsOfficePersonTestData('NP', null, 'Bessler', 'Anita');
|
||||
call createHsOfficePersonTestData('NP', null, 'Bessler', 'Bert');
|
||||
call createHsOfficePersonTestData('NP', null, 'Winkler', 'Paul');
|
||||
end;
|
||||
$$;
|
@@ -0,0 +1,36 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficeRelationType AS ENUM (
|
||||
'UNKNOWN',
|
||||
'PARTNER',
|
||||
'EX_PARTNER',
|
||||
'REPRESENTATIVE',
|
||||
'DEBITOR',
|
||||
'VIP_CONTACT',
|
||||
'OPERATIONS',
|
||||
'SUBSCRIBER');
|
||||
|
||||
CREATE CAST (character varying as HsOfficeRelationType) WITH INOUT AS IMPLICIT;
|
||||
|
||||
create table if not exists hs_office_relation
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
|
||||
anchorUuid uuid not null references hs_office_person(uuid),
|
||||
holderUuid uuid not null references hs_office_person(uuid),
|
||||
contactUuid uuid references hs_office_contact(uuid),
|
||||
type HsOfficeRelationType not null,
|
||||
mark varchar(24)
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_relation');
|
||||
--//
|
102
src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md
Normal file
102
src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md
Normal file
@@ -0,0 +1,102 @@
|
||||
### rbac relation
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph holderPerson["`**holderPerson**`"]
|
||||
direction TB
|
||||
style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph holderPerson:roles[ ]
|
||||
style holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:holderPerson:OWNER[[holderPerson:OWNER]]
|
||||
role:holderPerson:ADMIN[[holderPerson:ADMIN]]
|
||||
role:holderPerson:REFERRER[[holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph anchorPerson["`**anchorPerson**`"]
|
||||
direction TB
|
||||
style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph anchorPerson:roles[ ]
|
||||
style anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:anchorPerson:OWNER[[anchorPerson:OWNER]]
|
||||
role:anchorPerson:ADMIN[[anchorPerson:ADMIN]]
|
||||
role:anchorPerson:REFERRER[[anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph contact["`**contact**`"]
|
||||
direction TB
|
||||
style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph contact:roles[ ]
|
||||
style contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:contact:OWNER[[contact:OWNER]]
|
||||
role:contact:ADMIN[[contact:ADMIN]]
|
||||
role:contact:REFERRER[[contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph relation["`**relation**`"]
|
||||
direction TB
|
||||
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph relation:roles[ ]
|
||||
style relation:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:relation:OWNER[[relation:OWNER]]
|
||||
role:relation:ADMIN[[relation:ADMIN]]
|
||||
role:relation:AGENT[[relation:AGENT]]
|
||||
role:relation:TENANT[[relation:TENANT]]
|
||||
end
|
||||
|
||||
subgraph relation:permissions[ ]
|
||||
style relation:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:relation:DELETE{{relation:DELETE}}
|
||||
perm:relation:UPDATE{{relation:UPDATE}}
|
||||
perm:relation:SELECT{{relation:SELECT}}
|
||||
perm:relation:INSERT{{relation:INSERT}}
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==> role:relation:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:anchorPerson:OWNER
|
||||
role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN
|
||||
role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:holderPerson:OWNER
|
||||
role:holderPerson:OWNER -.-> role:holderPerson:ADMIN
|
||||
role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:contact:OWNER
|
||||
role:contact:OWNER -.-> role:contact:ADMIN
|
||||
role:contact:ADMIN -.-> role:contact:REFERRER
|
||||
role:global:ADMIN ==> role:relation:OWNER
|
||||
role:relation:OWNER ==> role:relation:ADMIN
|
||||
role:anchorPerson:ADMIN ==> role:relation:ADMIN
|
||||
role:relation:ADMIN ==> role:relation:AGENT
|
||||
role:holderPerson:ADMIN ==> role:relation:AGENT
|
||||
role:relation:AGENT ==> role:relation:TENANT
|
||||
role:holderPerson:ADMIN ==> role:relation:TENANT
|
||||
role:contact:ADMIN ==> role:relation:TENANT
|
||||
role:relation:TENANT ==> role:anchorPerson:REFERRER
|
||||
role:relation:TENANT ==> role:holderPerson:REFERRER
|
||||
role:relation:TENANT ==> role:contact:REFERRER
|
||||
|
||||
%% granting permissions to roles
|
||||
role:relation:OWNER ==> perm:relation:DELETE
|
||||
role:relation:ADMIN ==> perm:relation:UPDATE
|
||||
role:relation:TENANT ==> perm:relation:SELECT
|
||||
role:anchorPerson:ADMIN ==> perm:relation:INSERT
|
||||
|
||||
```
|
271
src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql
Normal file
271
src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql
Normal file
@@ -0,0 +1,271 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_relation');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeRelation', 'hs_office_relation');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficeRelation(
|
||||
NEW hs_office_relation
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newHolderPerson hs_office_person;
|
||||
newAnchorPerson hs_office_person;
|
||||
newContact hs_office_contact;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson;
|
||||
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
|
||||
|
||||
SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson;
|
||||
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
|
||||
|
||||
SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact;
|
||||
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePersonADMIN(newAnchorPerson),
|
||||
hsOfficeRelationOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationAGENT(NEW),
|
||||
incomingSuperRoles => array[
|
||||
hsOfficePersonADMIN(newHolderPerson),
|
||||
hsOfficeRelationADMIN(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeRelationTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeContactADMIN(newContact),
|
||||
hsOfficePersonADMIN(newHolderPerson),
|
||||
hsOfficeRelationAGENT(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeContactREFERRER(newContact),
|
||||
hsOfficePersonREFERRER(newAnchorPerson),
|
||||
hsOfficePersonREFERRER(newHolderPerson)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_relation row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficeRelation_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficeRelation(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficeRelation_tg
|
||||
after insert on hs_office_relation
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficeRelation_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-update-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||
*/
|
||||
|
||||
create or replace procedure updateRbacRulesForHsOfficeRelation(
|
||||
OLD hs_office_relation,
|
||||
NEW hs_office_relation
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
oldHolderPerson hs_office_person;
|
||||
newHolderPerson hs_office_person;
|
||||
oldAnchorPerson hs_office_person;
|
||||
newAnchorPerson hs_office_person;
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM hs_office_person WHERE uuid = OLD.holderUuid INTO oldHolderPerson;
|
||||
assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid);
|
||||
|
||||
SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson;
|
||||
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
|
||||
|
||||
SELECT * FROM hs_office_person WHERE uuid = OLD.anchorUuid INTO oldAnchorPerson;
|
||||
assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid);
|
||||
|
||||
SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson;
|
||||
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
|
||||
|
||||
SELECT * FROM hs_office_contact WHERE uuid = OLD.contactUuid INTO oldContact;
|
||||
assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid);
|
||||
|
||||
SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact;
|
||||
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
|
||||
|
||||
|
||||
if NEW.contactUuid <> OLD.contactUuid then
|
||||
|
||||
call revokeRoleFromRole(hsOfficeRelationTENANT(OLD), hsOfficeContactADMIN(oldContact));
|
||||
call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact));
|
||||
|
||||
call revokeRoleFromRole(hsOfficeContactREFERRER(oldContact), hsOfficeRelationTENANT(OLD));
|
||||
call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_relation row.
|
||||
*/
|
||||
|
||||
create or replace function updateTriggerForHsOfficeRelation_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call updateRbacRulesForHsOfficeRelation(OLD, NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger updateTriggerForHsOfficeRelation_tg
|
||||
after update on hs_office_relation
|
||||
for each row
|
||||
execute procedure updateTriggerForHsOfficeRelation_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_relation permissions for the related hs_office_person rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row hs_office_person;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_relation permissions for the related hs_office_person rows');
|
||||
|
||||
FOR row IN SELECT * FROM hs_office_person
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_relation'),
|
||||
hsOfficePersonADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_relation INSERT permission to specified role of new hs_office_person rows.
|
||||
*/
|
||||
create or replace function hs_office_relation_hs_office_person_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'),
|
||||
hsOfficePersonADMIN(NEW));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_relation_hs_office_person_insert_tg
|
||||
after insert on hs_office_person
|
||||
for each row
|
||||
execute procedure hs_office_relation_hs_office_person_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_relation,
|
||||
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_relation_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_relation_insert_permission_check_tg
|
||||
before insert on hs_office_relation
|
||||
for each row
|
||||
when ( not hasInsertPermission(NEW.anchorUuid, 'INSERT', 'hs_office_relation') )
|
||||
execute procedure hs_office_relation_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_relation',
|
||||
$idName$
|
||||
(select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|
||||
|| '-with-' || target.type || '-'
|
||||
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_relation',
|
||||
$orderBy$
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
|
||||
$orderBy$,
|
||||
$updates$
|
||||
contactUuid = new.contactUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
113
src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql
Normal file
113
src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql
Normal file
@@ -0,0 +1,113 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single relation test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeRelationTestData(
|
||||
holderPersonName varchar,
|
||||
relationType HsOfficeRelationType,
|
||||
anchorPersonName varchar,
|
||||
contactLabel varchar,
|
||||
mark varchar default null)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
anchorPerson hs_office_person;
|
||||
holderPerson hs_office_person;
|
||||
contact hs_office_contact;
|
||||
|
||||
begin
|
||||
idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName);
|
||||
currentTask := 'creating relation test-data ' || idName;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select p.*
|
||||
into anchorPerson
|
||||
from hs_office_person p
|
||||
where p.tradeName = anchorPersonName or p.familyName = anchorPersonName;
|
||||
if anchorPerson is null then
|
||||
raise exception 'anchorPerson "%" not found', anchorPersonName;
|
||||
end if;
|
||||
|
||||
select p.*
|
||||
into holderPerson
|
||||
from hs_office_person p
|
||||
where p.tradeName = holderPersonName or p.familyName = holderPersonName;
|
||||
if holderPerson is null then
|
||||
raise exception 'holderPerson "%" not found', holderPersonName;
|
||||
end if;
|
||||
|
||||
select c.* into contact from hs_office_contact c where c.label = contactLabel;
|
||||
if contact is null then
|
||||
raise exception 'contact "%" not found', contactLabel;
|
||||
end if;
|
||||
|
||||
raise notice 'creating test relation: %', idName;
|
||||
raise notice '- using anchor person (%): %', anchorPerson.uuid, anchorPerson;
|
||||
raise notice '- using holder person (%): %', holderPerson.uuid, holderPerson;
|
||||
raise notice '- using contact (%): %', contact.uuid, contact;
|
||||
insert
|
||||
into hs_office_relation (uuid, anchoruuid, holderuuid, type, mark, contactUuid)
|
||||
values (uuid_generate_v4(), anchorPerson.uuid, holderPerson.uuid, relationType, mark, contact.uuid);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
/*
|
||||
Creates a range of test relation for mass data generation.
|
||||
*/
|
||||
create or replace procedure createHsOfficeRelationTestData(
|
||||
startCount integer, -- count of auto generated rows before the run
|
||||
endCount integer -- count of auto generated rows after the run
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
person hs_office_person;
|
||||
contact hs_office_contact;
|
||||
begin
|
||||
for t in startCount..endCount
|
||||
loop
|
||||
select p.* from hs_office_person p where tradeName = intToVarChar(t, 4) into person;
|
||||
select c.* from hs_office_contact c where c.label = intToVarChar(t, 4) || '#' || t into contact;
|
||||
|
||||
call createHsOfficeRelationTestData(person.uuid, contact.uuid, 'REPRESENTATIVE');
|
||||
commit;
|
||||
end loop;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeRelationTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
|
||||
call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
||||
call createHsOfficeRelationTestData('First GmbH', 'DEBITOR', 'First GmbH', 'first contact');
|
||||
|
||||
call createHsOfficeRelationTestData('Second e.K.', 'PARTNER', 'Hostsharing eG', 'second contact');
|
||||
call createHsOfficeRelationTestData('Smith', 'REPRESENTATIVE', 'Second e.K.', 'second contact');
|
||||
call createHsOfficeRelationTestData('Second e.K.', 'DEBITOR', 'Second e.K.', 'second contact');
|
||||
|
||||
call createHsOfficeRelationTestData('Third OHG', 'PARTNER', 'Hostsharing eG', 'third contact');
|
||||
call createHsOfficeRelationTestData('Tucker', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
||||
call createHsOfficeRelationTestData('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
|
||||
|
||||
call createHsOfficeRelationTestData('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact');
|
||||
call createHsOfficeRelationTestData('Fouler', 'REPRESENTATIVE', 'Third OHG', 'third contact');
|
||||
call createHsOfficeRelationTestData('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
|
||||
|
||||
call createHsOfficeRelationTestData('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact');
|
||||
call createHsOfficeRelationTestData('Smith', 'DEBITOR', 'Smith', 'third contact');
|
||||
call createHsOfficeRelationTestData('Smith', 'SUBSCRIBER', 'Third OHG', 'third contact', 'members-announce');
|
||||
end;
|
||||
$$;
|
||||
--//
|
@@ -33,23 +33,20 @@ create table hs_office_partner
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
partnerNumber numeric(5) unique not null,
|
||||
partnerRoleUuid uuid not null references hs_office_relationship(uuid), -- TODO: delete in after delete trigger
|
||||
personUuid uuid not null references hs_office_person(uuid), -- TODO: remove, replaced by partnerRoleUuid
|
||||
contactUuid uuid not null references hs_office_contact(uuid), -- TODO: remove, replaced by partnerRoleUuid
|
||||
partnerRelUuid uuid not null references hs_office_relation(uuid), -- deleted in after delete trigger
|
||||
detailsUuid uuid not null references hs_office_partner_details(uuid) -- deleted in after delete trigger
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-DELETE-DETAILS-TRIGGER:1 endDelimiter:--//
|
||||
--changeset hs-office-partner-DELETE-DEPENDENTS-TRIGGER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Trigger function to delete related details of a partner to delete.
|
||||
*/
|
||||
create or replace function deleteHsOfficeDetailsOnPartnerDelete()
|
||||
create or replace function deleteHsOfficeDependentsOnPartnerDelete()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
@@ -61,17 +58,24 @@ begin
|
||||
if counter = 0 then
|
||||
raise exception 'partner details % could not be deleted', OLD.detailsUuid;
|
||||
end if;
|
||||
|
||||
DELETE FROM hs_office_relation r WHERE r.uuid = OLD.partnerRelUuid;
|
||||
GET DIAGNOSTICS counter = ROW_COUNT;
|
||||
if counter = 0 then
|
||||
raise exception 'partner relation % could not be deleted', OLD.partnerRelUuid;
|
||||
end if;
|
||||
|
||||
RETURN OLD;
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Triggers deletion of related details of a partner to delete.
|
||||
Triggers deletion of related rows of a partner to delete.
|
||||
*/
|
||||
create trigger hs_office_partner_delete_details_trigger
|
||||
create trigger hs_office_partner_delete_dependents_trigger
|
||||
after delete
|
||||
on hs_office_partner
|
||||
for each row
|
||||
execute procedure deleteHsOfficeDetailsOnPartnerDelete();
|
||||
execute procedure deleteHsOfficeDependentsOnPartnerDelete();
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
120
src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md
Normal file
120
src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md
Normal file
@@ -0,0 +1,120 @@
|
||||
### rbac partner
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph partnerRel.contact["`**partnerRel.contact**`"]
|
||||
direction TB
|
||||
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel.contact:roles[ ]
|
||||
style partnerRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]]
|
||||
role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]]
|
||||
role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partner["`**partner**`"]
|
||||
direction TB
|
||||
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partner:permissions[ ]
|
||||
style partner:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:partner:INSERT{{partner:INSERT}}
|
||||
perm:partner:DELETE{{partner:DELETE}}
|
||||
perm:partner:UPDATE{{partner:UPDATE}}
|
||||
perm:partner:SELECT{{partner:SELECT}}
|
||||
end
|
||||
|
||||
subgraph partnerRel["`**partnerRel**`"]
|
||||
direction TB
|
||||
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel:roles[ ]
|
||||
style partnerRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel:OWNER[[partnerRel:OWNER]]
|
||||
role:partnerRel:ADMIN[[partnerRel:ADMIN]]
|
||||
role:partnerRel:AGENT[[partnerRel:AGENT]]
|
||||
role:partnerRel:TENANT[[partnerRel:TENANT]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerDetails["`**partnerDetails**`"]
|
||||
direction TB
|
||||
style partnerDetails fill:#feb28c,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerDetails:permissions[ ]
|
||||
style partnerDetails:permissions fill:#feb28c,stroke:white
|
||||
|
||||
perm:partnerDetails:DELETE{{partnerDetails:DELETE}}
|
||||
perm:partnerDetails:UPDATE{{partnerDetails:UPDATE}}
|
||||
perm:partnerDetails:SELECT{{partnerDetails:SELECT}}
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel.anchorPerson:roles[ ]
|
||||
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]]
|
||||
role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]]
|
||||
role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
|
||||
direction TB
|
||||
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel.holderPerson:roles[ ]
|
||||
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]]
|
||||
role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]]
|
||||
role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER
|
||||
role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN
|
||||
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel.holderPerson:OWNER
|
||||
role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel.contact:OWNER
|
||||
role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
|
||||
role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel:OWNER
|
||||
role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
|
||||
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN
|
||||
role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
|
||||
role:partnerRel:AGENT -.-> role:partnerRel:TENANT
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT
|
||||
role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
|
||||
role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
|
||||
role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
|
||||
role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:ADMIN ==> perm:partner:INSERT
|
||||
role:partnerRel:ADMIN ==> perm:partner:DELETE
|
||||
role:partnerRel:AGENT ==> perm:partner:UPDATE
|
||||
role:partnerRel:TENANT ==> perm:partner:SELECT
|
||||
role:partnerRel:ADMIN ==> perm:partnerDetails:DELETE
|
||||
role:partnerRel:AGENT ==> perm:partnerDetails:UPDATE
|
||||
role:partnerRel:AGENT ==> perm:partnerDetails:SELECT
|
||||
|
||||
```
|
238
src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql
Normal file
238
src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql
Normal file
@@ -0,0 +1,238 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_partner');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficePartner(
|
||||
NEW hs_office_partner
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newPartnerRel hs_office_relation;
|
||||
newPartnerDetails hs_office_partner_details;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
|
||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
|
||||
|
||||
SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
|
||||
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
|
||||
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficePartner_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficePartner(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficePartner_tg
|
||||
after insert on hs_office_partner
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficePartner_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-update-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||
*/
|
||||
|
||||
create or replace procedure updateRbacRulesForHsOfficePartner(
|
||||
OLD hs_office_partner,
|
||||
NEW hs_office_partner
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
oldPartnerRel hs_office_relation;
|
||||
newPartnerRel hs_office_relation;
|
||||
oldPartnerDetails hs_office_partner_details;
|
||||
newPartnerDetails hs_office_partner_details;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM hs_office_relation WHERE uuid = OLD.partnerRelUuid INTO oldPartnerRel;
|
||||
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRelUuid = %s', OLD.partnerRelUuid);
|
||||
|
||||
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
|
||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
|
||||
|
||||
SELECT * FROM hs_office_partner_details WHERE uuid = OLD.detailsUuid INTO oldPartnerDetails;
|
||||
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s', OLD.detailsUuid);
|
||||
|
||||
SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
|
||||
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
|
||||
|
||||
|
||||
if NEW.partnerRelUuid <> OLD.partnerRelUuid then
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTENANT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_partner row.
|
||||
*/
|
||||
|
||||
create or replace function updateTriggerForHsOfficePartner_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call updateRbacRulesForHsOfficePartner(OLD, NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger updateTriggerForHsOfficePartner_tg
|
||||
after update on hs_office_partner
|
||||
for each row
|
||||
execute procedure updateTriggerForHsOfficePartner_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_partner permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_partner permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_partner'),
|
||||
globalADMIN());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_partner INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_partner_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'),
|
||||
globalADMIN());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_partner_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_partner_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function hs_office_partner_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_partner not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_partner_insert_permission_check_tg
|
||||
before insert on hs_office_partner
|
||||
for each row
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure hs_office_partner_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_partner',
|
||||
$idName$
|
||||
'P-' || partnerNumber
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_partner',
|
||||
$orderBy$
|
||||
'P-' || partnerNumber
|
||||
$orderBy$,
|
||||
$updates$
|
||||
partnerRelUuid = new.partnerRelUuid
|
||||
$updates$);
|
||||
--//
|
||||
|
23
src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.md
Normal file
23
src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.md
Normal file
@@ -0,0 +1,23 @@
|
||||
### rbac partnerDetails
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph partnerDetails["`**partnerDetails**`"]
|
||||
direction TB
|
||||
style partnerDetails fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerDetails:permissions[ ]
|
||||
style partnerDetails:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:partnerDetails:INSERT{{partnerDetails:INSERT}}
|
||||
end
|
||||
end
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:ADMIN ==> perm:partnerDetails:INSERT
|
||||
|
||||
```
|
150
src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql
Normal file
150
src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql
Normal file
@@ -0,0 +1,150 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_partner_details');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePartnerDetails', 'hs_office_partner_details');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficePartnerDetails(
|
||||
NEW hs_office_partner_details
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner_details row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficePartnerDetails_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficePartnerDetails(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficePartnerDetails_tg
|
||||
after insert on hs_office_partner_details
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficePartnerDetails_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_partner_details permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_partner_details permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'),
|
||||
globalADMIN());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_partner_details INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_partner_details_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'),
|
||||
globalADMIN());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_partner_details_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_partner_details_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function hs_office_partner_details_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_partner_details_insert_permission_check_tg
|
||||
before insert on hs_office_partner_details
|
||||
for each row
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure hs_office_partner_details_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromQuery('hs_office_partner_details',
|
||||
$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
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_partner_details',
|
||||
$orderBy$
|
||||
uuid
|
||||
$orderBy$,
|
||||
$updates$
|
||||
registrationOffice = new.registrationOffice,
|
||||
registrationNumber = new.registrationNumber,
|
||||
birthPlace = new.birthPlace,
|
||||
birthName = new.birthName,
|
||||
birthday = new.birthday,
|
||||
dateOfDeath = new.dateOfDeath
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -9,23 +9,22 @@
|
||||
Creates a single partner test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficePartnerTestData(
|
||||
mandantTradeName varchar,
|
||||
partnerNumber numeric(5),
|
||||
mandantTradeName varchar,
|
||||
newPartnerNumber numeric(5),
|
||||
partnerPersonName varchar,
|
||||
contactLabel varchar )
|
||||
contactLabel varchar )
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
mandantPerson hs_office_person;
|
||||
partnerRole hs_office_relationship;
|
||||
partnerRel hs_office_relation;
|
||||
relatedPerson hs_office_person;
|
||||
relatedContact hs_office_contact;
|
||||
relatedDetailsUuid uuid;
|
||||
begin
|
||||
idName := cleanIdentifier( partnerPersonName|| '-' || contactLabel);
|
||||
currentTask := 'creating partner test-data ' || idName;
|
||||
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);
|
||||
|
||||
select p.* from hs_office_person p
|
||||
@@ -38,22 +37,18 @@ begin
|
||||
select p.* from hs_office_person p
|
||||
where p.tradeName = partnerPersonName or p.familyName = partnerPersonName
|
||||
into relatedPerson;
|
||||
select c.* from hs_office_contact c
|
||||
where c.label = contactLabel
|
||||
into relatedContact;
|
||||
|
||||
select r.* from hs_office_relationship r
|
||||
where r.reltype = 'PARTNER'
|
||||
and r.relanchoruuid = mandantPerson.uuid and r.relholderuuid = relatedPerson.uuid
|
||||
into partnerRole;
|
||||
if partnerRole is null then
|
||||
raise exception 'partnerRole "%"-"%" not found', mandantPerson.tradename, partnerPersonName;
|
||||
select r.* from hs_office_relation r
|
||||
where r.type = 'PARTNER'
|
||||
and r.anchoruuid = mandantPerson.uuid and r.holderuuid = relatedPerson.uuid
|
||||
into partnerRel;
|
||||
if partnerRel is null then
|
||||
raise exception 'partnerRel "%"-"%" not found', mandantPerson.tradename, partnerPersonName;
|
||||
end if;
|
||||
|
||||
raise notice 'creating test partner: %', idName;
|
||||
raise notice '- using partnerRole (%): %', partnerRole.uuid, partnerRole;
|
||||
raise notice '- using partnerRel (%): %', partnerRel.uuid, partnerRel;
|
||||
raise notice '- using person (%): %', relatedPerson.uuid, relatedPerson;
|
||||
raise notice '- using contact (%): %', relatedContact.uuid, relatedContact;
|
||||
|
||||
if relatedPerson.persontype = 'NP' then
|
||||
insert
|
||||
@@ -68,8 +63,8 @@ begin
|
||||
end if;
|
||||
|
||||
insert
|
||||
into hs_office_partner (uuid, partnerNumber, partnerRoleUuid, personuuid, contactuuid, detailsUuid)
|
||||
values (uuid_generate_v4(), partnerNumber, partnerRole.uuid, relatedPerson.uuid, relatedContact.uuid, relatedDetailsUuid);
|
||||
into hs_office_partner (uuid, partnerNumber, partnerRelUuid, detailsUuid)
|
||||
values (uuid_generate_v4(), newPartnerNumber, partnerRel.uuid, relatedDetailsUuid);
|
||||
end; $$;
|
||||
--//
|
||||
|
45
src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.md
Normal file
45
src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.md
Normal file
@@ -0,0 +1,45 @@
|
||||
### rbac bankAccount
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph bankAccount["`**bankAccount**`"]
|
||||
direction TB
|
||||
style bankAccount fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph bankAccount:roles[ ]
|
||||
style bankAccount:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:bankAccount:OWNER[[bankAccount:OWNER]]
|
||||
role:bankAccount:ADMIN[[bankAccount:ADMIN]]
|
||||
role:bankAccount:REFERRER[[bankAccount:REFERRER]]
|
||||
end
|
||||
|
||||
subgraph bankAccount:permissions[ ]
|
||||
style bankAccount:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:bankAccount:INSERT{{bankAccount:INSERT}}
|
||||
perm:bankAccount:DELETE{{bankAccount:DELETE}}
|
||||
perm:bankAccount:UPDATE{{bankAccount:UPDATE}}
|
||||
perm:bankAccount:SELECT{{bankAccount:SELECT}}
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==> role:bankAccount:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN ==> role:bankAccount:OWNER
|
||||
role:bankAccount:OWNER ==> role:bankAccount:ADMIN
|
||||
role:bankAccount:ADMIN ==> role:bankAccount:REFERRER
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:GUEST ==> perm:bankAccount:INSERT
|
||||
role:bankAccount:OWNER ==> perm:bankAccount:DELETE
|
||||
role:bankAccount:ADMIN ==> perm:bankAccount:UPDATE
|
||||
role:bankAccount:REFERRER ==> perm:bankAccount:SELECT
|
||||
|
||||
```
|
145
src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql
Normal file
145
src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql
Normal file
@@ -0,0 +1,145 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_bankaccount');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeBankAccount', 'hs_office_bankaccount');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficeBankAccount(
|
||||
NEW hs_office_bankaccount
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeBankAccountOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeBankAccountREFERRER(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficeBankAccountADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_bankaccount row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficeBankAccount_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficeBankAccount(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficeBankAccount_tg
|
||||
after insert on hs_office_bankaccount
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficeBankAccount_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_bankaccount permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_bankaccount permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_bankaccount'),
|
||||
globalGUEST());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_bankaccount INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_bankaccount_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'),
|
||||
globalGUEST());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_bankaccount_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_bankaccount_global_insert_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_bankaccount',
|
||||
$idName$
|
||||
iban
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_bankaccount',
|
||||
$orderBy$
|
||||
iban
|
||||
$orderBy$,
|
||||
$updates$
|
||||
holder = new.holder,
|
||||
iban = new.iban,
|
||||
bic = new.bic
|
||||
$updates$);
|
||||
--//
|
||||
|
@@ -7,10 +7,9 @@
|
||||
create table hs_office_debitor
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
partnerUuid uuid not null references hs_office_partner(uuid),
|
||||
debitorNumberSuffix char(2) not null check (debitorNumberSuffix::text ~ '^[0-9][0-9]$'),
|
||||
debitorRelUuid uuid not null references hs_office_relation(uuid),
|
||||
billable boolean not null default true,
|
||||
debitorNumberSuffix numeric(2) not null,
|
||||
billingContactUuid uuid not null references hs_office_contact(uuid),
|
||||
vatId varchar(24), -- TODO.spec: here or in person?
|
||||
vatCountryCode varchar(2),
|
||||
vatBusiness boolean not null,
|
||||
@@ -20,11 +19,43 @@ create table hs_office_debitor
|
||||
constraint check_default_prefix check (
|
||||
defaultPrefix::text ~ '^([a-z]{3}|al0|bh1|c4s|f3k|k8i|l3d|mh1|o13|p2m|s80|t4w)$'
|
||||
)
|
||||
-- TODO.impl: SEPA-mandate
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-DELETE-DEPENDENTS-TRIGGER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Trigger function to delete related rows of a debitor to delete.
|
||||
*/
|
||||
create or replace function deleteHsOfficeDependentsOnDebitorDelete()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
declare
|
||||
counter integer;
|
||||
begin
|
||||
DELETE FROM hs_office_relation r WHERE r.uuid = OLD.debitorRelUuid;
|
||||
GET DIAGNOSTICS counter = ROW_COUNT;
|
||||
if counter = 0 then
|
||||
raise exception 'debitor relation % could not be deleted', OLD.debitorRelUuid;
|
||||
end if;
|
||||
|
||||
RETURN OLD;
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Triggers deletion of related details of a debitor to delete.
|
||||
*/
|
||||
create trigger hs_office_debitor_delete_dependents_trigger
|
||||
after delete
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
execute procedure deleteHsOfficeDependentsOnDebitorDelete();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
198
src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md
Normal file
198
src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md
Normal file
@@ -0,0 +1,198 @@
|
||||
### rbac debitor
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.anchorPerson:roles[ ]
|
||||
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]]
|
||||
role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]]
|
||||
role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
|
||||
direction TB
|
||||
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.holderPerson:roles[ ]
|
||||
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]]
|
||||
role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]]
|
||||
role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
|
||||
direction TB
|
||||
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel.holderPerson:roles[ ]
|
||||
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]]
|
||||
role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]]
|
||||
role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor["`**debitor**`"]
|
||||
direction TB
|
||||
style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor:permissions[ ]
|
||||
style debitor:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:debitor:INSERT{{debitor:INSERT}}
|
||||
perm:debitor:DELETE{{debitor:DELETE}}
|
||||
perm:debitor:UPDATE{{debitor:UPDATE}}
|
||||
perm:debitor:SELECT{{debitor:SELECT}}
|
||||
end
|
||||
|
||||
subgraph debitorRel["`**debitorRel**`"]
|
||||
direction TB
|
||||
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel:roles[ ]
|
||||
style debitorRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel:OWNER[[debitorRel:OWNER]]
|
||||
role:debitorRel:ADMIN[[debitorRel:ADMIN]]
|
||||
role:debitorRel:AGENT[[debitorRel:AGENT]]
|
||||
role:debitorRel:TENANT[[debitorRel:TENANT]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerRel["`**partnerRel**`"]
|
||||
direction TB
|
||||
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel:roles[ ]
|
||||
style partnerRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel:OWNER[[partnerRel:OWNER]]
|
||||
role:partnerRel:ADMIN[[partnerRel:ADMIN]]
|
||||
role:partnerRel:AGENT[[partnerRel:AGENT]]
|
||||
role:partnerRel:TENANT[[partnerRel:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerRel.contact["`**partnerRel.contact**`"]
|
||||
direction TB
|
||||
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel.contact:roles[ ]
|
||||
style partnerRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]]
|
||||
role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]]
|
||||
role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.contact["`**debitorRel.contact**`"]
|
||||
direction TB
|
||||
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.contact:roles[ ]
|
||||
style debitorRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]]
|
||||
role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]]
|
||||
role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph partnerRel.anchorPerson:roles[ ]
|
||||
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]]
|
||||
role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]]
|
||||
role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph refundBankAccount["`**refundBankAccount**`"]
|
||||
direction TB
|
||||
style refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph refundBankAccount:roles[ ]
|
||||
style refundBankAccount:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:refundBankAccount:OWNER[[refundBankAccount:OWNER]]
|
||||
role:refundBankAccount:ADMIN[[refundBankAccount:ADMIN]]
|
||||
role:refundBankAccount:REFERRER[[refundBankAccount:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER
|
||||
role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN
|
||||
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel.holderPerson:OWNER
|
||||
role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel.contact:OWNER
|
||||
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
|
||||
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel:OWNER
|
||||
role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
|
||||
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN
|
||||
role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
|
||||
role:debitorRel:AGENT -.-> role:debitorRel:TENANT
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT
|
||||
role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:refundBankAccount:OWNER
|
||||
role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN
|
||||
role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER
|
||||
role:refundBankAccount:ADMIN ==> role:debitorRel:AGENT
|
||||
role:debitorRel:AGENT ==> role:refundBankAccount:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER
|
||||
role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN
|
||||
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel.holderPerson:OWNER
|
||||
role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel.contact:OWNER
|
||||
role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
|
||||
role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:partnerRel:OWNER
|
||||
role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
|
||||
role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN
|
||||
role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
|
||||
role:partnerRel:AGENT -.-> role:partnerRel:TENANT
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT
|
||||
role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
|
||||
role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
|
||||
role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
|
||||
role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
|
||||
role:partnerRel:ADMIN ==> role:debitorRel:ADMIN
|
||||
role:partnerRel:AGENT ==> role:debitorRel:AGENT
|
||||
role:debitorRel:AGENT ==> role:partnerRel:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:ADMIN ==> perm:debitor:INSERT
|
||||
role:debitorRel:OWNER ==> perm:debitor:DELETE
|
||||
role:debitorRel:ADMIN ==> perm:debitor:UPDATE
|
||||
role:debitorRel:TENANT ==> perm:debitor:SELECT
|
||||
|
||||
```
|
227
src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql
Normal file
227
src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql
Normal file
@@ -0,0 +1,227 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_debitor');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeDebitor', 'hs_office_debitor');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficeDebitor(
|
||||
NEW hs_office_debitor
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newPartnerRel hs_office_relation;
|
||||
newDebitorRel hs_office_relation;
|
||||
newRefundBankAccount hs_office_bankaccount;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT partnerRel.*
|
||||
FROM hs_office_relation AS partnerRel
|
||||
JOIN hs_office_relation AS debitorRel
|
||||
ON debitorRel.type = 'DEBITOR' AND debitorRel.anchorUuid = partnerRel.holderUuid
|
||||
WHERE partnerRel.type = 'PARTNER'
|
||||
AND NEW.debitorRelUuid = debitorRel.uuid
|
||||
INTO newPartnerRel;
|
||||
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
|
||||
|
||||
SELECT * FROM hs_office_relation WHERE uuid = NEW.debitorRelUuid INTO newDebitorRel;
|
||||
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
|
||||
|
||||
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.refundBankAccountUuid INTO newRefundBankAccount;
|
||||
|
||||
call grantRoleToRole(hsOfficeBankAccountREFERRER(newRefundBankAccount), hsOfficeRelationAGENT(newDebitorRel));
|
||||
call grantRoleToRole(hsOfficeRelationADMIN(newDebitorRel), hsOfficeRelationADMIN(newPartnerRel));
|
||||
call grantRoleToRole(hsOfficeRelationAGENT(newDebitorRel), hsOfficeBankAccountADMIN(newRefundBankAccount));
|
||||
call grantRoleToRole(hsOfficeRelationAGENT(newDebitorRel), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call grantRoleToRole(hsOfficeRelationTENANT(newPartnerRel), hsOfficeRelationAGENT(newDebitorRel));
|
||||
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newDebitorRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newDebitorRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newDebitorRel));
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_debitor row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficeDebitor_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficeDebitor(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficeDebitor_tg
|
||||
after insert on hs_office_debitor
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficeDebitor_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-update-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||
*/
|
||||
|
||||
create or replace procedure updateRbacRulesForHsOfficeDebitor(
|
||||
OLD hs_office_debitor,
|
||||
NEW hs_office_debitor
|
||||
)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
|
||||
if NEW.debitorRelUuid is distinct from OLD.debitorRelUuid
|
||||
or NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then
|
||||
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
|
||||
call buildRbacSystemForHsOfficeDebitor(NEW);
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_debitor row.
|
||||
*/
|
||||
|
||||
create or replace function updateTriggerForHsOfficeDebitor_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call updateRbacRulesForHsOfficeDebitor(OLD, NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger updateTriggerForHsOfficeDebitor_tg
|
||||
after update on hs_office_debitor
|
||||
for each row
|
||||
execute procedure updateTriggerForHsOfficeDebitor_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_debitor permissions for the related global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_debitor permissions for the related global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_debitor'),
|
||||
globalADMIN());
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_debitor INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function hs_office_debitor_global_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'),
|
||||
globalADMIN());
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_debitor_global_insert_tg
|
||||
after insert on global
|
||||
for each row
|
||||
execute procedure hs_office_debitor_global_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_debitor,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function hs_office_debitor_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise exception '[403] insert into hs_office_debitor not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_debitor_insert_permission_check_tg
|
||||
before insert on hs_office_debitor
|
||||
for each row
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure hs_office_debitor_insert_permission_missing_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromQuery('hs_office_debitor',
|
||||
$idName$
|
||||
SELECT debitor.uuid AS uuid,
|
||||
'D-' || (SELECT partner.partnerNumber
|
||||
FROM hs_office_partner partner
|
||||
JOIN hs_office_relation partnerRel
|
||||
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
|
||||
JOIN hs_office_relation debitorRel
|
||||
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
||||
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
||||
|| debitorNumberSuffix as idName
|
||||
FROM hs_office_debitor AS debitor
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_debitor',
|
||||
$orderBy$
|
||||
defaultPrefix
|
||||
$orderBy$,
|
||||
$updates$
|
||||
debitorRelUuid = new.debitorRelUuid,
|
||||
billable = new.billable,
|
||||
refundBankAccountUuid = new.refundBankAccountUuid,
|
||||
vatId = new.vatId,
|
||||
vatCountryCode = new.vatCountryCode,
|
||||
vatBusiness = new.vatBusiness,
|
||||
vatReverseCharge = new.vatReverseCharge,
|
||||
defaultPrefix = new.defaultPrefix
|
||||
$updates$);
|
||||
--//
|
||||
|
62
src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql
Normal file
62
src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql
Normal file
@@ -0,0 +1,62 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single debitor test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeDebitorTestData(
|
||||
withDebitorNumberSuffix numeric(5),
|
||||
forPartnerPersonName varchar,
|
||||
forBillingContactLabel varchar,
|
||||
withDefaultPrefix varchar
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
relatedDebitorRelUuid uuid;
|
||||
relatedBankAccountUuid uuid;
|
||||
begin
|
||||
idName := cleanIdentifier( forPartnerPersonName|| '-' || forBillingContactLabel);
|
||||
currentTask := 'creating debitor test-data ' || idName;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select debitorRel.uuid
|
||||
into relatedDebitorRelUuid
|
||||
from hs_office_relation debitorRel
|
||||
join hs_office_person person on person.uuid = debitorRel.holderUuid
|
||||
and (person.tradeName = forPartnerPersonName or person.familyName = forPartnerPersonName)
|
||||
where debitorRel.type = 'DEBITOR';
|
||||
|
||||
select b.uuid
|
||||
into relatedBankAccountUuid
|
||||
from hs_office_bankaccount b
|
||||
where b.holder = forPartnerPersonName;
|
||||
|
||||
raise notice 'creating test debitor: % (#%)', idName, withDebitorNumberSuffix;
|
||||
-- raise exception 'creating test debitor: (uuid=%, debitorRelUuid=%, debitornumbersuffix=%, billable=%, vatbusiness=%, vatreversecharge=%, refundbankaccountuuid=%, defaultprefix=%)',
|
||||
-- uuid_generate_v4(), relatedDebitorRelUuid, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix;
|
||||
insert
|
||||
into hs_office_debitor (uuid, debitorRelUuid, debitornumbersuffix, billable, vatbusiness, vatreversecharge, refundbankaccountuuid, defaultprefix)
|
||||
values (uuid_generate_v4(), relatedDebitorRelUuid, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeDebitorTestData(11, 'First GmbH', 'first contact', 'fir');
|
||||
call createHsOfficeDebitorTestData(12, 'Second e.K.', 'second contact', 'sec');
|
||||
call createHsOfficeDebitorTestData(13, 'Third OHG', 'third contact', 'thi');
|
||||
end;
|
||||
$$;
|
||||
--//
|
141
src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md
Normal file
141
src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md
Normal file
@@ -0,0 +1,141 @@
|
||||
### rbac sepaMandate
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph bankAccount["`**bankAccount**`"]
|
||||
direction TB
|
||||
style bankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph bankAccount:roles[ ]
|
||||
style bankAccount:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:bankAccount:OWNER[[bankAccount:OWNER]]
|
||||
role:bankAccount:ADMIN[[bankAccount:ADMIN]]
|
||||
role:bankAccount:REFERRER[[bankAccount:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.contact["`**debitorRel.contact**`"]
|
||||
direction TB
|
||||
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.contact:roles[ ]
|
||||
style debitorRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]]
|
||||
role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]]
|
||||
role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.anchorPerson:roles[ ]
|
||||
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]]
|
||||
role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]]
|
||||
role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
|
||||
direction TB
|
||||
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.holderPerson:roles[ ]
|
||||
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]]
|
||||
role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]]
|
||||
role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph sepaMandate["`**sepaMandate**`"]
|
||||
direction TB
|
||||
style sepaMandate fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph sepaMandate:roles[ ]
|
||||
style sepaMandate:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:sepaMandate:OWNER[[sepaMandate:OWNER]]
|
||||
role:sepaMandate:ADMIN[[sepaMandate:ADMIN]]
|
||||
role:sepaMandate:AGENT[[sepaMandate:AGENT]]
|
||||
role:sepaMandate:REFERRER[[sepaMandate:REFERRER]]
|
||||
end
|
||||
|
||||
subgraph sepaMandate:permissions[ ]
|
||||
style sepaMandate:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:sepaMandate:DELETE{{sepaMandate:DELETE}}
|
||||
perm:sepaMandate:UPDATE{{sepaMandate:UPDATE}}
|
||||
perm:sepaMandate:SELECT{{sepaMandate:SELECT}}
|
||||
perm:sepaMandate:INSERT{{sepaMandate:INSERT}}
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel["`**debitorRel**`"]
|
||||
direction TB
|
||||
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel:roles[ ]
|
||||
style debitorRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel:OWNER[[debitorRel:OWNER]]
|
||||
role:debitorRel:ADMIN[[debitorRel:ADMIN]]
|
||||
role:debitorRel:AGENT[[debitorRel:AGENT]]
|
||||
role:debitorRel:TENANT[[debitorRel:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to users
|
||||
user:creator ==> role:sepaMandate:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER
|
||||
role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN
|
||||
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel.holderPerson:OWNER
|
||||
role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel.contact:OWNER
|
||||
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
|
||||
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel:OWNER
|
||||
role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
|
||||
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN
|
||||
role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
|
||||
role:debitorRel:AGENT -.-> role:debitorRel:TENANT
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT
|
||||
role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:bankAccount:OWNER
|
||||
role:bankAccount:OWNER -.-> role:bankAccount:ADMIN
|
||||
role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER
|
||||
role:global:ADMIN ==> role:sepaMandate:OWNER
|
||||
role:sepaMandate:OWNER ==> role:sepaMandate:ADMIN
|
||||
role:sepaMandate:ADMIN ==> role:sepaMandate:AGENT
|
||||
role:sepaMandate:AGENT ==> role:bankAccount:REFERRER
|
||||
role:sepaMandate:AGENT ==> role:debitorRel:AGENT
|
||||
role:sepaMandate:AGENT ==> role:sepaMandate:REFERRER
|
||||
role:bankAccount:ADMIN ==> role:sepaMandate:REFERRER
|
||||
role:debitorRel:AGENT ==> role:sepaMandate:REFERRER
|
||||
role:sepaMandate:REFERRER ==> role:debitorRel:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:sepaMandate:OWNER ==> perm:sepaMandate:DELETE
|
||||
role:sepaMandate:ADMIN ==> perm:sepaMandate:UPDATE
|
||||
role:sepaMandate:REFERRER ==> perm:sepaMandate:SELECT
|
||||
role:debitorRel:ADMIN ==> perm:sepaMandate:INSERT
|
||||
|
||||
```
|
207
src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql
Normal file
207
src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql
Normal file
@@ -0,0 +1,207 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_sepamandate');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeSepaMandate', 'hs_office_sepamandate');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsOfficeSepaMandate(
|
||||
NEW hs_office_sepamandate
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newBankAccount hs_office_bankaccount;
|
||||
newDebitorRel hs_office_relation;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.bankAccountUuid INTO newBankAccount;
|
||||
assert newBankAccount.uuid is not null, format('newBankAccount must not be null for NEW.bankAccountUuid = %s', NEW.bankAccountUuid);
|
||||
|
||||
SELECT debitorRel.*
|
||||
FROM hs_office_relation debitorRel
|
||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||
WHERE debitor.uuid = NEW.debitorUuid
|
||||
INTO newDebitorRel;
|
||||
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s', NEW.debitorUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateAGENT(NEW),
|
||||
incomingSuperRoles => array[hsOfficeSepaMandateADMIN(NEW)],
|
||||
outgoingSubRoles => array[
|
||||
hsOfficeBankAccountREFERRER(newBankAccount),
|
||||
hsOfficeRelationAGENT(newDebitorRel)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsOfficeSepaMandateREFERRER(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
hsOfficeBankAccountADMIN(newBankAccount),
|
||||
hsOfficeRelationAGENT(newDebitorRel),
|
||||
hsOfficeSepaMandateAGENT(NEW)],
|
||||
outgoingSubRoles => array[hsOfficeRelationTENANT(newDebitorRel)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_sepamandate row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsOfficeSepaMandate_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsOfficeSepaMandate(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsOfficeSepaMandate_tg
|
||||
after insert on hs_office_sepamandate
|
||||
for each row
|
||||
execute procedure insertTriggerForHsOfficeSepaMandate_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row hs_office_relation;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows');
|
||||
|
||||
FOR row IN SELECT * FROM hs_office_relation
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'),
|
||||
hsOfficeRelationADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_office_sepamandate INSERT permission to specified role of new hs_office_relation rows.
|
||||
*/
|
||||
create or replace function hs_office_sepamandate_hs_office_relation_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_sepamandate'),
|
||||
hsOfficeRelationADMIN(NEW));
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_office_sepamandate_hs_office_relation_insert_tg
|
||||
after insert on hs_office_relation
|
||||
for each row
|
||||
execute procedure hs_office_sepamandate_hs_office_relation_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate,
|
||||
where the check is performed by an indirect role.
|
||||
|
||||
An indirect role is a role which depends on an object uuid which is not a direct foreign key
|
||||
of the source entity, but needs to be fetched via joined tables.
|
||||
*/
|
||||
create or replace function hs_office_sepamandate_insert_permission_check_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
superRoleObjectUuid uuid;
|
||||
|
||||
begin
|
||||
superRoleObjectUuid := (SELECT debitorRel.uuid
|
||||
FROM hs_office_relation debitorRel
|
||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||
WHERE debitor.uuid = NEW.debitorUuid
|
||||
);
|
||||
assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null';
|
||||
|
||||
if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_office_sepamandate') ) then
|
||||
raise exception
|
||||
'[403] insert into hs_office_sepamandate not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_sepamandate_insert_permission_check_tg
|
||||
before insert on hs_office_sepamandate
|
||||
for each row
|
||||
execute procedure hs_office_sepamandate_insert_permission_check_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromQuery('hs_office_sepamandate',
|
||||
$idName$
|
||||
select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName
|
||||
from hs_office_sepamandate sm
|
||||
join hs_office_bankaccount ba on ba.uuid = sm.bankAccountUuid
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_sepamandate',
|
||||
$orderBy$
|
||||
validity
|
||||
$orderBy$,
|
||||
$updates$
|
||||
reference = new.reference,
|
||||
agreement = new.agreement,
|
||||
validity = new.validity
|
||||
$updates$);
|
||||
--//
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user