introduce separate database-schemas base+rbac (#103)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Co-authored-by: Michael Hönnig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/103 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
@@ -3,13 +3,13 @@ components:
|
||||
|
||||
parameters:
|
||||
|
||||
currentUser:
|
||||
name: current-user
|
||||
currentSubject:
|
||||
name: current-subject
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
description: Identifying name of the current subject (e.g. user).
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
@@ -17,4 +17,4 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Semicolon-separated list of roles to assume. The current user needs to have the right to assume these roles.
|
||||
description: Semicolon-separated list of roles to assume. The current subject needs to have the right to assume these roles.
|
||||
|
||||
@@ -8,13 +8,13 @@ components:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user is unknown or not authorized.
|
||||
description: The current subject is unknown or not authorized.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Forbidden:
|
||||
description: The current user or none of the assumed or roles is granted access to the resource.
|
||||
description: The current subject or none of the assumed or roles is granted access to the resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
||||
@@ -3,13 +3,13 @@ components:
|
||||
|
||||
parameters:
|
||||
|
||||
currentUser:
|
||||
name: current-user
|
||||
currentSubject:
|
||||
name: current-subject
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
description: Identifying name of the currently logged in subject.
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
@@ -17,4 +17,4 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Semicolon-separated list of roles to assume. The current user needs to have the right to assume these roles.
|
||||
description: Semicolon-separated list of roles to assume. The current subject needs to have the right to assume these roles.
|
||||
|
||||
@@ -8,13 +8,13 @@ components:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user is unknown or not authorized.
|
||||
description: The current subject is unknown or not authorized.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Forbidden:
|
||||
description: The current user or none of the assumed or roles is granted access to the resource.
|
||||
description: The current subject or none of the assumed or roles is granted access to the resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single booking item its uuid, if visible for the current subject.'
|
||||
operationId: getBookingItemByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single booking item identified by its uuid, if permitted for the current subject.'
|
||||
operationId: patchBookingItem
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single booking item identified by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteBookingIemByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of all booking items for a specified project.
|
||||
description: Returns the list of all booking items for a specified project which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of all booking items for a specified project which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-booking-items
|
||||
operationId: listBookingItemsByProjectUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: projectUuid
|
||||
in: query
|
||||
@@ -34,7 +34,7 @@ post:
|
||||
- hs-booking-items
|
||||
operationId: addBookingItem
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new booking item.
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single booking project its uuid, if visible for the current subject.'
|
||||
operationId: getBookingProjectByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingProjectUuid
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single booking project identified by its uuid, if permitted for the current subject.'
|
||||
operationId: patchBookingProject
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingProjectUuid
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single booking project identified by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteBookingIemByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bookingProjectUuid
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of all booking projects for a specified debitor.
|
||||
description: Returns the list of all booking projects for a specified debitor which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of all booking projects for a specified debitor which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-booking-projects
|
||||
operationId: listBookingProjectsByDebitorUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUuid
|
||||
in: query
|
||||
@@ -34,7 +34,7 @@ post:
|
||||
- hs-booking-projects
|
||||
operationId: addBookingProject
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new booking project.
|
||||
|
||||
@@ -3,13 +3,13 @@ components:
|
||||
|
||||
parameters:
|
||||
|
||||
currentUser:
|
||||
name: current-user
|
||||
currentSubject:
|
||||
name: current-subject
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
description: Identifying name of the currently logged in subject.
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
@@ -17,4 +17,4 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Semicolon-separated list of roles to assume. The current user needs to have the right to assume these roles.
|
||||
description: Semicolon-separated list of roles to assume. The current subject needs to have the right to assume these roles.
|
||||
|
||||
@@ -8,13 +8,13 @@ components:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user is unknown or not authorized.
|
||||
description: The current subject is unknown or not authorized.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Forbidden:
|
||||
description: The current user or none of the assumed or roles is granted access to the resource.
|
||||
description: The current subject or none of the assumed or roles is granted access to the resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single managed asset by its uuid, if visible for the current subject.'
|
||||
operationId: getAssetByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: assetUuid
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single hosting asset identified by its uuid, if permitted for the current subject.'
|
||||
operationId: patchAsset
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: assetUuid
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single hosting asset identified by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteAssetUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: assetUuid
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a filtered list of all hosting assets.
|
||||
description: Returns the list of all hosting assets which match the given filters and are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of all hosting assets which match the given filters and are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-hosting-assets
|
||||
operationId: listAssets
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: projectUuid
|
||||
in: query
|
||||
@@ -47,7 +47,7 @@ post:
|
||||
- hs-hosting-assets
|
||||
operationId: addAsset
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new hosting asset.
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single bank account by its uuid, if visible for the current subject.'
|
||||
operationId: getBankAccountByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bankAccountUUID
|
||||
in: path
|
||||
@@ -31,7 +31,7 @@ delete:
|
||||
description: 'Delete a single bank account by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteBankAccountByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: bankAccountUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) bankaccounts.
|
||||
description: Returns the list of (optionally filtered) bankaccounts which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) bankaccounts which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-bank-accounts
|
||||
operationId: listBankAccounts
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: holder
|
||||
in: query
|
||||
@@ -33,7 +33,7 @@ post:
|
||||
- hs-office-bank-accounts
|
||||
operationId: addBankAccount
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single business contact by its uuid, if visible for the current subject.'
|
||||
operationId: getContactByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: contactUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single contact by its uuid, if permitted for the current subject.'
|
||||
operationId: patchContact
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: contactUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single business contact by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteContactByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: contactUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) contacts.
|
||||
description: Returns the list of (optionally filtered) contacts which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) contacts which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-contacts
|
||||
operationId: listContacts
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
@@ -33,7 +33,7 @@ post:
|
||||
- hs-office-contacts
|
||||
operationId: addContact
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single asset transaction by its uuid, if visible for the current subject.'
|
||||
operationId: getCoopAssetTransactionByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: assetTransactionUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) cooperative asset transactions.
|
||||
description: Returns the list of (optionally filtered) cooperative asset transactions which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) cooperative asset transactions which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-coopAssets
|
||||
operationId: listCoopAssets
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: membershipUuid
|
||||
in: query
|
||||
@@ -48,7 +48,7 @@ post:
|
||||
- hs-office-coopAssets
|
||||
operationId: addCoopAssetsTransaction
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new cooperative assets transaction.
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single share transaction by its uuid, if visible for the current subject.'
|
||||
operationId: getCoopShareTransactionByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: shareTransactionUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) cooperative share transactions.
|
||||
description: Returns the list of (optionally filtered) cooperative share transactions which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) cooperative share transactions which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-coopShares
|
||||
operationId: listCoopShares
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: membershipUuid
|
||||
in: query
|
||||
@@ -48,7 +48,7 @@ post:
|
||||
- hs-office-coopShares
|
||||
operationId: addCoopSharesTransaction
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new cooperative shares transaction.
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single debitor by its uuid, if visible for the current subject.'
|
||||
operationId: getDebitorByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single debitor by its uuid, if permitted for the current subject.'
|
||||
operationId: patchDebitor
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single debitor by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteDebitorByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) debitors.
|
||||
description: Returns the list of (optionally filtered) debitors which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) debitors which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
operationId: listDebitors
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
@@ -39,7 +39,7 @@ post:
|
||||
- hs-office-debitors
|
||||
operationId: addDebitor
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single membership by its uuid, if visible for the current subject.'
|
||||
operationId: getMembershipByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: membershipUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single membership by its uuid, if permitted for the current subject.'
|
||||
operationId: patchMembership
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: membershipUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single membership by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteMembershipByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: membershipUUID
|
||||
in: path
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) memberships.
|
||||
description: Returns the list of memberships which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of memberships which are visible to the current subject or any of it's assumed roles.
|
||||
The list can optionally be filtered by either the `partnerUuid` or the `memberNumber` - not both at the same time.
|
||||
tags:
|
||||
- hs-office-memberships
|
||||
operationId: listMemberships
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: partnerUuid
|
||||
in: query
|
||||
@@ -41,7 +41,7 @@ post:
|
||||
- hs-office-memberships
|
||||
operationId: addMembership
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new membership.
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single business partner by its uuid, if visible for the current subject.'
|
||||
operationId: getPartnerByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: partnerUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single business partner by its uuid, if permitted for the current subject.'
|
||||
operationId: patchPartner
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: partnerUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single business partner by its uuid, if permitted for the current subject.'
|
||||
operationId: deletePartnerByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: partnerUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) business partners.
|
||||
description: Returns the list of (optionally filtered) business partners which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) business partners which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-partners
|
||||
operationId: listPartners
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
@@ -33,7 +33,7 @@ post:
|
||||
- hs-office-partners
|
||||
operationId: addPartner
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single business person by its uuid, if visible for the current subject.'
|
||||
operationId: getPersonByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: personUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single person by its uuid, if permitted for the current subject.'
|
||||
operationId: patchPerson
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: personUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single business person by its uuid, if permitted for the current subject.'
|
||||
operationId: deletePersonByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: personUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) persons.
|
||||
description: Returns the list of (optionally filtered) persons which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) persons which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-persons
|
||||
operationId: listPersons
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
@@ -33,7 +33,7 @@ post:
|
||||
- hs-office-persons
|
||||
operationId: addPerson
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
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/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
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/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
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/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
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.
|
||||
description: Returns the list of (optionally filtered) person relations of a given person and which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-relations
|
||||
operationId: listRelations
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: personUuid
|
||||
in: query
|
||||
@@ -40,7 +40,7 @@ post:
|
||||
- hs-office-relations
|
||||
operationId: addRelation
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -4,7 +4,7 @@ get:
|
||||
description: 'Fetch a single SEPA Mandate by its uuid, if visible for the current subject.'
|
||||
operationId: getSepaMandateByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: sepaMandateUUID
|
||||
in: path
|
||||
@@ -32,7 +32,7 @@ patch:
|
||||
description: 'Updates a single SEPA Mandate by its uuid, if permitted for the current subject.'
|
||||
operationId: patchSepaMandate
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: sepaMandateUUID
|
||||
in: path
|
||||
@@ -63,7 +63,7 @@ delete:
|
||||
description: 'Delete a single SEPA Mandate by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteSepaMandateByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: sepaMandateUUID
|
||||
in: path
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) SEPA Mandates.
|
||||
description: Returns the list of (optionally filtered) SEPA Mandates which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) SEPA Mandates which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-sepaMandates
|
||||
operationId: listSepaMandatesByIBAN
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
@@ -33,7 +33,7 @@ post:
|
||||
- hs-office-sepaMandates
|
||||
operationId: addSepaMandate
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new SEPA-Mandate.
|
||||
|
||||
@@ -18,11 +18,11 @@ components:
|
||||
grantedRoleUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
granteeUserName:
|
||||
granteeSubjectName:
|
||||
type: string
|
||||
granteeUserUuid:
|
||||
granteeSubjectUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
required:
|
||||
- grantedRoleUuid
|
||||
- granteeUserUuid
|
||||
- granteeSubjectUuid
|
||||
|
||||
@@ -3,7 +3,7 @@ get:
|
||||
- rbac-grants
|
||||
operationId: getGrantById
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: grantedRoleUuid
|
||||
in: path
|
||||
@@ -12,13 +12,13 @@ get:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the granted role.
|
||||
- name: granteeUserUuid
|
||||
- name: granteeSubjectUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the user to whom the role was granted.
|
||||
description: UUID of the subject to who the role was granted.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@@ -36,9 +36,9 @@ get:
|
||||
delete:
|
||||
tags:
|
||||
- rbac-grants
|
||||
operationId: revokeRoleFromUser
|
||||
operationId: revokeRoleFromSubject
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: grantedRoleUuid
|
||||
in: path
|
||||
@@ -47,13 +47,13 @@ delete:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the granted role.
|
||||
- name: granteeUserUuid
|
||||
- name: granteeSubjectUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the user to whom the role was granted.
|
||||
description: UUID of the subject to which the role was granted.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-grants
|
||||
operationId: listUserGrants
|
||||
operationId: listSubjectGrants
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
responses:
|
||||
"200":
|
||||
@@ -18,9 +18,9 @@ get:
|
||||
post:
|
||||
tags:
|
||||
- rbac-grants
|
||||
operationId: grantRoleToUser
|
||||
operationId: grantRoleToSubject
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
required: true
|
||||
|
||||
@@ -3,7 +3,7 @@ get:
|
||||
- rbac-roles
|
||||
operationId: listRoles
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
responses:
|
||||
"200":
|
||||
|
||||
@@ -3,7 +3,7 @@ components:
|
||||
|
||||
schemas:
|
||||
|
||||
RbacUser:
|
||||
RbacSubject:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
@@ -11,7 +11,7 @@ components:
|
||||
format: uuid
|
||||
name:
|
||||
type: string
|
||||
RbacUserPermission:
|
||||
RbacSubjectPermission:
|
||||
type: object
|
||||
properties:
|
||||
objectUuid:
|
||||
@@ -1,12 +1,12 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: 'List all visible permissions granted to the given user; reduced '
|
||||
operationId: listUserPermissions
|
||||
- rbac-subjects
|
||||
description: 'List all visible permissions granted to the given subject; reduced '
|
||||
operationId: listSubjectPermissions
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: userUuid
|
||||
- name: subjectUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
@@ -20,7 +20,7 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUserPermission'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubjectPermission'
|
||||
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
@@ -1,12 +1,12 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: 'Fetch a single user by its id, if visible for the current subject.'
|
||||
operationId: getUserById
|
||||
- rbac-subjects
|
||||
description: 'Fetch a single subject by its id, if visible for the current subject.'
|
||||
operationId: getSubjectById
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: userUuid
|
||||
- name: subjectUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
@@ -18,7 +18,7 @@ get:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
@@ -28,18 +28,18 @@ get:
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- rbac-users
|
||||
operationId: deleteUserByUuid
|
||||
- rbac-subjects
|
||||
operationId: deleteSubjectByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: userUuid
|
||||
- name: subjectUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the user to delete.
|
||||
description: UUID of the subject to delete.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
@@ -1,10 +1,10 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: List accessible RBAC users with optional filter by name.
|
||||
operationId: listUsers
|
||||
- rbac-subjects
|
||||
description: List accessible RBAC subjects with optional filter by name.
|
||||
operationId: listSubjects
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
@@ -19,7 +19,7 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
'401':
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
'403':
|
||||
@@ -27,22 +27,22 @@ get:
|
||||
|
||||
post:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: Create a new RBAC user.
|
||||
operationId: createUser
|
||||
- rbac-subjects
|
||||
description: Create a new RBAC subject (e.g. user).
|
||||
operationId: createSubject
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
'409':
|
||||
$ref: 'error-responses.yaml#/components/responses/Conflict'
|
||||
|
||||
@@ -8,14 +8,14 @@ servers:
|
||||
|
||||
paths:
|
||||
|
||||
/api/rbac/users:
|
||||
$ref: 'rbac-users.yaml'
|
||||
/api/rbac/subjects:
|
||||
$ref: 'rbac-subjects.yaml'
|
||||
|
||||
/api/rbac/users/{userUuid}/permissions:
|
||||
$ref: 'rbac-users-with-id-permissions.yaml'
|
||||
/api/rbac/subjects/{subjectUuid}/permissions:
|
||||
$ref: 'rbac-subjects-with-id-permissions.yaml'
|
||||
|
||||
/api/rbac/users/{userUuid}:
|
||||
$ref: 'rbac-users-with-uuid.yaml'
|
||||
/api/rbac/subjects/{subjectUuid}:
|
||||
$ref: 'rbac-subjects-with-uuid.yaml'
|
||||
|
||||
/api/rbac/roles:
|
||||
$ref: 'rbac-roles.yaml'
|
||||
@@ -23,6 +23,6 @@ paths:
|
||||
/api/rbac/grants:
|
||||
$ref: 'rbac-grants.yaml'
|
||||
|
||||
/api/rbac/grants/{grantedRoleUuid}/{granteeUserUuid}:
|
||||
/api/rbac/grants/{grantedRoleUuid}/{granteeSubjectUuid}:
|
||||
$ref: 'rbac-grants-with-id.yaml'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) customers.
|
||||
description: Returns the list of (optionally filtered) customers which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) customers which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- testCustomers
|
||||
operationId: listCustomers
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: prefix
|
||||
in: query
|
||||
@@ -33,7 +33,7 @@ post:
|
||||
- testCustomers
|
||||
operationId: addCustomer
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -3,7 +3,7 @@ patch:
|
||||
- testPackages
|
||||
operationId: updatePackage
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: packageUUID
|
||||
in: path
|
||||
|
||||
@@ -3,7 +3,7 @@ get:
|
||||
- testPackages
|
||||
operationId: listPackages
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset prefix-TEMPLATE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:base-SCHEMA endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
CREATE SCHEMA base;
|
||||
--//
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- LAST-ROW-COUNT
|
||||
--changeset last-row-count:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:last-row-count endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the row count from the result of the previous query.
|
||||
Other than the native statement it's usable in an expression.
|
||||
*/
|
||||
create or replace function lastRowCount()
|
||||
create or replace function base.lastRowCount()
|
||||
returns bigint
|
||||
language plpgsql as $$
|
||||
declare
|
||||
lastRowCount bigint;
|
||||
begin
|
||||
get diagnostics lastrowCount = row_count;
|
||||
get diagnostics lastRowCount = row_count;
|
||||
return lastRowCount;
|
||||
end; $$;
|
||||
--//
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- INT-TO-VAR
|
||||
--changeset int-to-var:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:int-to-var endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns a textual representation of an integer number to be used as generated test data.
|
||||
|
||||
Examples :
|
||||
intToVarChar(0, 3) => 'aaa'
|
||||
intToVarChar(1, 3) => 'aab'
|
||||
base.intToVarChar(0, 3) => 'aaa'
|
||||
base.intToVarChar(1, 3) => 'aab'
|
||||
*/
|
||||
create or replace function intToVarChar(i integer, len integer)
|
||||
create or replace function base.intToVarChar(i integer, len integer)
|
||||
returns varchar
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@@ -19,7 +19,7 @@ declare
|
||||
begin
|
||||
select chr(ascii('a') + i % 26) into partial;
|
||||
if len > 1 then
|
||||
return intToVarChar(i / 26, len - 1) || partial;
|
||||
return base.intToVarChar(i / 26, len - 1) || partial;
|
||||
else
|
||||
return partial;
|
||||
end if;
|
||||
@@ -3,16 +3,16 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- RANDOM-IN-RANGE
|
||||
--changeset random-in-range:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:random-in-range endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns a random integer in the given range (both included),
|
||||
to be used for test data generation.
|
||||
|
||||
Example:
|
||||
randomInRange(0, 4) might return any of 0, 1, 2, 3, 4
|
||||
base.randomInRange(0, 4) might return any of 0, 1, 2, 3, 4
|
||||
*/
|
||||
create or replace function randomInRange(min integer, max integer)
|
||||
create or replace function base.randomInRange(min integer, max integer)
|
||||
returns integer
|
||||
returns null on null input
|
||||
language 'plpgsql' as $$
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset JSONB-CHANGES-DELTA:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:JSONB-CHANGES-DELTA endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Recursively compares two jsonb values and returns what has changed.
|
||||
This is a kind of right sided json diff.
|
||||
*/
|
||||
|
||||
create or replace function jsonb_changes_delta(oldJson jsonb, newJson jsonb)
|
||||
create or replace function base.jsonb_changes_delta(oldJson jsonb, newJson jsonb)
|
||||
returns jsonb
|
||||
called on null input
|
||||
language plpgsql as $$
|
||||
@@ -31,7 +31,7 @@ begin
|
||||
if jsonb_typeof(newJson -> (oldJsonElement.key)) = 'object' then
|
||||
diffJson = diffJson ||
|
||||
jsonb_build_object(oldJsonElement.key,
|
||||
jsonb_changes_delta(oldJsonElement.value, newJson -> (oldJsonElement.key)));
|
||||
base.jsonb_changes_delta(oldJsonElement.value, newJson -> (oldJsonElement.key)));
|
||||
end if;
|
||||
else
|
||||
diffJson = diffJson || jsonb_build_object(oldJsonElement.key, null);
|
||||
@@ -49,30 +49,30 @@ do language plpgsql $$
|
||||
actual text;
|
||||
begin
|
||||
|
||||
select jsonb_changes_delta(null::jsonb, null::jsonb) into actual;
|
||||
select base.jsonb_changes_delta(null::jsonb, null::jsonb) into actual;
|
||||
if actual is not null then
|
||||
raise exception 'jsonb_diff #1 failed:% expected: %,% actually: %', E'\n', expected, E'\n', actual;
|
||||
end if;
|
||||
|
||||
select jsonb_changes_delta(null::jsonb, '{"a": "new"}'::jsonb) into actual;
|
||||
select base.jsonb_changes_delta(null::jsonb, '{"a": "new"}'::jsonb) into actual;
|
||||
expected := '{"a": "new"}'::jsonb;
|
||||
if actual <> expected then
|
||||
raise exception 'jsonb_diff #2 failed:% expected: %,% actual: %', E'\n', expected, E'\n', actual;
|
||||
end if;
|
||||
|
||||
select jsonb_changes_delta('{"a": "old"}'::jsonb, '{"a": "new"}'::jsonb) into actual;
|
||||
select base.jsonb_changes_delta('{"a": "old"}'::jsonb, '{"a": "new"}'::jsonb) into actual;
|
||||
expected := '{"a": "new"}'::jsonb;
|
||||
if actual <> expected then
|
||||
raise exception 'jsonb_diff #3 failed:% expected: %,% actual: %', E'\n', expected, E'\n', actual;
|
||||
end if;
|
||||
|
||||
select jsonb_changes_delta('{"a": "old"}'::jsonb, '{"a": "old"}'::jsonb) into actual;
|
||||
select base.jsonb_changes_delta('{"a": "old"}'::jsonb, '{"a": "old"}'::jsonb) into actual;
|
||||
expected := '{}'::jsonb;
|
||||
if actual <> expected then
|
||||
raise exception 'jsonb_diff #4 failed:% expected: %,% actual: %', E'\n', expected, E'\n', actual;
|
||||
end if;
|
||||
|
||||
select jsonb_changes_delta(
|
||||
select base.jsonb_changes_delta(
|
||||
$json${
|
||||
"a": "same",
|
||||
"b": "old",
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- UUID-OSSP-EXTENSION
|
||||
--changeset uuid-ossp-extension:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:uuid-ossp-extension endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Makes improved uuid generation available.
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- NUMERIC-HASH-FUNCTIONS
|
||||
--changeset numeric-hash-functions:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:numeric-hash-functions endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create function bigIntHash(text) returns bigint as $$
|
||||
create function base.bigIntHash(text) returns bigint as $$
|
||||
select ('x'||substr(md5($1),1,16))::bit(64)::bigint;
|
||||
$$ language sql;
|
||||
--//
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- TABLE-COLUMNS-FUNCTION
|
||||
--changeset table-columns-function:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:table-columns-function endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function columnsNames( tableName text )
|
||||
create or replace function base.tableColumnNames( tableName text )
|
||||
returns text
|
||||
stable
|
||||
language 'plpgsql' as $$
|
||||
@@ -1,12 +1,12 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset RAISE-FUNCTIONS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:RAISE-FUNCTIONS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Like `RAISE EXCEPTION` ... just as an expression instead of a statement.
|
||||
*/
|
||||
create or replace function raiseException(msg text)
|
||||
create or replace function base.raiseException(msg text)
|
||||
returns varchar
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@@ -16,12 +16,12 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset ASSERT-FUNCTIONS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:ASSERT-FUNCTIONS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Like `ASSERT` but as an expression instead of a statement.
|
||||
*/
|
||||
create or replace function assertTrue(expectedTrue boolean, msg text)
|
||||
create or replace function base.assertTrue(expectedTrue boolean, msg text)
|
||||
returns boolean
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- NUMERIC-HASH-FUNCTIONS
|
||||
--changeset hash:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hash endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do $$
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset context-DEFINE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:context-DEFINE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Callback which is called after the context has been (re-) defined.
|
||||
This function will be overwritten by later changesets.
|
||||
*/
|
||||
create procedure contextDefined(
|
||||
create procedure base.contextDefined(
|
||||
currentTask varchar(127),
|
||||
currentRequest text,
|
||||
currentUser varchar(63),
|
||||
currentSubject varchar(63),
|
||||
assumedRoles varchar(1023)
|
||||
)
|
||||
language plpgsql as $$
|
||||
@@ -22,10 +22,10 @@ end; $$;
|
||||
/*
|
||||
Defines the transaction context.
|
||||
*/
|
||||
create or replace procedure defineContext(
|
||||
create or replace procedure base.defineContext(
|
||||
currentTask varchar(127),
|
||||
currentRequest text = null,
|
||||
currentUser varchar(63) = null,
|
||||
currentSubject varchar(63) = null,
|
||||
assumedRoles varchar(1023) = null
|
||||
)
|
||||
language plpgsql as $$
|
||||
@@ -38,27 +38,27 @@ begin
|
||||
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);
|
||||
currentSubject := coalesce(currentSubject, '');
|
||||
assert length(currentSubject) <= 63, FORMAT('currentSubject must not be longer than 63 characters: "%s"', currentSubject);
|
||||
execute format('set local hsadminng.currentSubject to %L', currentSubject);
|
||||
|
||||
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);
|
||||
call base.contextDefined(currentTask, currentRequest, currentSubject, assumedRoles);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset context-CURRENT-TASK:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:context-CURRENT-TASK endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the current task as set by `hsadminng.currentTask`.
|
||||
Raises exception if not set.
|
||||
*/
|
||||
create or replace function currentTask()
|
||||
create or replace function base.currentTask()
|
||||
returns varchar(127)
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
@@ -72,7 +72,7 @@ begin
|
||||
currentTask := null;
|
||||
end;
|
||||
if (currentTask is null or currentTask = '') then
|
||||
raise exception '[401] currentTask must be defined, please call `defineContext(...)`';
|
||||
raise exception '[401] currentTask must be defined, please call `base.defineContext(...)`';
|
||||
end if;
|
||||
return currentTask;
|
||||
end; $$;
|
||||
@@ -80,13 +80,13 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset context-CURRENT-REQUEST:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:context-CURRENT-REQUEST endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the current http request as set via `defineContext(...)`.
|
||||
Returns the current http request as set via `base.defineContext(...)`.
|
||||
Raises exception if not set.
|
||||
*/
|
||||
create or replace function currentRequest()
|
||||
create or replace function base.currentRequest()
|
||||
returns text
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
@@ -105,36 +105,36 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset context-CURRENT-USER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:context-current-subject endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the current user as defined by `defineContext(...)`.
|
||||
Returns the current user as defined by `base.defineContext(...)`.
|
||||
*/
|
||||
create or replace function currentUser()
|
||||
create or replace function base.currentSubject()
|
||||
returns varchar(63)
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentUser varchar(63);
|
||||
currentSubject varchar(63);
|
||||
begin
|
||||
begin
|
||||
currentUser := current_setting('hsadminng.currentUser');
|
||||
currentSubject := current_setting('hsadminng.currentSubject');
|
||||
exception
|
||||
when others then
|
||||
currentUser := null;
|
||||
currentSubject := null;
|
||||
end;
|
||||
return currentUser;
|
||||
return currentSubject;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset context-ASSUMED-ROLES:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:context-base.ASSUMED-ROLES endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns assumed role names as set in `hsadminng.assumedRoles`
|
||||
or empty array, if not set.
|
||||
*/
|
||||
create or replace function assumedRoles()
|
||||
create or replace function base.assumedRoles()
|
||||
returns varchar(1023)[]
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
@@ -142,7 +142,7 @@ begin
|
||||
return string_to_array(current_setting('hsadminng.assumedRoles', true), ';');
|
||||
end; $$;
|
||||
|
||||
create or replace function cleanIdentifier(rawIdentifier varchar)
|
||||
create or replace function base.cleanIdentifier(rawIdentifier varchar)
|
||||
returns varchar
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
@@ -153,21 +153,21 @@ begin
|
||||
return cleanIdentifier;
|
||||
end; $$;
|
||||
|
||||
create or replace function pureIdentifier(rawIdentifier varchar)
|
||||
create or replace function base.pureIdentifier(rawIdentifier varchar)
|
||||
returns varchar
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
cleanIdentifier varchar;
|
||||
begin
|
||||
cleanIdentifier := cleanIdentifier(rawIdentifier);
|
||||
cleanIdentifier := base.cleanIdentifier(rawIdentifier);
|
||||
if cleanIdentifier != rawIdentifier then
|
||||
raise exception 'identifier "%" contains invalid characters, maybe use "%"', rawIdentifier, cleanIdentifier;
|
||||
end if;
|
||||
return cleanIdentifier;
|
||||
end; $$;
|
||||
|
||||
create or replace function findObjectUuidByIdName(objectTable varchar, objectIdName varchar)
|
||||
create or replace function base.findObjectUuidByIdName(objectTable varchar, objectIdName varchar)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
@@ -175,8 +175,8 @@ declare
|
||||
sql varchar;
|
||||
uuid uuid;
|
||||
begin
|
||||
objectTable := pureIdentifier(objectTable);
|
||||
objectIdName := pureIdentifier(objectIdName);
|
||||
objectTable := base.pureIdentifier(objectTable);
|
||||
objectIdName := base.pureIdentifier(objectIdName);
|
||||
sql := format('select * from %sUuidByIdName(%L);', objectTable, objectIdName);
|
||||
begin
|
||||
execute sql into uuid;
|
||||
@@ -187,7 +187,7 @@ begin
|
||||
return uuid;
|
||||
end ; $$;
|
||||
|
||||
create or replace function findIdNameByObjectUuid(objectTable varchar, objectUuid uuid)
|
||||
create or replace function base.findIdNameByObjectUuid(objectTable varchar, objectUuid uuid)
|
||||
returns varchar
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
@@ -195,7 +195,7 @@ declare
|
||||
sql varchar;
|
||||
idName varchar;
|
||||
begin
|
||||
objectTable := pureIdentifier(objectTable);
|
||||
objectTable := base.pureIdentifier(objectTable);
|
||||
sql := format('select * from %sIdNameByUuid(%L::uuid);', objectTable, objectUuid);
|
||||
begin
|
||||
execute sql into idName;
|
||||
@@ -206,27 +206,27 @@ begin
|
||||
return idName;
|
||||
end ; $$;
|
||||
|
||||
create or replace function currentSubjects()
|
||||
create or replace function base.currentSubjects()
|
||||
returns varchar(1023)[]
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
assumedRoles varchar(1023)[];
|
||||
begin
|
||||
assumedRoles := assumedRoles();
|
||||
assumedRoles := base.assumedRoles();
|
||||
if array_length(assumedRoles, 1) > 0 then
|
||||
return assumedRoles;
|
||||
else
|
||||
return array [currentUser()]::varchar(1023)[];
|
||||
return array [base.currentSubject()]::varchar(1023)[];
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
create or replace function hasAssumedRole()
|
||||
create or replace function base.hasAssumedRole()
|
||||
returns boolean
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return array_length(assumedRoles(), 1) > 0;
|
||||
return array_length(base.assumedRoles(), 1) > 0;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
@@ -1,107 +1,107 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset audit-OPERATION-TYPE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:audit-OPERATION-TYPE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A type representing a DML operation.
|
||||
*/
|
||||
do $$
|
||||
begin
|
||||
if not exists(select 1 from pg_type where typname = 'operation') then
|
||||
create type "operation" as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE');
|
||||
if not exists(select 1 from pg_type where typname = 'base.tx_operation') then
|
||||
create type base.tx_operation as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE');
|
||||
end if;
|
||||
--more types here...
|
||||
end $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset audit-TX-CONTEXT-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:audit-TX-CONTEXT-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A table storing transactions with context data.
|
||||
*/
|
||||
create table tx_context
|
||||
create table base.tx_context
|
||||
(
|
||||
txId xid8 primary key not null,
|
||||
txTimestamp timestamp not null,
|
||||
currentUser varchar(63) not null, -- not the uuid, because users can be deleted
|
||||
currentSubject varchar(63) not null, -- not the uuid, because users can be deleted
|
||||
assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted
|
||||
currentTask varchar(127) not null,
|
||||
currentRequest text not null
|
||||
);
|
||||
|
||||
create index on tx_context using brin (txTimestamp);
|
||||
create index on base.tx_context using brin (txTimestamp);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset audit-TX-JOURNAL-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:audit-TX-JOURNAL-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A table storing the transaction audit journal for all target tables it's configured for.
|
||||
*/
|
||||
create table tx_journal
|
||||
create table base.tx_journal
|
||||
(
|
||||
txId xid8 not null references tx_context (txId),
|
||||
targetTable text not null,
|
||||
targetUuid uuid not null, -- Assumes that all audited tables have a uuid column.
|
||||
targetOp operation not null,
|
||||
txId xid8 not null references base.tx_context (txId),
|
||||
targetTable text not null,
|
||||
targetUuid uuid not null, -- Assumes that all audited tables have a uuid column.
|
||||
targetOp base.tx_operation not null,
|
||||
targetDelta jsonb
|
||||
);
|
||||
|
||||
create index on tx_journal (targetTable, targetUuid);
|
||||
create index on base.tx_journal (targetTable, targetUuid);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset audit-TX-JOURNAL-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:audit-TX-JOURNAL-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A view combining tx_journal with tx_context.
|
||||
A view combining base.tx_journal with base.tx_context.
|
||||
*/
|
||||
create view tx_journal_v as
|
||||
create view base.tx_journal_v as
|
||||
select txc.*, txj.targettable, txj.targetop, txj.targetuuid, txj.targetdelta
|
||||
from tx_journal txj
|
||||
left join tx_context txc using (txId)
|
||||
from base.tx_journal txj
|
||||
left join base.tx_context txc using (txId)
|
||||
order by txc.txtimestamp;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset audit-TX-JOURNAL-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:audit-TX-JOURNAL-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Trigger function for transaction audit journal.
|
||||
*/
|
||||
create or replace function tx_journal_trigger()
|
||||
create or replace function base.tx_journal_trigger()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
declare
|
||||
curTask text;
|
||||
curTxId xid8;
|
||||
begin
|
||||
curTask := currentTask();
|
||||
curTask := base.currentTask();
|
||||
curTxId := pg_current_xact_id();
|
||||
|
||||
insert
|
||||
into tx_context (txId, txTimestamp, currentUser, assumedRoles, currentTask, currentRequest)
|
||||
into base.tx_context (txId, txTimestamp, currentSubject, assumedRoles, currentTask, currentRequest)
|
||||
values ( curTxId, now(),
|
||||
currentUser(), assumedRoles(), curTask, currentRequest())
|
||||
base.currentSubject(), base.assumedRoles(), curTask, base.currentRequest())
|
||||
on conflict do nothing;
|
||||
|
||||
case tg_op
|
||||
when 'INSERT' then insert
|
||||
into tx_journal
|
||||
into base.tx_journal
|
||||
values (curTxId,
|
||||
tg_table_name, new.uuid, tg_op::operation,
|
||||
tg_table_name, new.uuid, tg_op::base.tx_operation,
|
||||
to_jsonb(new));
|
||||
when 'UPDATE' then insert
|
||||
into tx_journal
|
||||
into base.tx_journal
|
||||
values (curTxId,
|
||||
tg_table_name, old.uuid, tg_op::operation,
|
||||
jsonb_changes_delta(to_jsonb(old), to_jsonb(new)));
|
||||
tg_table_name, old.uuid, tg_op::base.tx_operation,
|
||||
base.jsonb_changes_delta(to_jsonb(old), to_jsonb(new)));
|
||||
when 'DELETE' then insert
|
||||
into tx_journal
|
||||
into base.tx_journal
|
||||
values (curTxId,
|
||||
tg_table_name, old.uuid, 'DELETE'::operation,
|
||||
tg_table_name, old.uuid, 'DELETE'::base.tx_operation,
|
||||
null::jsonb);
|
||||
else raise exception 'Trigger op % not supported for %.', tg_op, tg_table_name;
|
||||
end case;
|
||||
@@ -110,22 +110,23 @@ end; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset audit-CREATE-JOURNAL-LOG:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:audit-CREATE-JOURNAL-LOG endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Trigger function for transaction audit journal.
|
||||
*/
|
||||
|
||||
create or replace procedure create_journal(targetTable varchar)
|
||||
create or replace procedure base.create_journal(targetTable varchar)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
createTriggerSQL varchar;
|
||||
begin
|
||||
targetTable := lower(targetTable);
|
||||
|
||||
createTriggerSQL = 'CREATE TRIGGER ' || targetTable || '_journal' ||
|
||||
-- "-0-" to put the trigger execution before any alphabetically greater tx-triggers
|
||||
createTriggerSQL = 'CREATE TRIGGER tx_0_journal_tg' ||
|
||||
' AFTER INSERT OR UPDATE OR DELETE ON ' || targetTable ||
|
||||
' FOR EACH ROW EXECUTE PROCEDURE tx_journal_trigger()';
|
||||
' FOR EACH ROW EXECUTE PROCEDURE base.tx_journal_trigger()';
|
||||
execute createTriggerSQL;
|
||||
end; $$;
|
||||
--//
|
||||
@@ -1,9 +1,9 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-global-historization-tx-history-txid:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-global-historization-tx-history-txid endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function tx_history_txid()
|
||||
create or replace function base.tx_history_txid()
|
||||
returns xid8 stable
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@@ -23,11 +23,11 @@ begin
|
||||
historicalTxIdSetting, historicalTimestampSetting;
|
||||
end if;
|
||||
-- just for debugging / making sure the function is only called once per query
|
||||
-- raise notice 'tx_history_txid() called with: (%, %)', historicalTxIdSetting, historicalTimestampSetting;
|
||||
-- raise notice 'base.tx_history_txid() called with: (%, %)', historicalTxIdSetting, historicalTimestampSetting;
|
||||
|
||||
if historicalTxIdSetting is null or historicalTxIdSetting = '' then
|
||||
select historicalTimestampSetting::timestamp into historicalTimestamp;
|
||||
select max(txc.txid) from tx_context txc where txc.txtimestamp <= historicalTimestamp into historicalTxId;
|
||||
select max(txc.txid) from base.tx_context txc where txc.txtimestamp <= historicalTimestamp into historicalTxId;
|
||||
else
|
||||
historicalTxId = historicalTxIdSetting::xid8;
|
||||
end if;
|
||||
@@ -37,17 +37,17 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-global-historization-tx-historicize-tf:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-global-historization-tx-historicize-tf endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create type "tx_operation" as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE');
|
||||
-- create type base.tx_operation as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE');
|
||||
|
||||
create or replace function tx_historicize_tf()
|
||||
create or replace function base.tx_historicize_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
currentUser varchar(63);
|
||||
currentSubject varchar(63);
|
||||
currentTask varchar(127);
|
||||
"row" record;
|
||||
"alive" boolean;
|
||||
@@ -55,15 +55,15 @@ declare
|
||||
begin
|
||||
-- determine user_id
|
||||
begin
|
||||
currentUser := current_setting('hsadminng.currentUser');
|
||||
currentSubject := current_setting('hsadminng.currentSubject');
|
||||
exception
|
||||
when others then
|
||||
currentUser := null;
|
||||
currentSubject := null;
|
||||
end;
|
||||
if (currentUser is null or currentUser = '') then
|
||||
raise exception 'hsadminng.currentUser must be defined, please use "SET LOCAL ...;"';
|
||||
if (currentSubject is null or currentSubject = '') then
|
||||
raise exception 'hsadminng.currentSubject must be defined, please use "SET LOCAL ...;"';
|
||||
end if;
|
||||
raise notice 'currentUser: %', currentUser;
|
||||
raise notice 'currentSubject: %', currentSubject;
|
||||
|
||||
-- determine task
|
||||
currentTask = current_setting('hsadminng.currentTask');
|
||||
@@ -91,11 +91,11 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-global-historization-tx-create-historicization:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-global-historization-tx-create-historicization endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
create or replace procedure tx_create_historicization(baseTable varchar)
|
||||
create or replace procedure base.tx_create_historicization(baseTable varchar)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
createHistTableSql varchar;
|
||||
@@ -110,8 +110,8 @@ begin
|
||||
createHistTableSql = '' ||
|
||||
'CREATE TABLE ' || baseTable || '_ex (' ||
|
||||
' version_id serial PRIMARY KEY,' ||
|
||||
' txid xid8 NOT NULL REFERENCES tx_context(txid),' ||
|
||||
' trigger_op tx_operation NOT NULL,' ||
|
||||
' txid xid8 NOT NULL REFERENCES base.tx_context(txid),' ||
|
||||
' trigger_op base.tx_operation NOT NULL,' ||
|
||||
' alive boolean not null,' ||
|
||||
' LIKE ' || baseTable ||
|
||||
' EXCLUDING CONSTRAINTS' ||
|
||||
@@ -131,8 +131,8 @@ begin
|
||||
createViewSQL = format(
|
||||
'CREATE OR REPLACE VIEW %1$s AS' ||
|
||||
'(' ||
|
||||
-- make sure the function is only called once, not for every matching row in tx_context
|
||||
' WITH txh AS (SELECT tx_history_txid() AS txid) ' ||
|
||||
-- make sure the function is only called once, not for every matching row in base.tx_context
|
||||
' WITH txh AS (SELECT base.tx_history_txid() AS txid) ' ||
|
||||
' SELECT %2$s' ||
|
||||
' FROM %3$s' ||
|
||||
' WHERE alive = TRUE' ||
|
||||
@@ -140,7 +140,7 @@ begin
|
||||
' (' ||
|
||||
' SELECT max(ex.version_id) AS history_id' ||
|
||||
' FROM %3$s AS ex' ||
|
||||
' JOIN tx_context as txc ON ex.txid = txc.txid' ||
|
||||
' JOIN base.tx_context as txc ON ex.txid = txc.txid' ||
|
||||
' WHERE txc.txid <= (SELECT txid FROM txh)' ||
|
||||
' GROUP BY uuid' ||
|
||||
' )' ||
|
||||
@@ -150,9 +150,10 @@ begin
|
||||
raise notice 'sql: %', createViewSQL;
|
||||
execute createViewSQL;
|
||||
|
||||
createTriggerSQL = 'CREATE TRIGGER ' || baseTable || '_tx_historicize_tg' ||
|
||||
-- "-9-" to put the trigger execution after any alphabetically lesser tx-triggers
|
||||
createTriggerSQL = 'CREATE TRIGGER tx_9_historicize_tg' ||
|
||||
' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable ||
|
||||
' FOR EACH ROW EXECUTE PROCEDURE tx_historicize_tf()';
|
||||
' FOR EACH ROW EXECUTE PROCEDURE base.tx_historicize_tf()';
|
||||
raise notice 'sql: %', createTriggerSQL;
|
||||
execute createTriggerSQL;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
-- ============================================================================
|
||||
-- PG-STAT-STATEMENTS-EXTENSION
|
||||
--changeset pg-stat-statements-extension:1 context:pg_stat_statements endDelimiter:--//
|
||||
--changeset michael.hoennig:pg-stat-statements-extension context:pg_stat_statements endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Makes improved uuid generation available.
|
||||
@@ -0,0 +1,8 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:rbac-SCHEMA endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE SCHEMA rbac;
|
||||
--//
|
||||
@@ -1,30 +1,30 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-REFERENCE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-REFERENCE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
|
||||
*/
|
||||
create type ReferenceType as enum ('RbacUser', 'RbacRole', 'RbacPermission');
|
||||
create type rbac.ReferenceType as enum ('rbac.subject', 'rbac.role', 'rbac.permission');
|
||||
|
||||
create table RbacReference
|
||||
create table rbac.reference
|
||||
(
|
||||
uuid uuid unique default uuid_generate_v4(),
|
||||
type ReferenceType not null
|
||||
type rbac.ReferenceType not null
|
||||
);
|
||||
|
||||
create or replace function assertReferenceType(argument varchar, referenceId uuid, expectedType ReferenceType)
|
||||
returns ReferenceType
|
||||
create or replace function rbac.assertReferenceType(argument varchar, referenceId uuid, expectedType rbac.ReferenceType)
|
||||
returns rbac.ReferenceType
|
||||
language plpgsql as $$
|
||||
declare
|
||||
actualType ReferenceType;
|
||||
actualType rbac.ReferenceType;
|
||||
begin
|
||||
if referenceId is null then
|
||||
raise exception '% must be a % and not null', argument, expectedType;
|
||||
end if;
|
||||
|
||||
actualType = (select type from RbacReference where uuid = referenceId);
|
||||
actualType = (select type from rbac.reference where uuid = referenceId);
|
||||
if (actualType <> expectedType) then
|
||||
raise exception '% must reference a %, but got a %', argument, expectedType, actualType;
|
||||
end if;
|
||||
@@ -33,20 +33,20 @@ end; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-USER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-SUBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
|
||||
*/
|
||||
create table RbacUser
|
||||
create table rbac.subject
|
||||
(
|
||||
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
||||
uuid uuid primary key references rbac.reference (uuid) on delete cascade,
|
||||
name varchar(63) not null unique
|
||||
);
|
||||
|
||||
call create_journal('RbacUser');
|
||||
call base.create_journal('rbac.subject');
|
||||
|
||||
create or replace function createRbacUser(userName varchar)
|
||||
create or replace function rbac.create_subject(subjectName varchar)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
@@ -54,47 +54,47 @@ declare
|
||||
objectId uuid;
|
||||
begin
|
||||
insert
|
||||
into RbacReference (type)
|
||||
values ('RbacUser')
|
||||
into rbac.reference (type)
|
||||
values ('rbac.subject')
|
||||
returning uuid into objectId;
|
||||
insert
|
||||
into RbacUser (uuid, name)
|
||||
values (objectid, userName);
|
||||
into rbac.subject (uuid, name)
|
||||
values (objectid, subjectName);
|
||||
return objectId;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function createRbacUser(refUuid uuid, userName varchar)
|
||||
create or replace function rbac.create_subject(refUuid uuid, subjectName varchar)
|
||||
returns uuid
|
||||
called on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
insert
|
||||
into RbacReference as r (uuid, type)
|
||||
values (coalesce(refUuid, uuid_generate_v4()), 'RbacUser')
|
||||
into rbac.reference as r (uuid, type)
|
||||
values (coalesce(refUuid, uuid_generate_v4()), 'rbac.subject')
|
||||
returning r.uuid into refUuid;
|
||||
insert
|
||||
into RbacUser (uuid, name)
|
||||
values (refUuid, userName);
|
||||
into rbac.subject (uuid, name)
|
||||
values (refUuid, subjectName);
|
||||
return refUuid;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function findRbacUserId(userName varchar)
|
||||
create or replace function rbac.find_subject_id(subjectName varchar)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select uuid from RbacUser where name = userName
|
||||
select uuid from rbac.subject where name = subjectName
|
||||
$$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
|
||||
*/
|
||||
create table RbacObject
|
||||
create table rbac.object
|
||||
(
|
||||
uuid uuid primary key default uuid_generate_v4(),
|
||||
serialId serial, -- TODO.perf: only needed for reverse deletion of temp test data
|
||||
@@ -102,19 +102,19 @@ create table RbacObject
|
||||
unique (objectTable, uuid)
|
||||
);
|
||||
|
||||
call create_journal('RbacObject');
|
||||
call base.create_journal('rbac.object');
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-GENERATE-RELATED-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-GENERATE-RELATED-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Inserts related RbacObject for use in the BEFORE ONSERT TRIGGERs on the business objects.
|
||||
Inserts related rbac.object for use in the BEFORE INSERT TRIGGERs on the business objects.
|
||||
*/
|
||||
create or replace function insertRelatedRbacObject()
|
||||
create or replace function rbac.insert_related_object()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
@@ -124,13 +124,13 @@ begin
|
||||
if TG_OP = 'INSERT' then
|
||||
if NEW.uuid is null then
|
||||
insert
|
||||
into RbacObject (objectTable)
|
||||
into rbac.object (objectTable)
|
||||
values (TG_TABLE_NAME)
|
||||
returning uuid into objectUuid;
|
||||
NEW.uuid = objectUuid;
|
||||
else
|
||||
insert
|
||||
into RbacObject (uuid, objectTable)
|
||||
into rbac.object (uuid, objectTable)
|
||||
values (NEW.uuid, TG_TABLE_NAME)
|
||||
returning uuid into objectUuid;
|
||||
end if;
|
||||
@@ -141,75 +141,79 @@ begin
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Deletes related RbacObject for use in the BEFORE DELETE TRIGGERs on the business objects.
|
||||
Deletes related rbac.object for use in the BEFORE DELETE TRIGGERs on the business objects.
|
||||
Through cascades all related rbac roles and grants are going to be deleted as well.
|
||||
*/
|
||||
create or replace function deleteRelatedRbacObject()
|
||||
create or replace function rbac.delete_related_rbac_rules_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP = 'DELETE' then
|
||||
delete from RbacObject where rbacobject.uuid = old.uuid;
|
||||
delete from rbac.object where rbac.object.uuid = old.uuid;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
|
||||
end if;
|
||||
return old;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-ROLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-ROLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
|
||||
*/
|
||||
create type rbac.RoleType as enum ('OWNER', 'ADMIN', 'AGENT', 'TENANT', 'GUEST', 'REFERRER');
|
||||
|
||||
create type RbacRoleType as enum ('OWNER', 'ADMIN', 'AGENT', 'TENANT', 'GUEST', 'REFERRER');
|
||||
|
||||
create table RbacRole
|
||||
create table rbac.role
|
||||
(
|
||||
uuid uuid primary key references RbacReference (uuid) on delete cascade initially deferred, -- initially deferred
|
||||
objectUuid uuid not null references RbacObject (uuid) initially deferred,
|
||||
roleType RbacRoleType not null,
|
||||
uuid uuid primary key references rbac.reference (uuid) on delete cascade initially deferred, -- initially deferred
|
||||
objectUuid uuid not null references rbac.object (uuid) initially deferred,
|
||||
roleType rbac.RoleType not null,
|
||||
unique (objectUuid, roleType)
|
||||
);
|
||||
|
||||
call create_journal('RbacRole');
|
||||
call base.create_journal('rbac.role');
|
||||
--//
|
||||
|
||||
create type RbacRoleDescriptor as
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:rbac-base-ROLE-DESCRIPTOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create type rbac.RoleDescriptor as
|
||||
(
|
||||
objectTable varchar(63), -- for human readability and easier debugging
|
||||
objectUuid uuid,
|
||||
roleType RbacRoleType,
|
||||
roleType rbac.RoleType,
|
||||
assumed boolean
|
||||
);
|
||||
|
||||
create or replace function assumed()
|
||||
create or replace function rbac.assumed()
|
||||
returns boolean
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select true;
|
||||
$$;
|
||||
|
||||
create or replace function unassumed()
|
||||
create or replace function rbac.unassumed()
|
||||
returns boolean
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select false;
|
||||
$$;
|
||||
|
||||
|
||||
create or replace function roleDescriptor(
|
||||
objectTable varchar(63), objectUuid uuid, roleType RbacRoleType,
|
||||
create or replace function rbac.roleDescriptorOf(
|
||||
objectTable varchar(63), objectUuid uuid, roleType rbac.RoleType,
|
||||
assumed boolean = true) -- just for DSL readability, belongs actually to the grant
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select objectTable, objectUuid, roleType::RbacRoleType, assumed;
|
||||
select objectTable, objectUuid, roleType::rbac.RoleType, assumed;
|
||||
$$;
|
||||
|
||||
create or replace function createRole(roleDescriptor RbacRoleDescriptor)
|
||||
create or replace function rbac.createRole(roleDescriptor rbac.RoleDescriptor)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
@@ -217,60 +221,65 @@ declare
|
||||
referenceId uuid;
|
||||
begin
|
||||
insert
|
||||
into RbacReference (type)
|
||||
values ('RbacRole')
|
||||
into rbac.reference (type)
|
||||
values ('rbac.role')
|
||||
returning uuid into referenceId;
|
||||
insert
|
||||
into RbacRole (uuid, objectUuid, roleType)
|
||||
into rbac.role (uuid, objectUuid, roleType)
|
||||
values (referenceId, roleDescriptor.objectUuid, roleDescriptor.roleType);
|
||||
return referenceId;
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
create or replace procedure deleteRole(roleUUid uuid)
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:rbac-base-ROLE-FUNCTIONS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure rbac.deleteRole(roleUUid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
--raise exception '% deleting role uuid %', currentsubjectsuuids(), roleUUid;
|
||||
delete from RbacRole where uuid = roleUUid;
|
||||
--raise exception '% deleting role uuid %', rbac.currentSubjectOrAssumedRolesUuids(), roleUUid;
|
||||
delete from rbac.role where uuid = roleUUid;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function findRoleId(roleIdName varchar)
|
||||
create or replace function rbac.findRoleId(roleIdName varchar)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
roleParts text;
|
||||
roleTypeFromRoleIdName RbacRoleType;
|
||||
roleTypeFromRoleIdName rbac.RoleType;
|
||||
objectNameFromRoleIdName text;
|
||||
objectTableFromRoleIdName text;
|
||||
objectUuidOfRole uuid;
|
||||
roleUuid uuid;
|
||||
begin
|
||||
-- TODO.refa: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences
|
||||
-- TODO.refa: extract function rbac.toRoleDescriptor(roleIdName varchar) + find other occurrences
|
||||
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);
|
||||
objectUuidOfRole = findObjectUuidByIdName(objectTableFromRoleIdName, objectNameFromRoleIdName);
|
||||
objectUuidOfRole = base.findObjectUuidByIdName(objectTableFromRoleIdName, objectNameFromRoleIdName);
|
||||
|
||||
select uuid
|
||||
from RbacRole
|
||||
from rbac.role
|
||||
where objectUuid = objectUuidOfRole
|
||||
and roleType = roleTypeFromRoleIdName
|
||||
into roleUuid;
|
||||
return roleUuid;
|
||||
end; $$;
|
||||
|
||||
create or replace function findRoleId(roleDescriptor RbacRoleDescriptor)
|
||||
create or replace function rbac.findRoleId(roleDescriptor rbac.RoleDescriptor)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select uuid from RbacRole where objectUuid = roleDescriptor.objectUuid and roleType = roleDescriptor.roleType;
|
||||
select uuid from rbac.role where objectUuid = roleDescriptor.objectUuid and roleType = roleDescriptor.roleType;
|
||||
$$;
|
||||
|
||||
create or replace function getRoleId(roleDescriptor RbacRoleDescriptor)
|
||||
create or replace function rbac.getRoleId(roleDescriptor rbac.RoleDescriptor)
|
||||
returns uuid
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@@ -278,29 +287,30 @@ declare
|
||||
begin
|
||||
assert roleDescriptor is not null, 'roleDescriptor must not be null';
|
||||
|
||||
roleUuid := findRoleId(roleDescriptor);
|
||||
roleUuid := rbac.findRoleId(roleDescriptor);
|
||||
if (roleUuid is null) then
|
||||
raise exception 'RbacRole "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
|
||||
raise exception 'rbac.role "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
|
||||
end if;
|
||||
return roleUuid;
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-BEFORE-DELETE-ROLE-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-BEFORE-DELETE-ROLE-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
RbacRole BEFORE DELETE TRIGGER function which deletes all related roles.
|
||||
rbac.role BEFORE DELETE TRIGGER function which deletes all related roles.
|
||||
*/
|
||||
create or replace function deleteRbacGrantsOfRbacRole()
|
||||
create or replace function rbac.delete_grants_of_role_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP = 'DELETE' then
|
||||
delete from RbacGrants g where old.uuid in (g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid);
|
||||
delete from rbac.grants g where old.uuid in (g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid);
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
|
||||
end if;
|
||||
@@ -308,31 +318,31 @@ begin
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Installs the RbacRole BEFORE DELETE TRIGGER.
|
||||
Installs the rbac.role BEFORE DELETE TRIGGER.
|
||||
*/
|
||||
create trigger deleteRbacGrantsOfRbacRole_Trigger
|
||||
create trigger delete_grants_of_role_tg
|
||||
before delete
|
||||
on RbacRole
|
||||
on rbac.role
|
||||
for each row
|
||||
execute procedure deleteRbacGrantsOfRbacRole();
|
||||
execute procedure rbac.delete_grants_of_role_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-BEFORE-DELETE-OBJECT-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-BEFORE-DELETE-OBJECT-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
RbacObject BEFORE DELETE TRIGGER function which deletes all related roles.
|
||||
rbac.object BEFORE DELETE TRIGGER function which deletes all related roles.
|
||||
*/
|
||||
create or replace function deleteRbacRolesOfRbacObject()
|
||||
create or replace function rbac.delete_roles_of_object_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if TG_OP = 'DELETE' then
|
||||
delete from RbacPermission p where p.objectuuid = old.uuid;
|
||||
delete from RbacRole r where r.objectUuid = old.uuid;
|
||||
delete from rbac.permission p where p.objectuuid = old.uuid;
|
||||
delete from rbac.role r where r.objectUuid = old.uuid;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
|
||||
end if;
|
||||
@@ -340,23 +350,20 @@ begin
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Installs the RbacRole BEFORE DELETE TRIGGER.
|
||||
Installs the rbac.role BEFORE DELETE TRIGGER.
|
||||
*/
|
||||
create trigger deleteRbacRolesOfRbacObject_Trigger
|
||||
create trigger delete_roles_of_object_tg
|
||||
before delete
|
||||
on RbacObject
|
||||
on rbac.object
|
||||
for each row
|
||||
execute procedure deleteRbacRolesOfRbacObject();
|
||||
execute procedure rbac.delete_roles_of_object_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-PERMISSION:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
|
||||
*/
|
||||
create domain RbacOp as varchar(6)
|
||||
create domain rbac.RbacOp as varchar(6)
|
||||
check (
|
||||
VALUE = 'DELETE'
|
||||
or VALUE = 'UPDATE'
|
||||
@@ -365,23 +372,23 @@ create domain RbacOp as varchar(6)
|
||||
or VALUE = 'ASSUME'
|
||||
);
|
||||
|
||||
create table RbacPermission
|
||||
create table rbac.permission
|
||||
(
|
||||
uuid uuid primary key references RbacReference (uuid) on delete cascade,
|
||||
objectUuid uuid not null references RbacObject,
|
||||
op RbacOp not null,
|
||||
uuid uuid primary key references rbac.reference (uuid) on delete cascade,
|
||||
objectUuid uuid not null references rbac.object,
|
||||
op rbac.RbacOp not null,
|
||||
opTableName varchar(60)
|
||||
);
|
||||
-- TODO.perf: check if these indexes are really useful
|
||||
create index on RbacPermission (objectUuid, op);
|
||||
create index on RbacPermission (opTableName, op);
|
||||
create index on rbac.permission (objectUuid, op);
|
||||
create index on rbac.permission (opTableName, op);
|
||||
|
||||
ALTER TABLE RbacPermission
|
||||
ALTER TABLE rbac.permission
|
||||
ADD CONSTRAINT RbacPermission_uc UNIQUE NULLS NOT DISTINCT (objectUuid, op, opTableName);
|
||||
|
||||
call create_journal('RbacPermission');
|
||||
call base.create_journal('rbac.permission');
|
||||
|
||||
create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
create or replace function rbac.createPermission(forObjectUuid uuid, forOp rbac.RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@@ -398,50 +405,50 @@ begin
|
||||
end if;
|
||||
|
||||
permissionUuid := (
|
||||
select uuid from RbacPermission
|
||||
select uuid from rbac.permission
|
||||
where objectUuid = forObjectUuid
|
||||
and op = forOp and opTableName is not distinct from forOpTableName);
|
||||
if (permissionUuid is null) then
|
||||
insert into RbacReference ("type")
|
||||
values ('RbacPermission')
|
||||
insert into rbac.reference ("type")
|
||||
values ('rbac.permission')
|
||||
returning uuid into permissionUuid;
|
||||
begin
|
||||
insert into RbacPermission (uuid, objectUuid, op, opTableName)
|
||||
insert into rbac.permission (uuid, objectUuid, op, opTableName)
|
||||
values (permissionUuid, forObjectUuid, forOp, forOpTableName);
|
||||
exception
|
||||
when others then
|
||||
raise exception 'insert into RbacPermission (uuid, objectUuid, op, opTableName)
|
||||
raise exception 'insert into rbac.permission (uuid, objectUuid, op, opTableName)
|
||||
values (%, %, %, %);', permissionUuid, forObjectUuid, forOp, forOpTableName;
|
||||
end;
|
||||
end if;
|
||||
return permissionUuid;
|
||||
end; $$;
|
||||
|
||||
create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
create or replace function rbac.findEffectivePermissionId(forObjectUuid uuid, forOp rbac.RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select uuid
|
||||
from RbacPermission p
|
||||
from rbac.permission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and (forOp = 'SELECT' or p.op = forOp) -- all other RbacOp include 'SELECT'
|
||||
and (forOp = 'SELECT' or p.op = forOp) -- all other rbac.RbacOp include 'SELECT'
|
||||
and p.opTableName = forOpTableName
|
||||
$$;
|
||||
|
||||
create or replace function findPermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
create or replace function rbac.findPermissionId(forObjectUuid uuid, forOp rbac.RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select uuid
|
||||
from RbacPermission p
|
||||
from rbac.permission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and p.op = forOp
|
||||
and p.opTableName = forOpTableName
|
||||
$$;
|
||||
|
||||
create or replace function getPermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
create or replace function rbac.getPermissionId(forObjectUuid uuid, forOp rbac.RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
@@ -449,7 +456,7 @@ declare
|
||||
permissionUuid uuid;
|
||||
begin
|
||||
select uuid into permissionUuid
|
||||
from RbacPermission p
|
||||
from rbac.permission p
|
||||
where p.objectUuid = forObjectUuid
|
||||
and p.op = forOp
|
||||
and forOpTableName is null or p.opTableName = forOpTableName;
|
||||
@@ -461,17 +468,17 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-duplicate-role-grant-exception:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-duplicate-role-grant-exception endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure raiseDuplicateRoleGrantException(subRoleId uuid, superRoleId uuid)
|
||||
create or replace procedure rbac.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;
|
||||
select roleIdName from rbac.role_ev where uuid=subRoleId into subRoleIdName;
|
||||
select roleIdName from rbac.role_ev where uuid=superRoleId into superRoleIdName;
|
||||
raise exception '[400] Duplicate role grant detected: role % (%) already granted to % (%)', subRoleId, subRoleIdName, superRoleId, superRoleIdName;
|
||||
end;
|
||||
$$;
|
||||
@@ -479,54 +486,54 @@ $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-GRANTS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-GRANTS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Table to store grants / role- or permission assignments to users or roles.
|
||||
Table to store grants / role- or permission assignments to subjects or roles.
|
||||
*/
|
||||
create table RbacGrants
|
||||
create table rbac.grants
|
||||
(
|
||||
uuid uuid primary key default uuid_generate_v4(),
|
||||
grantedByTriggerOf uuid references RbacObject (uuid) on delete cascade initially deferred ,
|
||||
grantedByRoleUuid uuid references RbacRole (uuid),
|
||||
ascendantUuid uuid references RbacReference (uuid),
|
||||
descendantUuid uuid references RbacReference (uuid),
|
||||
grantedByTriggerOf uuid references rbac.object (uuid) on delete cascade initially deferred ,
|
||||
grantedByRoleUuid uuid references rbac.role (uuid),
|
||||
ascendantUuid uuid references rbac.reference (uuid),
|
||||
descendantUuid uuid references rbac.reference (uuid),
|
||||
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
|
||||
unique (ascendantUuid, descendantUuid),
|
||||
constraint rbacGrant_createdBy check ( grantedByRoleUuid is null or grantedByTriggerOf is null) );
|
||||
create index on RbacGrants (ascendantUuid);
|
||||
create index on RbacGrants (descendantUuid);
|
||||
create index on rbac.grants (ascendantUuid);
|
||||
create index on rbac.grants (descendantUuid);
|
||||
|
||||
call create_journal('RbacGrants');
|
||||
create or replace function findGrantees(grantedId uuid)
|
||||
returns setof RbacReference
|
||||
call base.create_journal('rbac.grants');
|
||||
create or replace function rbac.findGrantees(grantedId uuid)
|
||||
returns setof rbac.reference
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
with recursive grants as (
|
||||
select descendantUuid, ascendantUuid
|
||||
from RbacGrants
|
||||
from rbac.grants
|
||||
where descendantUuid = grantedId
|
||||
union all
|
||||
select g.descendantUuid, g.ascendantUuid
|
||||
from RbacGrants g
|
||||
from rbac.grants g
|
||||
inner join grants on grants.ascendantUuid = g.descendantUuid
|
||||
)
|
||||
select ref.*
|
||||
from grants
|
||||
join RbacReference ref on ref.uuid = grants.ascendantUuid;
|
||||
join rbac.reference ref on ref.uuid = grants.ascendantUuid;
|
||||
$$;
|
||||
|
||||
create or replace function isGranted(granteeIds uuid[], grantedId uuid)
|
||||
create or replace function rbac.isGranted(granteeIds uuid[], grantedId uuid)
|
||||
returns bool
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
with recursive grants as (
|
||||
select descendantUuid, ascendantUuid
|
||||
from RbacGrants
|
||||
from rbac.grants
|
||||
where descendantUuid = grantedId
|
||||
union all
|
||||
select "grant".descendantUuid, "grant".ascendantUuid
|
||||
from RbacGrants "grant"
|
||||
from rbac.grants "grant"
|
||||
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid
|
||||
)
|
||||
select exists (
|
||||
@@ -536,23 +543,23 @@ select exists (
|
||||
) or grantedId = any(granteeIds);
|
||||
$$;
|
||||
|
||||
create or replace function isGranted(granteeId uuid, grantedId uuid)
|
||||
create or replace function rbac.isGranted(granteeId uuid, grantedId uuid)
|
||||
returns bool
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select * from isGranted(array[granteeId], grantedId);
|
||||
select * from rbac.isGranted(array[granteeId], grantedId);
|
||||
$$;
|
||||
create or replace function isPermissionGrantedToSubject(permissionId uuid, subjectId uuid)
|
||||
create or replace function rbac.isPermissionGrantedToSubject(permissionId uuid, subjectId uuid)
|
||||
returns BOOL
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
with recursive grants as (
|
||||
select descendantUuid, ascendantUuid
|
||||
from RbacGrants
|
||||
from rbac.grants
|
||||
where descendantUuid = permissionId
|
||||
union all
|
||||
select g.descendantUuid, g.ascendantUuid
|
||||
from RbacGrants g
|
||||
from rbac.grants g
|
||||
inner join grants on grants.ascendantUuid = g.descendantUuid
|
||||
)
|
||||
select exists(
|
||||
@@ -562,117 +569,117 @@ select exists(
|
||||
);
|
||||
$$;
|
||||
|
||||
create or replace function hasInsertPermission(objectUuid uuid, tableName text )
|
||||
create or replace function rbac.hasInsertPermission(objectUuid uuid, tableName text )
|
||||
returns BOOL
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
permissionUuid uuid;
|
||||
begin
|
||||
permissionUuid = findPermissionId(objectUuid, 'INSERT'::RbacOp, tableName);
|
||||
permissionUuid = rbac.findPermissionId(objectUuid, 'INSERT'::rbac.RbacOp, tableName);
|
||||
return permissionUuid is not null;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function hasGlobalRoleGranted(userUuid uuid)
|
||||
create or replace function rbac.hasGlobalRoleGranted(forAscendantUuid uuid)
|
||||
returns bool
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select exists(
|
||||
select r.uuid
|
||||
from RbacGrants as g
|
||||
join RbacRole as r on r.uuid = g.descendantuuid
|
||||
join RbacObject as o on o.uuid = r.objectuuid
|
||||
where g.ascendantuuid = userUuid
|
||||
and o.objecttable = 'global'
|
||||
from rbac.grants as g
|
||||
join rbac.role as r on r.uuid = g.descendantuuid
|
||||
join rbac.object as o on o.uuid = r.objectuuid
|
||||
where g.ascendantuuid = forAscendantUuid
|
||||
and o.objecttable = 'rbac.global'
|
||||
);
|
||||
$$;
|
||||
|
||||
create or replace procedure grantPermissionToRole(permissionUuid uuid, roleUuid uuid)
|
||||
create or replace procedure rbac.grantPermissionToRole(permissionUuid uuid, roleUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
|
||||
perform assertReferenceType('permissionId (descendant)', permissionUuid, 'RbacPermission');
|
||||
perform rbac.assertReferenceType('roleId (ascendant)', roleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('permissionId (descendant)', permissionUuid, 'rbac.permission');
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
|
||||
values (currentTriggerObjectUuid(), roleUuid, permissionUuid, true)
|
||||
into rbac.grants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
|
||||
values (rbac.currentTriggerObjectUuid(), roleUuid, permissionUuid, true)
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace procedure grantPermissionToRole(permissionUuid uuid, roleDesc RbacRoleDescriptor)
|
||||
create or replace procedure rbac.grantPermissionToRole(permissionUuid uuid, roleDesc rbac.RoleDescriptor)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call grantPermissionToRole(permissionUuid, findRoleId(roleDesc));
|
||||
call rbac.grantPermissionToRole(permissionUuid, rbac.findRoleId(roleDesc));
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace procedure grantRoleToRole(subRoleId uuid, superRoleId uuid, doAssume bool = true)
|
||||
create or replace procedure rbac.grantRoleToRole(subRoleId uuid, superRoleId uuid, doAssume bool = true)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
|
||||
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'rbac.role');
|
||||
|
||||
if isGranted(subRoleId, superRoleId) then
|
||||
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
if rbac.isGranted(subRoleId, superRoleId) then
|
||||
call rbac.raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
end if;
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||
into rbac.grants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||
values (rbac.currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
|
||||
create or replace procedure grantRoleToRole(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor, doAssume bool = true)
|
||||
create or replace procedure rbac.grantRoleToRole(subRole rbac.RoleDescriptor, superRole rbac.RoleDescriptor, doAssume bool = true)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
superRoleId uuid;
|
||||
subRoleId uuid;
|
||||
begin
|
||||
-- TODO.refa: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
|
||||
-- TODO.refa: maybe separate method rbac.grantRoleToRoleIfNotNull(...) for NULLABLE references
|
||||
if superRole.objectUuid is null or subRole.objectuuid is null then
|
||||
return;
|
||||
end if;
|
||||
|
||||
superRoleId := findRoleId(superRole);
|
||||
subRoleId := findRoleId(subRole);
|
||||
superRoleId := rbac.findRoleId(superRole);
|
||||
subRoleId := rbac.findRoleId(subRole);
|
||||
|
||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
|
||||
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'rbac.role');
|
||||
|
||||
if isGranted(subRoleId, superRoleId) then
|
||||
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
if rbac.isGranted(subRoleId, superRoleId) then
|
||||
call rbac.raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
end if;
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||
into rbac.grants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||
values (rbac.currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure revokeRoleFromRole(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor)
|
||||
create or replace procedure rbac.revokeRoleFromRole(subRole rbac.RoleDescriptor, superRole rbac.RoleDescriptor)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
superRoleId uuid;
|
||||
subRoleId uuid;
|
||||
begin
|
||||
superRoleId := findRoleId(superRole);
|
||||
subRoleId := findRoleId(subRole);
|
||||
superRoleId := rbac.findRoleId(superRole);
|
||||
subRoleId := rbac.findRoleId(subRole);
|
||||
|
||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
|
||||
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'rbac.role');
|
||||
|
||||
if (isGranted(superRoleId, subRoleId)) then
|
||||
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
|
||||
if (rbac.isGranted(superRoleId, subRoleId)) then
|
||||
delete from rbac.grants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
|
||||
else
|
||||
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)
|
||||
create or replace procedure rbac.revokePermissionFromRole(permissionId UUID, superRole rbac.RoleDescriptor)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
superRoleId uuid;
|
||||
@@ -680,18 +687,18 @@ declare
|
||||
objectTable text;
|
||||
objectUuid uuid;
|
||||
begin
|
||||
superRoleId := findRoleId(superRole);
|
||||
superRoleId := rbac.findRoleId(superRole);
|
||||
|
||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||
perform assertReferenceType('permission (descendant)', permissionId, 'RbacPermission');
|
||||
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
|
||||
perform rbac.assertReferenceType('permission (descendant)', permissionId, 'rbac.permission');
|
||||
|
||||
if (isGranted(superRoleId, permissionId)) then
|
||||
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = permissionId;
|
||||
if (rbac.isGranted(superRoleId, permissionId)) then
|
||||
delete from rbac.grants 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
|
||||
from rbac.grants g
|
||||
join rbac.permission p on p.uuid=g.descendantUuid
|
||||
join rbac.object o on o.uuid=p.objectUuid
|
||||
where g.uuid=permissionId
|
||||
into permissionOp, objectTable, objectUuid;
|
||||
|
||||
@@ -701,13 +708,13 @@ begin
|
||||
end; $$;
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS:1 runOnChange=true endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS runOnChange=true endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
|
||||
*/
|
||||
create or replace function queryAccessibleObjectUuidsOfSubjectIds(
|
||||
requiredOp RbacOp,
|
||||
create or replace function rbac.queryAccessibleObjectUuidsOfSubjectIds(
|
||||
requiredOp rbac.RbacOp,
|
||||
forObjectTable varchar,
|
||||
subjectIds uuid[],
|
||||
maxObjects integer = 8000)
|
||||
@@ -720,12 +727,12 @@ begin
|
||||
return query
|
||||
WITH RECURSIVE grants AS (
|
||||
SELECT descendantUuid, ascendantUuid, 1 AS level
|
||||
FROM RbacGrants
|
||||
FROM rbac.grants
|
||||
WHERE assumed
|
||||
AND ascendantUuid = any(subjectIds)
|
||||
UNION ALL
|
||||
SELECT g.descendantUuid, g.ascendantUuid, grants.level + 1 AS level
|
||||
FROM RbacGrants g
|
||||
FROM rbac.grants g
|
||||
INNER JOIN grants ON grants.descendantUuid = g.ascendantUuid
|
||||
WHERE g.assumed
|
||||
),
|
||||
@@ -735,13 +742,13 @@ begin
|
||||
)
|
||||
SELECT DISTINCT perm.objectUuid
|
||||
FROM granted
|
||||
JOIN RbacPermission perm ON granted.descendantUuid = perm.uuid
|
||||
JOIN RbacObject obj ON obj.uuid = perm.objectUuid
|
||||
JOIN rbac.permission perm ON granted.descendantUuid = perm.uuid
|
||||
JOIN rbac.object obj ON obj.uuid = perm.objectUuid
|
||||
WHERE (requiredOp = 'SELECT' OR perm.op = requiredOp)
|
||||
AND obj.objectTable = forObjectTable
|
||||
LIMIT maxObjects+1;
|
||||
|
||||
foundRows = lastRowCount();
|
||||
foundRows = base.lastRowCount();
|
||||
if foundRows > maxObjects then
|
||||
raise exception '[400] Too many accessible objects, limit is %, found %.', maxObjects, foundRows
|
||||
using
|
||||
@@ -753,26 +760,26 @@ $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-QUERY-GRANTED-PERMISSIONS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-QUERY-GRANTED-PERMISSIONS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns all permissions accessible to the given subject UUID (user or role).
|
||||
Returns all permissions accessible to the given subject UUID (subject or role).
|
||||
*/
|
||||
create or replace function queryPermissionsGrantedToSubjectId(subjectId uuid)
|
||||
returns setof RbacPermission
|
||||
create or replace function rbac.queryPermissionsGrantedToSubjectId(subjectId uuid)
|
||||
returns setof rbac.permission
|
||||
strict
|
||||
language sql as $$
|
||||
with recursive grants as (
|
||||
select descendantUuid, ascendantUuid
|
||||
from RbacGrants
|
||||
from rbac.grants
|
||||
where ascendantUuid = subjectId
|
||||
union all
|
||||
select g.descendantUuid, g.ascendantUuid
|
||||
from RbacGrants g
|
||||
from rbac.grants g
|
||||
inner join grants on grants.descendantUuid = g.ascendantUuid
|
||||
)
|
||||
select perm.*
|
||||
from RbacPermission perm
|
||||
from rbac.permission perm
|
||||
where perm.uuid in (
|
||||
select descendantUuid
|
||||
from grants
|
||||
@@ -782,27 +789,27 @@ $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-QUERY-USERS-WITH-PERMISSION-FOR-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-QUERY-SUBJECTS-WITH-PERMISSION-FOR-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns all user UUIDs which have any permission for the given object UUID.
|
||||
Returns all subject UUIDs which have any permission for the given object UUID.
|
||||
*/
|
||||
|
||||
create or replace function queryAllRbacUsersWithPermissionsFor(objectId uuid)
|
||||
returns setof RbacUser
|
||||
create or replace function rbac.queryAllRbacSubjectsWithPermissionsFor(objectId uuid)
|
||||
returns setof rbac.subject
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select *
|
||||
from RbacUser
|
||||
from rbac.subject
|
||||
where uuid in (
|
||||
-- @formatter:off
|
||||
with recursive grants as (
|
||||
select descendantUuid, ascendantUuid
|
||||
from RbacGrants
|
||||
from rbac.grants
|
||||
where descendantUuid = objectId
|
||||
union all
|
||||
select "grant".descendantUuid, "grant".ascendantUuid
|
||||
from RbacGrants "grant"
|
||||
from rbac.grants "grant"
|
||||
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid
|
||||
)
|
||||
-- @formatter:on
|
||||
@@ -813,7 +820,7 @@ $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-base-PGSQL-ROLES:1 context:dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-base-PGSQL-ROLES context:dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do $$
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:rbac-user-grant-GRANT-ROLE-TO-USER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function rbac.assumedRoleUuid()
|
||||
returns uuid
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentSubjectOrAssumedRolesUuids uuid[];
|
||||
begin
|
||||
-- exactly one role must be assumed, not none not more than one
|
||||
if cardinality(base.assumedRoles()) <> 1 then
|
||||
raise exception '[400] Granting roles to user is only possible if exactly one role is assumed, given: %', base.assumedRoles();
|
||||
end if;
|
||||
|
||||
currentSubjectOrAssumedRolesUuids := rbac.currentSubjectOrAssumedRolesUuids();
|
||||
return currentSubjectOrAssumedRolesUuids[1];
|
||||
end; $$;
|
||||
|
||||
create or replace procedure rbac.grantRoleToSubjectUnchecked(grantedByRoleUuid uuid, grantedRoleUuid uuid, subjectUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform rbac.assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('roleId (descendant)', grantedRoleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
|
||||
|
||||
insert
|
||||
into rbac.grants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, subjectUuid, grantedRoleUuid, doAssume)
|
||||
-- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception?
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure rbac.grantRoleToSubject(grantedByRoleUuid uuid, grantedRoleUuid uuid, subjectUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
grantedByRoleIdName text;
|
||||
grantedRoleIdName text;
|
||||
begin
|
||||
perform rbac.assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
|
||||
|
||||
assert grantedByRoleUuid is not null, 'grantedByRoleUuid must not be null';
|
||||
assert grantedRoleUuid is not null, 'grantedRoleUuid must not be null';
|
||||
assert subjectUuid is not null, 'subjectUuid must not be null';
|
||||
|
||||
if NOT rbac.isGranted(rbac.currentSubjectOrAssumedRolesUuids(), grantedByRoleUuid) then
|
||||
select roleIdName from rbac.role_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
|
||||
raise exception '[403] Access to granted-by-role % (%) forbidden for % (%)',
|
||||
grantedByRoleIdName, grantedByRoleUuid, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end if;
|
||||
if NOT rbac.isGranted(grantedByRoleUuid, grantedRoleUuid) then
|
||||
select roleIdName from rbac.role_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
|
||||
select roleIdName from rbac.role_ev where uuid=grantedRoleUuid into grantedRoleIdName;
|
||||
raise exception '[403] Access to granted role % (%) forbidden for % (%)',
|
||||
grantedRoleIdName, grantedRoleUuid, grantedByRoleIdName, grantedByRoleUuid;
|
||||
end if;
|
||||
|
||||
insert
|
||||
into rbac.grants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, subjectUuid, grantedRoleUuid, doAssume);
|
||||
-- TODO.impl: 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; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:rbac-user-grant-REVOKE-ROLE-FROM-USER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure rbac.checkRevokeRoleFromSubjectPreconditions(grantedByRoleUuid uuid, grantedRoleUuid uuid, subjectUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform rbac.assertReferenceType('grantedByRoleUuid', grantedByRoleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'rbac.role');
|
||||
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
|
||||
|
||||
if NOT rbac.isGranted(rbac.currentSubjectOrAssumedRolesUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Revoking role created by % is forbidden for %.', grantedByRoleUuid, base.currentSubjects();
|
||||
end if;
|
||||
|
||||
if NOT rbac.isGranted(grantedByRoleUuid, grantedRoleUuid) then
|
||||
raise exception '[403] Revoking role % is forbidden for %.', grantedRoleUuid, base.currentSubjects();
|
||||
end if;
|
||||
|
||||
--raise exception 'rbac.isGranted(%, %)', rbac.currentSubjectOrAssumedRolesUuids(), grantedByRoleUuid;
|
||||
if NOT rbac.isGranted(rbac.currentSubjectOrAssumedRolesUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Revoking role granted by % is forbidden for %.', grantedByRoleUuid, base.currentSubjects();
|
||||
end if;
|
||||
|
||||
if NOT rbac.isGranted(subjectUuid, grantedRoleUuid) then
|
||||
raise exception '[404] No such grant found granted by % for subject % to role %.', grantedByRoleUuid, subjectUuid, grantedRoleUuid;
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
create or replace procedure rbac.revokeRoleFromSubject(grantedByRoleUuid uuid, grantedRoleUuid uuid, subjectUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call rbac.checkRevokeRoleFromSubjectPreconditions(grantedByRoleUuid, grantedRoleUuid, subjectUuid);
|
||||
|
||||
raise INFO 'delete from rbac.grants where ascendantUuid = % and descendantUuid = %', subjectUuid, grantedRoleUuid;
|
||||
delete from rbac.grants as g
|
||||
where g.ascendantUuid = subjectUuid and g.descendantUuid = grantedRoleUuid
|
||||
and g.grantedByRoleUuid = revokeRoleFromSubject.grantedByRoleUuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:rbac-user-grant-REVOKE-PERMISSION-FROM-ROLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure rbac.revokePermissionFromRole(permissionUuid uuid, superRoleUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
raise INFO 'delete from rbac.grants where ascendantUuid = % and descendantUuid = %', superRoleUuid, permissionUuid;
|
||||
delete from rbac.grants as g
|
||||
where g.ascendantUuid = superRoleUuid and g.descendantUuid = permissionUuid;
|
||||
end; $$;
|
||||
--//
|
||||
@@ -1,125 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-user-grant-GRANT-ROLE-TO-USER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function assumedRoleUuid()
|
||||
returns uuid
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentSubjectsUuids uuid[];
|
||||
begin
|
||||
-- exactly one role must be assumed, not none not more than one
|
||||
if cardinality(assumedRoles()) <> 1 then
|
||||
raise exception '[400] Granting roles to user is only possible if exactly one role is assumed, given: %', assumedRoles();
|
||||
end if;
|
||||
|
||||
currentSubjectsUuids := currentSubjectsUuids();
|
||||
return currentSubjectsUuids[1];
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('roleId (descendant)', grantedRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userId (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, userUuid, grantedRoleUuid, doAssume)
|
||||
-- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception?
|
||||
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');
|
||||
|
||||
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
|
||||
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
|
||||
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, userUuid, grantedRoleUuid, doAssume);
|
||||
-- TODO.impl: What should happen on mupltiple 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; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-user-grant-REVOKE-ROLE-FROM-USER:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure checkRevokeRoleFromUserPreconditions(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('grantedByRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Revoking role created by % is forbidden for %.', grantedByRoleUuid, currentSubjects();
|
||||
end if;
|
||||
|
||||
if NOT isGranted(grantedByRoleUuid, grantedRoleUuid) then
|
||||
raise exception '[403] Revoking role % is forbidden for %.', grantedRoleUuid, currentSubjects();
|
||||
end if;
|
||||
|
||||
--raise exception 'isGranted(%, %)', currentSubjectsUuids(), grantedByRoleUuid;
|
||||
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
|
||||
raise exception '[403] Revoking role granted by % is forbidden for %.', grantedByRoleUuid, currentSubjects();
|
||||
end if;
|
||||
|
||||
if NOT isGranted(userUuid, grantedRoleUuid) then
|
||||
raise exception '[404] No such grant found granted by % for user % to role %.', grantedByRoleUuid, userUuid, grantedRoleUuid;
|
||||
end if;
|
||||
end; $$;
|
||||
|
||||
create or replace procedure revokeRoleFromUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call checkRevokeRoleFromUserPreconditions(grantedByRoleUuid, grantedRoleUuid, userUuid);
|
||||
|
||||
raise INFO 'delete from RbacGrants where ascendantUuid = % and descendantUuid = %', userUuid, grantedRoleUuid;
|
||||
delete from RbacGrants as g
|
||||
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; $$;
|
||||
--//
|
||||
@@ -2,28 +2,28 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-context-DETERMINE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-context-DETERMINE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace function determineCurrentUserUuid(currentUser varchar)
|
||||
create or replace function rbac.determineCurrentSubjectUuid(currentSubject varchar)
|
||||
returns uuid
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentUserUuid uuid;
|
||||
currentSubjectUuid uuid;
|
||||
begin
|
||||
if currentUser = '' then
|
||||
if currentSubject = '' then
|
||||
return null;
|
||||
end if;
|
||||
|
||||
select uuid from RbacUser where name = currentUser into currentUserUuid;
|
||||
if currentUserUuid is null then
|
||||
raise exception '[401] user % given in `defineContext(...)` does not exist', currentUser;
|
||||
select uuid from rbac.subject where name = currentSubject into currentSubjectUuid;
|
||||
if currentSubjectUuid is null then
|
||||
raise exception '[401] subject % given in `base.defineContext(...)` does not exist', currentSubject;
|
||||
end if;
|
||||
return currentUserUuid;
|
||||
return currentSubjectUuid;
|
||||
end; $$;
|
||||
|
||||
create or replace function determineCurrentSubjectsUuids(currentUserUuid uuid, assumedRoles varchar)
|
||||
create or replace function rbac.determinecurrentsubjectorassumedrolesuuids(currentSubjectOrAssumedRolesUuids uuid, assumedRoles varchar)
|
||||
returns uuid[]
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
@@ -33,11 +33,11 @@ declare
|
||||
objectTableToAssume varchar(63);
|
||||
objectNameToAssume varchar(63);
|
||||
objectUuidToAssume uuid;
|
||||
roleTypeToAssume RbacRoleType;
|
||||
roleTypeToAssume rbac.RoleType;
|
||||
roleIdsToAssume uuid[];
|
||||
roleUuidToAssume uuid;
|
||||
begin
|
||||
if currentUserUuid is null then
|
||||
if currentSubjectOrAssumedRolesUuids is null then
|
||||
if length(coalesce(assumedRoles, '')) > 0 then
|
||||
raise exception '[403] undefined has no permission to assume role %', assumedRoles;
|
||||
else
|
||||
@@ -45,7 +45,7 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
if length(coalesce(assumedRoles, '')) = 0 then
|
||||
return array [currentUserUuid];
|
||||
return array [currentSubjectOrAssumedRolesUuids];
|
||||
end if;
|
||||
|
||||
foreach roleName in array string_to_array(assumedRoles, ';')
|
||||
@@ -55,21 +55,21 @@ begin
|
||||
objectNameToAssume = split_part(roleNameParts, '#', 2);
|
||||
roleTypeToAssume = split_part(roleNameParts, '#', 3);
|
||||
|
||||
objectUuidToAssume = findObjectUuidByIdName(objectTableToAssume, objectNameToAssume);
|
||||
objectUuidToAssume = base.findObjectUuidByIdName(objectTableToAssume, objectNameToAssume);
|
||||
if objectUuidToAssume is null then
|
||||
raise exception '[401] object % cannot be found in table %', objectNameToAssume, objectTableToAssume;
|
||||
raise exception '[401] object % cannot be found in table % (from roleNameParts=%)', objectNameToAssume, objectTableToAssume, roleNameParts;
|
||||
end if;
|
||||
|
||||
select uuid
|
||||
from RbacRole r
|
||||
from rbac.role r
|
||||
where r.objectUuid = objectUuidToAssume
|
||||
and r.roleType = roleTypeToAssume
|
||||
into roleUuidToAssume;
|
||||
if roleUuidToAssume is null then
|
||||
raise exception '[403] role % does not exist or is not accessible for user %', roleName, currentUser();
|
||||
raise exception '[403] role % does not exist or is not accessible for subject %', roleName, base.currentSubject();
|
||||
end if;
|
||||
if not isGranted(currentUserUuid, roleUuidToAssume) then
|
||||
raise exception '[403] user % has no permission to assume role %', currentUser(), roleName;
|
||||
if not rbac.isGranted(currentSubjectOrAssumedRolesUuids, roleUuidToAssume) then
|
||||
raise exception '[403] subject % has no permission to assume role %', base.currentSubject(), roleName;
|
||||
end if;
|
||||
roleIdsToAssume := roleIdsToAssume || roleUuidToAssume;
|
||||
end loop;
|
||||
@@ -78,102 +78,102 @@ begin
|
||||
end; $$;
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-context-CONTEXT-DEFINED:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-context-CONTEXT-DEFINED endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Callback which is called after the context has been (re-) defined.
|
||||
This function will be overwritten by later changesets.
|
||||
*/
|
||||
create or replace procedure contextDefined(
|
||||
create or replace procedure base.contextDefined(
|
||||
currentTask varchar(127),
|
||||
currentRequest text,
|
||||
currentUser varchar(63),
|
||||
currentSubject varchar(63),
|
||||
assumedRoles varchar(1023)
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentUserUuid uuid;
|
||||
currentSubjectUuid uuid;
|
||||
begin
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
execute format('set local hsadminng.currentRequest to %L', currentRequest);
|
||||
|
||||
execute format('set local hsadminng.currentUser to %L', currentUser);
|
||||
select determineCurrentUserUuid(currentUser) into currentUserUuid;
|
||||
execute format('set local hsadminng.currentUserUuid to %L', coalesce(currentUserUuid::text, ''));
|
||||
execute format('set local hsadminng.currentSubject to %L', currentSubject);
|
||||
select rbac.determineCurrentSubjectUuid(currentSubject) into currentSubjectUuid;
|
||||
execute format('set local hsadminng.currentSubjectUuid to %L', coalesce(currentSubjectUuid::text, ''));
|
||||
|
||||
execute format('set local hsadminng.assumedRoles to %L', assumedRoles);
|
||||
execute format('set local hsadminng.currentSubjectsUuids to %L',
|
||||
(select array_to_string(determinecurrentSubjectsUuids(currentUserUuid, assumedRoles), ';')));
|
||||
execute format('set local hsadminng.currentSubjectOrAssumedRolesUuids to %L',
|
||||
(select array_to_string(rbac.determinecurrentsubjectorassumedrolesuuids(currentSubjectUuid, assumedRoles), ';')));
|
||||
|
||||
raise notice 'Context defined as: %, %, %, [%]', currentTask, currentRequest, currentUser, assumedRoles;
|
||||
raise notice 'Context defined as: %, %, %, [%]', currentTask, currentRequest, currentSubject, assumedRoles;
|
||||
end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-context-CURRENT-USER-ID:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-context-current-subject-ID endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the uuid of the current user as set via `defineContext(...)`.
|
||||
Returns the uuid of the current subject as set via `base.defineContext(...)`.
|
||||
*/
|
||||
|
||||
create or replace function currentUserUuid()
|
||||
create or replace function rbac.currentSubjectUuid()
|
||||
returns uuid
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentUserUuid text;
|
||||
currentUserName text;
|
||||
currentSubjectUuid text;
|
||||
currentSubjectName text;
|
||||
begin
|
||||
begin
|
||||
currentUserUuid := current_setting('hsadminng.currentUserUuid');
|
||||
currentSubjectUuid := current_setting('hsadminng.currentSubjectUuid');
|
||||
exception
|
||||
when others then
|
||||
currentUserUuid := null;
|
||||
currentSubjectUuid := null;
|
||||
end;
|
||||
if (currentUserUuid is null or currentUserUuid = '') then
|
||||
currentUserName := currentUser();
|
||||
if (length(currentUserName) > 0) then
|
||||
raise exception '[401] currentUserUuid cannot be determined, unknown user name "%"', currentUserName;
|
||||
if (currentSubjectUuid is null or currentSubjectUuid = '') then
|
||||
currentSubjectName := base.currentSubject();
|
||||
if (length(currentSubjectName) > 0) then
|
||||
raise exception '[401] currentSubjectUuid cannot be determined, unknown subject name "%"', currentSubjectName;
|
||||
else
|
||||
raise exception '[401] currentUserUuid cannot be determined, please call `defineContext(...)` first;"';
|
||||
raise exception '[401] currentSubjectUuid cannot be determined, please call `base.defineContext(...)` first;"';
|
||||
end if;
|
||||
end if;
|
||||
return currentUserUuid::uuid;
|
||||
return currentSubjectUuid::uuid;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-context-CURRENT-SUBJECT-UUIDS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-context-CURRENT-SUBJECT-UUIDS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the uuid of the current user as set via `defineContext(...)`,
|
||||
or, if any, the uuids of all assumed roles as set via `defineContext(...)`
|
||||
Returns the uuid of the current subject as set via `base.defineContext(...)`,
|
||||
or, if any, the uuids of all assumed roles as set via `base.defineContext(...)`
|
||||
or empty array, if context is not defined.
|
||||
*/
|
||||
create or replace function currentSubjectsUuids()
|
||||
create or replace function rbac.currentSubjectOrAssumedRolesUuids()
|
||||
returns uuid[]
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentSubjectsUuids text;
|
||||
currentUserName text;
|
||||
currentSubjectOrAssumedRolesUuids text;
|
||||
currentSubjectName text;
|
||||
begin
|
||||
begin
|
||||
currentSubjectsUuids := current_setting('hsadminng.currentSubjectsUuids');
|
||||
currentSubjectOrAssumedRolesUuids := current_setting('hsadminng.currentSubjectOrAssumedRolesUuids');
|
||||
exception
|
||||
when others then
|
||||
currentSubjectsUuids := null;
|
||||
currentSubjectOrAssumedRolesUuids := null;
|
||||
end;
|
||||
if (currentSubjectsUuids is null or length(currentSubjectsUuids) = 0 ) then
|
||||
currentUserName := currentUser();
|
||||
if (length(currentUserName) > 0) then
|
||||
raise exception '[401] currentSubjectsUuids (%) cannot be determined, unknown user name "%"', currentSubjectsUuids, currentUserName;
|
||||
if (currentSubjectOrAssumedRolesUuids is null or length(currentSubjectOrAssumedRolesUuids) = 0 ) then
|
||||
currentSubjectName := base.currentSubject();
|
||||
if (length(currentSubjectName) > 0) then
|
||||
raise exception '[401] currentSubjectOrAssumedRolesUuids (%) cannot be determined, unknown subject name "%"', currentSubjectOrAssumedRolesUuids, currentSubjectName;
|
||||
else
|
||||
raise exception '[401] currentSubjectsUuids cannot be determined, please call `defineContext(...)` with a valid user;"';
|
||||
raise exception '[401] currentSubjectOrAssumedRolesUuids cannot be determined, please call `base.defineContext(...)` with a valid subject;"';
|
||||
end if;
|
||||
end if;
|
||||
return string_to_array(currentSubjectsUuids, ';');
|
||||
return string_to_array(currentSubjectOrAssumedRolesUuids, ';');
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-ROLE-ENHANCED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-ROLE-ENHANCED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to the role table with additional columns
|
||||
for easier human readability.
|
||||
*/
|
||||
drop view if exists rbacrole_ev;
|
||||
create or replace view rbacrole_ev as
|
||||
drop view if exists rbac.role_ev;
|
||||
create or replace view rbac.role_ev as
|
||||
select (objectTable || '#' || objectIdName || ':' || roleType) as roleIdName, *
|
||||
-- @formatter:off
|
||||
from (
|
||||
select r.*,
|
||||
o.objectTable, findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbacrole as r
|
||||
join rbacobject as o on o.uuid = r.objectuuid
|
||||
o.objectTable, base.findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbac.role as r
|
||||
join rbac.object as o on o.uuid = r.objectuuid
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by roleIdName;
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-ROLE-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-ROLE-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to the role table with row-level limitation
|
||||
based on the grants of the current user or assumed roles.
|
||||
*/
|
||||
drop view if exists rbacrole_rv;
|
||||
create or replace view rbacrole_rv as
|
||||
drop view if exists rbac.role_rv;
|
||||
create or replace view rbac.role_rv as
|
||||
select *
|
||||
-- @formatter:off
|
||||
from (
|
||||
select r.*, o.objectTable,
|
||||
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbacrole as r
|
||||
join rbacobject as o on o.uuid = r.objectuuid
|
||||
where isGranted(currentSubjectsUuids(), r.uuid)
|
||||
base.findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbac.role as r
|
||||
join rbac.object as o on o.uuid = r.objectuuid
|
||||
where rbac.isGranted(rbac.currentSubjectOrAssumedRolesUuids(), r.uuid)
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by objectTable || '#' || objectIdName || ':' || roleType;
|
||||
grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
grant all privileges on rbac.role_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-GRANT-ENHANCED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-GRANT-ENHANCED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to the grants table with additional columns
|
||||
for easier human readability.
|
||||
*/
|
||||
drop view if exists rbacgrants_ev;
|
||||
create or replace view rbacgrants_ev as
|
||||
drop view if exists rbac.grants_ev;
|
||||
create or replace view rbac.grants_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 || '#' || base.findIdNameByObjectUuid(go.objectTable, go.uuid) || ':' || r.roletype as grantedByRoleIdName,
|
||||
x.ascendingIdName as ascendantIdName,
|
||||
x.descendingIdName as descendantIdName,
|
||||
x.grantedByRoleUuid,
|
||||
@@ -72,33 +72,33 @@ create or replace view rbacgrants_ev as
|
||||
|
||||
coalesce(
|
||||
'user:' || au.name,
|
||||
'role:' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || ':' || ar.roletype
|
||||
'role:' || aro.objectTable || '#' || base.findIdNameByObjectUuid(aro.objectTable, aro.uuid) || ':' || ar.roletype
|
||||
) as ascendingIdName,
|
||||
aro.objectTable, aro.uuid,
|
||||
( case
|
||||
when dro is not null
|
||||
then ('role:' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || ':' || dr.roletype)
|
||||
then ('role:' || dro.objectTable || '#' || base.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
|
||||
then 'perm:' || dpo.objecttable || '#' || base.findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) || ':' || dp.op || '>' || dp.opTableName
|
||||
else 'perm:' || dpo.objecttable || '#' || base.findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) || ':' || dp.op
|
||||
end
|
||||
) as descendingIdName,
|
||||
dro.objectTable, dro.uuid,
|
||||
dp.op, dp.optablename
|
||||
from rbacgrants as g
|
||||
from rbac.grants as g
|
||||
|
||||
left outer join rbacrole as ar on ar.uuid = g.ascendantUuid
|
||||
left outer join rbacobject as aro on aro.uuid = ar.objectuuid
|
||||
left outer join rbacuser as au on au.uuid = g.ascendantUuid
|
||||
left outer join rbac.role as ar on ar.uuid = g.ascendantUuid
|
||||
left outer join rbac.object as aro on aro.uuid = ar.objectuuid
|
||||
left outer join rbac.subject as au on au.uuid = g.ascendantUuid
|
||||
|
||||
left outer join rbacrole as dr on dr.uuid = g.descendantUuid
|
||||
left outer join rbacobject as dro on dro.uuid = dr.objectuuid
|
||||
left outer join rbacpermission dp on dp.uuid = g.descendantUuid
|
||||
left outer join rbacobject as dpo on dpo.uuid = dp.objectUuid
|
||||
left outer join rbac.role as dr on dr.uuid = g.descendantUuid
|
||||
left outer join rbac.object as dro on dro.uuid = dr.objectuuid
|
||||
left outer join rbac.permission dp on dp.uuid = g.descendantUuid
|
||||
left outer join rbac.object as dpo on dpo.uuid = dp.objectUuid
|
||||
) as x
|
||||
left outer join rbacrole as r on r.uuid = grantedByRoleUuid
|
||||
left outer join rbacuser u on u.uuid = x.ascendantuuid
|
||||
left outer join rbacobject go on go.uuid = r.objectuuid
|
||||
left outer join rbac.role as r on r.uuid = grantedByRoleUuid
|
||||
left outer join rbac.subject u on u.uuid = x.ascendantuuid
|
||||
left outer join rbac.object go on go.uuid = r.objectuuid
|
||||
|
||||
order by x.ascendingIdName, x.descendingIdName;
|
||||
-- @formatter:on
|
||||
@@ -106,116 +106,115 @@ create or replace view rbacgrants_ev as
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-GRANT-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-GRANT-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to the grants table with row-level limitation
|
||||
based on the direct grants of the current user.
|
||||
*/
|
||||
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,
|
||||
create or replace view rbac.grants_rv as
|
||||
-- @formatter:off
|
||||
select o.objectTable || '#' || base.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.grantedByRoleUuid, g.descendantUuid as grantedRoleUuid, g.ascendantUuid as subjectUuid,
|
||||
g.objectTable, g.objectUuid, g.objectIdName, g.roleType as grantedRoleType
|
||||
from (
|
||||
select g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||
u.name as userName, o.objecttable, r.objectuuid, r.roletype,
|
||||
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbacgrants as g
|
||||
join rbacrole as r on r.uuid = g.descendantUuid
|
||||
join rbacobject o on o.uuid = r.objectuuid
|
||||
left outer join rbacuser u on u.uuid = g.ascendantuuid
|
||||
where isGranted(currentSubjectsUuids(), r.uuid)
|
||||
base.findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
|
||||
from rbac.grants as g
|
||||
join rbac.role as r on r.uuid = g.descendantUuid
|
||||
join rbac.object o on o.uuid = r.objectuuid
|
||||
left outer join rbac.subject u on u.uuid = g.ascendantuuid
|
||||
where rbac.isGranted(rbac.currentSubjectOrAssumedRolesUuids(), r.uuid)
|
||||
) as g
|
||||
join RbacRole as r on r.uuid = grantedByRoleUuid
|
||||
join RbacObject as o on o.uuid = r.objectUuid
|
||||
join rbac.role as r on r.uuid = grantedByRoleUuid
|
||||
join rbac.object as o on o.uuid = r.objectUuid
|
||||
order by grantedRoleIdName;
|
||||
-- @formatter:on
|
||||
grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
grant all privileges on rbac.role_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-GRANTS-RV-INSERT-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-GRANTS-RV-INSERT-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Instead of insert trigger function for RbacGrants_RV.
|
||||
Instead of insert trigger function for rbac.grants_rv.
|
||||
*/
|
||||
create or replace function insertRbacGrant()
|
||||
create or replace function rbac.insert_grant_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
declare
|
||||
newGrant RbacGrants_RV;
|
||||
newGrant rbac.grants_rv;
|
||||
begin
|
||||
call grantRoleToUser(assumedRoleUuid(), new.grantedRoleUuid, new.userUuid, new.assumed);
|
||||
call rbac.grantRoleToSubject(rbac.assumedRoleUuid(), new.grantedRoleUuid, new.subjectUuid, new.assumed);
|
||||
select grv.*
|
||||
from RbacGrants_RV grv
|
||||
where grv.userUuid=new.userUuid and grv.grantedRoleUuid=new.grantedRoleUuid
|
||||
from rbac.grants_rv grv
|
||||
where grv.subjectUuid=new.subjectUuid and grv.grantedRoleUuid=new.grantedRoleUuid
|
||||
into newGrant;
|
||||
return newGrant;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Creates an instead of insert trigger for the RbacGrants_rv view.
|
||||
Creates an instead of insert trigger for the rbac.grants_rv view.
|
||||
*/
|
||||
create trigger insertRbacGrant_Trigger
|
||||
create trigger insert_grant_tg
|
||||
instead of insert
|
||||
on RbacGrants_rv
|
||||
on rbac.grants_rv
|
||||
for each row
|
||||
execute function insertRbacGrant();
|
||||
execute function rbac.insert_grant_tf();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-GRANTS-RV-DELETE-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-GRANTS-RV-DELETE-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Instead of delete trigger function for RbacGrants_RV.
|
||||
Instead of delete trigger function for rbac.grants_rv.
|
||||
|
||||
Checks if the current subject (user / assumed role) has the permission to revoke the grant.
|
||||
Checks if the current subject or assumed role have the permission to revoke the grant.
|
||||
*/
|
||||
create or replace function deleteRbacGrant()
|
||||
create or replace function rbac.delete_grant_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
call revokeRoleFromUser(old.grantedByRoleUuid, old.grantedRoleUuid, old.userUuid);
|
||||
call rbac.revokeRoleFromSubject(old.grantedByRoleUuid, old.grantedRoleUuid, old.subjectUuid);
|
||||
return old;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Creates an instead of delete trigger for the RbacGrants_rv view.
|
||||
Creates an instead of delete trigger for the rbac.grants_rv view.
|
||||
*/
|
||||
create trigger deleteRbacGrant_Trigger
|
||||
create trigger delete_grant_tg
|
||||
instead of delete
|
||||
on RbacGrants_rv
|
||||
on rbac.grants_rv
|
||||
for each row
|
||||
execute function deleteRbacGrant();
|
||||
execute function rbac.delete_grant_tf();
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-USER-ENHANCED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-USER-ENHANCED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to the users table with additional columns
|
||||
for easier human readability.
|
||||
*/
|
||||
drop view if exists RbacUser_ev;
|
||||
create or replace view RbacUser_ev as
|
||||
drop view if exists rbac.subject_ev;
|
||||
create or replace view rbac.subject_ev as
|
||||
select distinct *
|
||||
-- @formatter:off
|
||||
from (
|
||||
select usersInRolesOfCurrentUser.*
|
||||
from RbacUser as usersInRolesOfCurrentUser
|
||||
join RbacGrants as g on g.ascendantuuid = usersInRolesOfCurrentUser.uuid
|
||||
join rbacrole_ev as r on r.uuid = g.descendantuuid
|
||||
select usersInRolesOfcurrentSubject.*
|
||||
from rbac.subject as usersInRolesOfcurrentSubject
|
||||
join rbac.grants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid
|
||||
join rbac.role_ev as r on r.uuid = g.descendantuuid
|
||||
union
|
||||
select users.*
|
||||
from RbacUser as users
|
||||
from rbac.subject as users
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by unordered.name;
|
||||
@@ -223,53 +222,53 @@ select distinct *
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-USER-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-USER-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to the users table with row-level limitation
|
||||
based on the grants of the current user or assumed roles.
|
||||
*/
|
||||
drop view if exists RbacUser_rv;
|
||||
create or replace view RbacUser_rv as
|
||||
drop view if exists rbac.subject_rv;
|
||||
create or replace view rbac.subject_rv as
|
||||
select distinct *
|
||||
-- @formatter:off
|
||||
from (
|
||||
select usersInRolesOfCurrentUser.*
|
||||
from RbacUser as usersInRolesOfCurrentUser
|
||||
join RbacGrants as g on g.ascendantuuid = usersInRolesOfCurrentUser.uuid
|
||||
join rbacrole_rv as r on r.uuid = g.descendantuuid
|
||||
select usersInRolesOfcurrentSubject.*
|
||||
from rbac.subject as usersInRolesOfcurrentSubject
|
||||
join rbac.grants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid
|
||||
join rbac.role_rv as r on r.uuid = g.descendantuuid
|
||||
union
|
||||
select users.*
|
||||
from RbacUser as users
|
||||
where cardinality(assumedRoles()) = 0 and
|
||||
(currentUserUuid() = users.uuid or hasGlobalRoleGranted(currentUserUuid()))
|
||||
from rbac.subject as users
|
||||
where cardinality(base.assumedRoles()) = 0 and
|
||||
(rbac.currentSubjectUuid() = users.uuid or rbac.hasGlobalRoleGranted(rbac.currentSubjectUuid()))
|
||||
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by unordered.name;
|
||||
grant all privileges on RbacUser_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
grant all privileges on rbac.subject_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-USER-RV-INSERT-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-USER-RV-INSERT-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Instead of insert trigger function for RbacUser_rv.
|
||||
Instead of insert trigger function for rbac.subject_rv.
|
||||
*/
|
||||
create or replace function insertRbacUser()
|
||||
create or replace function rbac.insert_subject_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
declare
|
||||
refUuid uuid;
|
||||
newUser RbacUser;
|
||||
newUser rbac.subject;
|
||||
begin
|
||||
insert
|
||||
into RbacReference as r (uuid, type)
|
||||
values( new.uuid, 'RbacUser')
|
||||
into rbac.reference as r (uuid, type)
|
||||
values( new.uuid, 'rbac.subject')
|
||||
returning r.uuid into refUuid;
|
||||
insert
|
||||
into RbacUser (uuid, name)
|
||||
into rbac.subject (uuid, name)
|
||||
values (refUuid, new.name)
|
||||
returning * into newUser;
|
||||
return newUser;
|
||||
@@ -277,84 +276,84 @@ end;
|
||||
$$;
|
||||
|
||||
/*
|
||||
Creates an instead of insert trigger for the RbacUser_rv view.
|
||||
Creates an instead of insert trigger for the rbac.subject_rv view.
|
||||
*/
|
||||
create trigger insertRbacUser_Trigger
|
||||
create trigger insert_subject_tg
|
||||
instead of insert
|
||||
on RbacUser_rv
|
||||
on rbac.subject_rv
|
||||
for each row
|
||||
execute function insertRbacUser();
|
||||
execute function rbac.insert_subject_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-USER-RV-DELETE-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-USER-RV-DELETE-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Instead of delete trigger function for RbacUser_RV.
|
||||
Instead of delete trigger function for rbac.subject_rv.
|
||||
|
||||
Checks if the current subject (user / assumed role) has the permission to delete the user.
|
||||
*/
|
||||
create or replace function deleteRbacUser()
|
||||
create or replace function rbac.delete_subject_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if currentUserUuid() = old.uuid or hasGlobalRoleGranted(currentUserUuid()) then
|
||||
delete from RbacUser where uuid = old.uuid;
|
||||
if rbac.currentSubjectUuid() = old.uuid or rbac.hasGlobalRoleGranted(rbac.currentSubjectUuid()) then
|
||||
delete from rbac.subject where uuid = old.uuid;
|
||||
return old;
|
||||
end if;
|
||||
raise exception '[403] User % not allowed to delete user uuid %', currentUser(), old.uuid;
|
||||
raise exception '[403] User % not allowed to delete user uuid %', base.currentSubject(), old.uuid;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Creates an instead of delete trigger for the RbacUser_rv view.
|
||||
Creates an instead of delete trigger for the rbac.subject_rv view.
|
||||
*/
|
||||
create trigger deleteRbacUser_Trigger
|
||||
create trigger delete_subject_tg
|
||||
instead of delete
|
||||
on RbacUser_rv
|
||||
on rbac.subject_rv
|
||||
for each row
|
||||
execute function deleteRbacUser();
|
||||
execute function rbac.delete_subject_tf();
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-OWN-GRANTED-PERMISSIONS-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-OWN-GRANTED-PERMISSIONS-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a view to all permissions granted to the current user or
|
||||
based on the grants of the current user or assumed roles.
|
||||
*/
|
||||
-- @formatter:off
|
||||
drop view if exists RbacOwnGrantedPermissions_rv;
|
||||
create or replace view RbacOwnGrantedPermissions_rv as
|
||||
drop view if exists rbac.own_granted_permissions_rv;
|
||||
create or replace view rbac.own_granted_permissions_rv as
|
||||
select r.uuid as roleuuid, p.uuid as permissionUuid,
|
||||
(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
|
||||
join rbacpermission p on p.uuid = g.descendantuuid
|
||||
join rbacobject o on o.uuid = p.objectuuid;
|
||||
grant all privileges on RbacOwnGrantedPermissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
from rbac.role_rv r
|
||||
join rbac.grants g on g.ascendantuuid = r.uuid
|
||||
join rbac.permission p on p.uuid = g.descendantuuid
|
||||
join rbac.object o on o.uuid = p.objectuuid;
|
||||
grant all privileges on rbac.own_granted_permissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
-- @formatter:om
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-views-GRANTED-PERMISSIONS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-views-GRANTED-PERMISSIONS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns all permissions granted to the given user,
|
||||
which are also visible to the current user or assumed roles.
|
||||
*/
|
||||
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)
|
||||
create or replace function rbac.grantedPermissionsRaw(targetSubjectUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op rbac.RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentUserUuid uuid;
|
||||
currentSubjectUuid uuid;
|
||||
begin
|
||||
-- @formatter:off
|
||||
currentUserUuid := currentUserUuid();
|
||||
currentSubjectUuid := rbac.currentSubjectUuid();
|
||||
|
||||
if hasGlobalRoleGranted(targetUserUuid) and not hasGlobalRoleGranted(currentUserUuid) then
|
||||
raise exception '[403] permissions of user "%" are not accessible to user "%"', targetUserUuid, currentUser();
|
||||
if rbac.hasGlobalRoleGranted(targetSubjectUuid) and not rbac.hasGlobalRoleGranted(currentSubjectUuid) then
|
||||
raise exception '[403] permissions of user "%" are not accessible to user "%"', targetSubjectUuid, base.currentSubject();
|
||||
end if;
|
||||
|
||||
return query select
|
||||
@@ -364,29 +363,29 @@ begin
|
||||
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,
|
||||
base.findIdNameByObjectUuid(ro.objectTable, ro.uuid) as roleObjectIdName,
|
||||
p.uuid as permissionUuid, p.op, p.opTableName,
|
||||
po.objecttable as permissionObjectTable,
|
||||
findIdNameByObjectUuid(po.objectTable, po.uuid) as permissionObjectIdName,
|
||||
base.findIdNameByObjectUuid(po.objectTable, po.uuid) as permissionObjectIdName,
|
||||
po.uuid as permissionObjectUuid
|
||||
from queryPermissionsGrantedToSubjectId( targetUserUuid) as p
|
||||
join rbacgrants as g on g.descendantUuid = p.uuid
|
||||
join rbacobject as po on po.uuid = p.objectUuid
|
||||
join rbacrole_rv as r on r.uuid = g.ascendantUuid
|
||||
join rbacobject as ro on ro.uuid = r.objectUuid
|
||||
where isGranted(targetUserUuid, r.uuid)
|
||||
from rbac.queryPermissionsGrantedToSubjectId( targetSubjectUuid) as p
|
||||
join rbac.grants as g on g.descendantUuid = p.uuid
|
||||
join rbac.object as po on po.uuid = p.objectUuid
|
||||
join rbac.role_rv as r on r.uuid = g.ascendantUuid
|
||||
join rbac.object as ro on ro.uuid = r.objectUuid
|
||||
where rbac.isGranted(targetSubjectUuid, r.uuid)
|
||||
) 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)
|
||||
create or replace function rbac.grantedPermissions(targetSubjectUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op rbac.RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select * from grantedPermissionsRaw(targetUserUuid)
|
||||
select * from rbac.grantedPermissionsRaw(targetSubjectUuid)
|
||||
union all
|
||||
select roleUuid, roleName, permissionUuid, 'SELECT'::RbacOp, opTableName, objectTable, objectIdName, objectUuid
|
||||
from grantedPermissionsRaw(targetUserUuid)
|
||||
where op <> 'SELECT'::RbacOp;
|
||||
select roleUuid, roleName, permissionUuid, 'SELECT'::rbac.RbacOp, opTableName, objectTable, objectIdName, objectUuid
|
||||
from rbac.grantedPermissionsRaw(targetSubjectUuid)
|
||||
where op <> 'SELECT'::rbac.RbacOp;
|
||||
$$;
|
||||
--//
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-trigger-context-ENTER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-trigger-context-ENTER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure enterTriggerForObjectUuid(currentObjectUuid uuid)
|
||||
create or replace procedure rbac.enterTriggerForObjectUuid(currentObjectUuid uuid)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
existingObjectUuid text;
|
||||
@@ -19,13 +19,13 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-trigger-context-CURRENT-ID:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-trigger-context-CURRENT-ID endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Returns the uuid of the object uuid whose trigger is currently executed as set via `enterTriggerForObjectUuid(...)`.
|
||||
Returns the uuid of the object uuid whose trigger is currently executed as set via `rbac.enterTriggerForObjectUuid(...)`.
|
||||
*/
|
||||
|
||||
create or replace function currentTriggerObjectUuid()
|
||||
create or replace function rbac.currentTriggerObjectUuid()
|
||||
returns uuid
|
||||
stable -- leakproof
|
||||
language plpgsql as $$
|
||||
@@ -44,10 +44,10 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-trigger-context-LEAVE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-trigger-context-LEAVE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure leaveTriggerForObjectUuid(currentObjectUuid uuid)
|
||||
create or replace procedure rbac.leaveTriggerForObjectUuid(currentObjectUuid uuid)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
existingObjectUuid uuid;
|
||||
|
||||
@@ -3,62 +3,61 @@
|
||||
|
||||
-- =================================================================
|
||||
-- CREATE ROLE
|
||||
--changeset rbac-role-builder-create-role:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-role-builder-define-role endDelimiter:--//
|
||||
-- -----------------------------------------------------------------
|
||||
|
||||
-- TODO: rename to defineRoleWithGrants because it does not complain if the role already exists
|
||||
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
|
||||
create or replace function rbac.defineRoleWithGrants(
|
||||
roleDescriptor rbac.RoleDescriptor,
|
||||
permissions rbac.RbacOp[] = array[]::rbac.RbacOp[],
|
||||
incomingSuperRoles rbac.RoleDescriptor[] = array[]::rbac.RoleDescriptor[],
|
||||
outgoingSubRoles rbac.RoleDescriptor[] = array[]::rbac.RoleDescriptor[],
|
||||
subjectUuids uuid[] = array[]::uuid[],
|
||||
grantedByRole rbac.RoleDescriptor = null
|
||||
)
|
||||
returns uuid
|
||||
called on null input
|
||||
language plpgsql as $$
|
||||
declare
|
||||
roleUuid uuid;
|
||||
permission RbacOp;
|
||||
permission rbac.RbacOp;
|
||||
permissionUuid uuid;
|
||||
subRoleDesc RbacRoleDescriptor;
|
||||
superRoleDesc RbacRoleDescriptor;
|
||||
subRoleDesc rbac.RoleDescriptor;
|
||||
superRoleDesc rbac.RoleDescriptor;
|
||||
subRoleUuid uuid;
|
||||
superRoleUuid uuid;
|
||||
userUuid uuid;
|
||||
subjectUuid uuid;
|
||||
userGrantsByRoleUuid uuid;
|
||||
begin
|
||||
roleUuid := coalesce(findRoleId(roleDescriptor), createRole(roleDescriptor));
|
||||
roleUuid := coalesce(rbac.findRoleId(roleDescriptor), rbac.createRole(roleDescriptor));
|
||||
|
||||
foreach permission in array permissions
|
||||
loop
|
||||
permissionUuid := createPermission(roleDescriptor.objectuuid, permission);
|
||||
call grantPermissionToRole(permissionUuid, roleUuid);
|
||||
permissionUuid := rbac.createPermission(roleDescriptor.objectuuid, permission);
|
||||
call rbac.grantPermissionToRole(permissionUuid, roleUuid);
|
||||
end loop;
|
||||
|
||||
foreach superRoleDesc in array array_remove(incomingSuperRoles, null)
|
||||
loop
|
||||
superRoleUuid := getRoleId(superRoleDesc);
|
||||
call grantRoleToRole(roleUuid, superRoleUuid, superRoleDesc.assumed);
|
||||
superRoleUuid := rbac.getRoleId(superRoleDesc);
|
||||
call rbac.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);
|
||||
subRoleUuid := rbac.getRoleId(subRoleDesc);
|
||||
call rbac.grantRoleToRole(subRoleUuid, roleUuid, subRoleDesc.assumed);
|
||||
end loop;
|
||||
|
||||
if cardinality(userUuids) > 0 then
|
||||
if cardinality(subjectUuids) > 0 then
|
||||
-- direct grants to users need a grantedByRole which can revoke the grant
|
||||
if grantedByRole is null then
|
||||
userGrantsByRoleUuid := roleUuid; -- TODO.impl: or do we want to require an explicit userGrantsByRoleUuid?
|
||||
else
|
||||
userGrantsByRoleUuid := getRoleId(grantedByRole);
|
||||
userGrantsByRoleUuid := rbac.getRoleId(grantedByRole);
|
||||
end if;
|
||||
foreach userUuid in array userUuids
|
||||
foreach subjectUuid in array subjectUuids
|
||||
loop
|
||||
call grantRoleToUserUnchecked(userGrantsByRoleUuid, roleUuid, userUuid);
|
||||
call rbac.grantRoleToSubjectUnchecked(userGrantsByRoleUuid, roleUuid, subjectUuid);
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-generators-RELATED-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-generators-RELATED-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure generateRelatedRbacObject(targetTable varchar)
|
||||
create or replace procedure rbac.generateRelatedRbacObject(targetTable varchar)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
createInsertTriggerSQL text;
|
||||
@@ -15,16 +15,16 @@ begin
|
||||
create trigger createRbacObjectFor_%s_Trigger
|
||||
before insert on %s
|
||||
for each row
|
||||
execute procedure insertRelatedRbacObject();
|
||||
execute procedure rbac.insert_related_object();
|
||||
$sql$, targetTable, targetTable);
|
||||
execute createInsertTriggerSQL;
|
||||
|
||||
createDeleteTriggerSQL = format($sql$
|
||||
create trigger deleteRbacRulesFor_%s_Trigger
|
||||
create trigger delete_related_rbac_rules_for_%s_tg
|
||||
after delete
|
||||
on %s
|
||||
for each row
|
||||
execute procedure deleteRelatedRbacObject();
|
||||
execute procedure rbac.delete_related_rbac_rules_tf();
|
||||
$sql$, targetTable, targetTable);
|
||||
execute createDeleteTriggerSQL;
|
||||
end; $$;
|
||||
@@ -32,62 +32,62 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-generators-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-generators-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create procedure generateRbacRoleDescriptors(prefix text, targetTable text)
|
||||
create procedure rbac.generateRbacRoleDescriptors(prefix text, targetTable text)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sql text;
|
||||
begin
|
||||
sql = format($sql$
|
||||
create or replace function %1$sOwner(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'OWNER', assumed);
|
||||
return rbac.roleDescriptorOf('%2$s', entity.uuid, 'OWNER', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sAdmin(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'ADMIN', assumed);
|
||||
return rbac.roleDescriptorOf('%2$s', entity.uuid, 'ADMIN', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sAgent(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'AGENT', assumed);
|
||||
return rbac.roleDescriptorOf('%2$s', entity.uuid, 'AGENT', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sTenant(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'TENANT', assumed);
|
||||
return rbac.roleDescriptorOf('%2$s', entity.uuid, 'TENANT', assumed);
|
||||
end; $f$;
|
||||
|
||||
-- TODO: remove guest role
|
||||
create or replace function %1$sGuest(entity %2$s, assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'GUEST', assumed);
|
||||
return rbac.roleDescriptorOf('%2$s', entity.uuid, 'GUEST', assumed);
|
||||
end; $f$;
|
||||
|
||||
create or replace function %1$sReferrer(entity %2$s)
|
||||
returns RbacRoleDescriptor
|
||||
returns rbac.RoleDescriptor
|
||||
language plpgsql
|
||||
strict as $f$
|
||||
begin
|
||||
return roleDescriptor('%2$s', entity.uuid, 'REFERRER');
|
||||
return rbac.roleDescriptorOf('%2$s', entity.uuid, 'REFERRER');
|
||||
end; $f$;
|
||||
|
||||
$sql$, prefix, targetTable);
|
||||
@@ -97,10 +97,10 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-generators-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-generators-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure generateRbacIdentityViewFromQuery(targetTable text, sqlQuery text)
|
||||
create or replace procedure rbac.generateRbacIdentityViewFromQuery(targetTable text, sqlQuery text)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sql text;
|
||||
@@ -140,7 +140,7 @@ begin
|
||||
execute sql;
|
||||
end; $$;
|
||||
|
||||
create or replace procedure generateRbacIdentityViewFromProjection(targetTable text, sqlProjection text)
|
||||
create or replace procedure rbac.generateRbacIdentityViewFromProjection(targetTable text, sqlProjection text)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sqlQuery text;
|
||||
@@ -148,19 +148,19 @@ begin
|
||||
targettable := lower(targettable);
|
||||
|
||||
sqlQuery = format($sql$
|
||||
select target.uuid, cleanIdentifier(%2$s) as idName
|
||||
select target.uuid, base.cleanIdentifier(%2$s) as idName
|
||||
from %1$s as target;
|
||||
$sql$, targetTable, sqlProjection);
|
||||
call generateRbacIdentityViewFromQuery(targetTable, sqlQuery);
|
||||
call rbac.generateRbacIdentityViewFromQuery(targetTable, sqlQuery);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-generators-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-generators-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null, columnNames text = '*')
|
||||
create or replace procedure rbac.generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null, columnNames text = '*')
|
||||
language plpgsql as $$
|
||||
declare
|
||||
sql text;
|
||||
@@ -168,7 +168,7 @@ declare
|
||||
begin
|
||||
targetTable := lower(targetTable);
|
||||
if columnNames = '*' then
|
||||
columnNames := columnsNames(targetTable);
|
||||
columnNames := base.tableColumnNames(targetTable);
|
||||
end if;
|
||||
|
||||
/*
|
||||
@@ -179,31 +179,31 @@ begin
|
||||
with accessible_%1$s_uuids as (
|
||||
with recursive
|
||||
recursive_grants as
|
||||
(select distinct rbacgrants.descendantuuid,
|
||||
rbacgrants.ascendantuuid,
|
||||
(select distinct rbac.grants.descendantuuid,
|
||||
rbac.grants.ascendantuuid,
|
||||
1 as level,
|
||||
true
|
||||
from rbacgrants
|
||||
where rbacgrants.assumed
|
||||
and (rbacgrants.ascendantuuid = any (currentsubjectsuuids()))
|
||||
from rbac.grants
|
||||
where rbac.grants.assumed
|
||||
and (rbac.grants.ascendantuuid = any (rbac.currentSubjectOrAssumedRolesUuids()))
|
||||
union all
|
||||
select distinct g.descendantuuid,
|
||||
g.ascendantuuid,
|
||||
grants.level + 1 as level,
|
||||
assertTrue(grants.level < 22, 'too many grant-levels: ' || grants.level)
|
||||
from rbacgrants g
|
||||
base.assertTrue(grants.level < 22, 'too many grant-levels: ' || grants.level)
|
||||
from rbac.grants g
|
||||
join recursive_grants grants on grants.descendantuuid = g.ascendantuuid
|
||||
where g.assumed),
|
||||
grant_count AS (
|
||||
SELECT COUNT(*) AS grant_count FROM recursive_grants
|
||||
),
|
||||
count_check as (select assertTrue((select count(*) as grant_count from recursive_grants) < 400000,
|
||||
count_check as (select base.assertTrue((select count(*) as grant_count from recursive_grants) < 400000,
|
||||
'too many grants for current subjects: ' || (select count(*) as grant_count from recursive_grants))
|
||||
as valid)
|
||||
select distinct perm.objectuuid
|
||||
from recursive_grants
|
||||
join rbacpermission perm on recursive_grants.descendantuuid = perm.uuid
|
||||
join rbacobject obj on obj.uuid = perm.objectuuid
|
||||
join rbac.permission perm on recursive_grants.descendantuuid = perm.uuid
|
||||
join rbac.object obj on obj.uuid = perm.objectuuid
|
||||
join count_check cc on cc.valid
|
||||
where obj.objectTable = '%1$s' -- 'SELECT' permission is included in all other permissions
|
||||
)
|
||||
@@ -256,11 +256,11 @@ begin
|
||||
returns trigger
|
||||
language plpgsql as $f$
|
||||
begin
|
||||
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('DELETE', '%1$s', currentSubjectsUuids())) then
|
||||
if old.uuid in (select rbac.queryAccessibleObjectUuidsOfSubjectIds('DELETE', '%1$s', rbac.currentSubjectOrAssumedRolesUuids())) then
|
||||
delete from %1$s p where p.uuid = old.uuid;
|
||||
return old;
|
||||
end if;
|
||||
raise exception '[403] Subject %% is not allowed to delete %1$s uuid %%', currentSubjectsUuids(), old.uuid;
|
||||
raise exception '[403] Subject %% is not allowed to delete %1$s uuid %%', rbac.currentSubjectOrAssumedRolesUuids(), old.uuid;
|
||||
end; $f$;
|
||||
$sql$, targetTable);
|
||||
execute sql;
|
||||
@@ -287,13 +287,13 @@ begin
|
||||
returns trigger
|
||||
language plpgsql as $f$
|
||||
begin
|
||||
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('UPDATE', '%1$s', currentSubjectsUuids())) then
|
||||
if old.uuid in (select rbac.queryAccessibleObjectUuidsOfSubjectIds('UPDATE', '%1$s', rbac.currentSubjectOrAssumedRolesUuids())) then
|
||||
update %1$s
|
||||
set %2$s
|
||||
where uuid = old.uuid;
|
||||
return old;
|
||||
end if;
|
||||
raise exception '[403] Subject %% is not allowed to update %1$s uuid %%', currentSubjectsUuids(), old.uuid;
|
||||
raise exception '[403] Subject %% is not allowed to update %1$s uuid %%', rbac.currentSubjectOrAssumedRolesUuids(), old.uuid;
|
||||
end; $f$;
|
||||
$sql$, targetTable, columnUpdates);
|
||||
execute sql;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset rbac-statistics:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-statistics endDelimiter:--//
|
||||
|
||||
/*
|
||||
Creates a view which presents some statistics about the RBAC tables.
|
||||
*/
|
||||
create view RbacStatisticsView as
|
||||
create view rbac.statistics_v as
|
||||
select no, to_char("count", '9 999 999 999') as "count", "table"
|
||||
from (select 1 as no, count(*) as "count", 'login users' as "table"
|
||||
from RbacUser
|
||||
from rbac.subject
|
||||
union
|
||||
select 2 as no, count(*) as "count", 'roles' as "table"
|
||||
from RbacRole
|
||||
from rbac.role
|
||||
union
|
||||
select 3 as no, count(*) as "count", 'permissions' as "table"
|
||||
from RbacPermission
|
||||
from rbac.permission
|
||||
union
|
||||
select 4 as no, count(*) as "count", 'references' as "table"
|
||||
from RbacReference
|
||||
from rbac.reference
|
||||
union
|
||||
select 5 as no, count(*) as "count", 'grants' as "table"
|
||||
from RbacGrants
|
||||
from rbac.grants
|
||||
union
|
||||
select 6 as no, count(*) as "count", 'objects' as "table"
|
||||
from RbacObject) as totals
|
||||
from rbac.object) as totals
|
||||
order by totals.no;
|
||||
--//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-GLOBAL-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
The purpose of this table is provide root business objects
|
||||
@@ -11,184 +11,184 @@
|
||||
In production databases, there is only a single row in this table,
|
||||
in test stages, there can be one row for each test data realm.
|
||||
*/
|
||||
create table Global
|
||||
create table rbac.global
|
||||
(
|
||||
uuid uuid primary key references RbacObject (uuid) on delete cascade,
|
||||
uuid uuid primary key references rbac.object (uuid) on delete cascade,
|
||||
name varchar(63) unique
|
||||
);
|
||||
create unique index Global_Singleton on Global ((0));
|
||||
create unique index Global_Singleton on rbac.global ((0));
|
||||
|
||||
grant select on global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
grant select on rbac.global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-IS-GLOBAL-ADMIN:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-IS-GLOBAL-ADMIN endDelimiter:--//
|
||||
-- ------------------------------------------------------------------
|
||||
|
||||
create or replace function isGlobalAdmin()
|
||||
create or replace function rbac.isGlobalAdmin()
|
||||
returns boolean
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return isGranted(currentSubjectsUuids(), findRoleId(globalAdmin()));
|
||||
return rbac.isGranted(rbac.currentSubjectOrAssumedRolesUuids(), rbac.findRoleId(rbac.globalAdmin()));
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-HAS-GLOBAL-PERMISSION:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-HAS-GLOBAL-PERMISSION endDelimiter:--//
|
||||
-- ------------------------------------------------------------------
|
||||
|
||||
create or replace function hasGlobalPermission(op RbacOp)
|
||||
create or replace function rbac.hasGlobalPermission(op rbac.RbacOp)
|
||||
returns boolean
|
||||
language sql as
|
||||
$$
|
||||
-- TODO.perf: this could to be optimized
|
||||
select (select uuid from global) in
|
||||
(select queryAccessibleObjectUuidsOfSubjectIds(op, 'global', currentSubjectsUuids()));
|
||||
select (select uuid from rbac.global) in
|
||||
(select rbac.queryAccessibleObjectUuidsOfSubjectIds(op, 'rbac.global', rbac.currentSubjectOrAssumedRolesUuids()));
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-GLOBAL-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a view to the global object table which maps the identifying name to the objectUuid.
|
||||
Creates a view to the rbac.global object table which maps the identifying name to the objectUuid.
|
||||
*/
|
||||
drop view if exists global_iv;
|
||||
create or replace view global_iv as
|
||||
drop view if exists rbac.global_iv;
|
||||
create or replace view rbac.global_iv as
|
||||
select target.uuid, target.name as idName
|
||||
from global as target;
|
||||
grant all privileges on global_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
from rbac.global as target;
|
||||
grant all privileges on rbac.global_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
|
||||
/*
|
||||
Returns the objectUuid for a given identifying name (in this case the idName).
|
||||
*/
|
||||
create or replace function globalUuidByIdName(idName varchar)
|
||||
create or replace function rbac.globalUuidByIdName(idName varchar)
|
||||
returns uuid
|
||||
language sql
|
||||
strict as $$
|
||||
select uuid from global_iv iv where iv.idName = globalUuidByIdName.idName;
|
||||
select uuid from rbac.global_iv iv where iv.idName = globalUuidByIdName.idName;
|
||||
$$;
|
||||
|
||||
/*
|
||||
Returns the identifying name for a given objectUuid (in this case the idName).
|
||||
*/
|
||||
create or replace function globalIdNameByUuid(uuid uuid)
|
||||
create or replace function rbac.globalIdNameByUuid(uuid uuid)
|
||||
returns varchar
|
||||
language sql
|
||||
strict as $$
|
||||
select idName from global_iv iv where iv.uuid = globalIdNameByUuid.uuid;
|
||||
select idName from rbac.global_iv iv where iv.uuid = globalIdNameByUuid.uuid;
|
||||
$$;
|
||||
--//
|
||||
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-PSEUDO-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-PSEUDO-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
A single row to be referenced as a global object.
|
||||
A single row to be referenced as a rbac.Global object.
|
||||
*/
|
||||
begin transaction;
|
||||
call defineContext('initializing table "global"', null, null, null);
|
||||
call base.defineContext('initializing table "rbac.global"', null, null, null);
|
||||
insert
|
||||
into RbacObject (objecttable) values ('global');
|
||||
into rbac.object (objecttable) values ('rbac.global');
|
||||
insert
|
||||
into Global (uuid, name) values ((select uuid from RbacObject where objectTable = 'global'), 'global');
|
||||
into rbac.global (uuid, name) values ((select uuid from rbac.object where objectTable = 'rbac.global'), 'global');
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-ADMIN-ROLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-ADMIN-ROLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A global administrator role.
|
||||
A rbac.Global administrator role.
|
||||
*/
|
||||
create or replace function globalAdmin(assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
create or replace function rbac.globalAdmin(assumed boolean = true)
|
||||
returns rbac.RoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'ADMIN'::RbacRoleType, assumed;
|
||||
select 'rbac.global', (select uuid from rbac.object where objectTable = 'rbac.global'), 'ADMIN'::rbac.RoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating role:global#global:ADMIN', null, null, null);
|
||||
select createRole(globalAdmin());
|
||||
call base.defineContext('creating role:rbac.global#global:ADMIN', null, null, null);
|
||||
select rbac.createRole(rbac.globalAdmin());
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-GUEST-ROLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-GUEST-ROLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
A global guest role.
|
||||
A rbac.Global guest role.
|
||||
*/
|
||||
create or replace function globalGuest(assumed boolean = true)
|
||||
returns RbacRoleDescriptor
|
||||
create or replace function rbac.globalglobalGuest(assumed boolean = true)
|
||||
returns rbac.RoleDescriptor
|
||||
returns null on null input
|
||||
stable -- leakproof
|
||||
language sql as $$
|
||||
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'GUEST'::RbacRoleType, assumed;
|
||||
select 'rbac.global', (select uuid from rbac.object where objectTable = 'rbac.global'), 'GUEST'::rbac.RoleType, assumed;
|
||||
$$;
|
||||
|
||||
begin transaction;
|
||||
call defineContext('creating role:global#global:guest', null, null, null);
|
||||
select createRole(globalGuest());
|
||||
call base.defineContext('creating role:rbac.global#global:guest', null, null, null);
|
||||
select rbac.createRole(rbac.globalglobalGuest());
|
||||
commit;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-ADMIN-USERS:1 context:dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-ADMIN-USERS context:dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Create two users and assign both to the administrators role.
|
||||
Create two users and assign both to the administrators' role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
admins uuid ;
|
||||
begin
|
||||
call defineContext('creating fake test-realm admin users', null, null, null);
|
||||
call base.defineContext('creating fake test-realm admin users', null, null, null);
|
||||
|
||||
admins = findRoleId(globalAdmin());
|
||||
call grantRoleToUserUnchecked(admins, admins, createRbacUser('superuser-alex@hostsharing.net'));
|
||||
call grantRoleToUserUnchecked(admins, admins, createRbacUser('superuser-fran@hostsharing.net'));
|
||||
perform createRbacUser('selfregistered-user-drew@hostsharing.org');
|
||||
perform createRbacUser('selfregistered-test-user@hostsharing.org');
|
||||
admins = rbac.findRoleId(rbac.globalAdmin());
|
||||
call rbac.grantRoleToSubjectUnchecked(admins, admins, rbac.create_subject('superuser-alex@hostsharing.net'));
|
||||
call rbac.grantRoleToSubjectUnchecked(admins, admins, rbac.create_subject('superuser-fran@hostsharing.net'));
|
||||
perform rbac.create_subject('selfregistered-user-drew@hostsharing.org');
|
||||
perform rbac.create_subject('selfregistered-test-user@hostsharing.org');
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset rbac-global-TEST:1 context:dev,tc runAlways:true endDelimiter:--//
|
||||
--changeset michael.hoennig:rbac-global-TEST context:dev,tc runAlways:true endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Tests if currentUserUuid() can fetch the user from the session variable.
|
||||
Tests if rbac.currentSubjectUuid() can fetch the user from the session variable.
|
||||
*/
|
||||
|
||||
do language plpgsql $$
|
||||
declare
|
||||
userName varchar;
|
||||
begin
|
||||
call defineContext('testing currentUserUuid', null, 'superuser-fran@hostsharing.net', null);
|
||||
select userName from RbacUser where uuid = currentUserUuid() into userName;
|
||||
call base.defineContext('testing currentSubjectUuid', null, 'superuser-fran@hostsharing.net', null);
|
||||
select userName from rbac.subject where uuid = rbac.currentSubjectUuid() into userName;
|
||||
if userName <> 'superuser-fran@hostsharing.net' then
|
||||
raise exception 'setting or fetching initial currentUser failed, got: %', userName;
|
||||
raise exception 'setting or fetching initial currentSubject failed, got: %', userName;
|
||||
end if;
|
||||
|
||||
call defineContext('testing currentUserUuid', null, 'superuser-alex@hostsharing.net', null);
|
||||
select userName from RbacUser where uuid = currentUserUuid() into userName;
|
||||
call base.defineContext('testing currentSubjectUuid', null, 'superuser-alex@hostsharing.net', null);
|
||||
select userName from rbac.subject where uuid = rbac.currentSubjectUuid() into userName;
|
||||
if userName = 'superuser-alex@hostsharing.net' then
|
||||
raise exception 'currentUser should not change in one transaction, but did change, got: %', userName;
|
||||
raise exception 'currentSubject should not change in one transaction, but did change, got: %', userName;
|
||||
end if;
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:test-customer-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists test_customer
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
uuid uuid unique references rbac.object (uuid),
|
||||
version int not null default 0,
|
||||
reference int not null unique check (reference between 10000 and 99999),
|
||||
prefix character(3) unique,
|
||||
|
||||
@@ -32,12 +32,12 @@ end
|
||||
user:creator ==>|XX| role:customer:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN ==>|XX| role:customer:OWNER
|
||||
role:rbac.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:rbac.global:ADMIN ==> perm:customer:INSERT
|
||||
role:customer:OWNER ==> perm:customer:DELETE
|
||||
role:customer:ADMIN ==> perm:customer:UPDATE
|
||||
role:customer:TENANT ==> perm:customer:SELECT
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset RbacObjectGenerator:test-customer-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_customer');
|
||||
call rbac.generateRelatedRbacObject('test_customer');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset RbacRoleDescriptorsGenerator:test-customer-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testCustomer', 'test_customer');
|
||||
call rbac.generateRbacRoleDescriptors('testCustomer', 'test_customer');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:test-customer-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -32,28 +32,28 @@ create or replace procedure buildRbacSystemForTestCustomer(
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testCustomerOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN(unassumed())],
|
||||
userUuids => array[currentUserUuid()]
|
||||
incomingSuperRoles => array[rbac.globalADMIN(rbac.unassumed())],
|
||||
subjectUuids => array[rbac.currentSubjectUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testCustomerADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[testCustomerOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testCustomerTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testCustomerADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -77,26 +77,26 @@ execute procedure insertTriggerForTestCustomer_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:test-customer-rbac-GRANTING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
-- granting INSERT permission to global ----------------------------
|
||||
-- granting INSERT permission to rbac.global ----------------------------
|
||||
|
||||
/*
|
||||
Grants INSERT INTO test_customer permissions to specified role of pre-existing global rows.
|
||||
Grants INSERT INTO test_customer permissions to specified role of pre-existing rbac.global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
row rbac.global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_customer permissions for pre-exising global rows');
|
||||
call base.defineContext('create INSERT INTO test_customer permissions for pre-exising rbac.global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
FOR row IN SELECT * FROM rbac.global
|
||||
-- unconditional for all rows in that table
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_customer'),
|
||||
globalADMIN());
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(row.uuid, 'INSERT', 'test_customer'),
|
||||
rbac.globalADMIN());
|
||||
END LOOP;
|
||||
end;
|
||||
$$;
|
||||
@@ -104,28 +104,28 @@ $$;
|
||||
/**
|
||||
Grants test_customer INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function new_test_customer_grants_insert_to_global_tf()
|
||||
create or replace function rbac.new_test_customer_grants_insert_to_global_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
-- unconditional for all rows in that table
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_customer'),
|
||||
globalADMIN());
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(NEW.uuid, 'INSERT', 'test_customer'),
|
||||
rbac.globalADMIN());
|
||||
-- end.
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_new_test_customer_grants_insert_to_global_tg
|
||||
after insert on global
|
||||
create trigger z_new_test_customer_grants_after_insert_tg
|
||||
after insert on rbac.global
|
||||
for each row
|
||||
execute procedure new_test_customer_grants_insert_to_global_tf();
|
||||
execute procedure rbac.new_test_customer_grants_insert_to_global_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test_customer-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:test_customer-rbac-CHECKING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -137,13 +137,13 @@ create or replace function test_customer_insert_permission_check_tf()
|
||||
declare
|
||||
superObjectUuid uuid;
|
||||
begin
|
||||
-- check INSERT INSERT if global ADMIN
|
||||
if isGlobalAdmin() then
|
||||
-- check INSERT INSERT if rbac.global ADMIN
|
||||
if rbac.isGlobalAdmin() then
|
||||
return NEW;
|
||||
end if;
|
||||
|
||||
raise exception '[403] insert into test_customer values(%) not allowed for current subjects % (%)',
|
||||
NEW, currentSubjects(), currentSubjectsUuids();
|
||||
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_customer_insert_permission_check_tg
|
||||
@@ -154,10 +154,10 @@ create trigger test_customer_insert_permission_check_tg
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacIdentityViewGenerator:test-customer-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('test_customer',
|
||||
call rbac.generateRbacIdentityViewFromProjection('test_customer',
|
||||
$idName$
|
||||
prefix
|
||||
$idName$);
|
||||
@@ -165,9 +165,9 @@ call generateRbacIdentityViewFromProjection('test_customer',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacRestrictedViewGenerator:test-customer-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_customer',
|
||||
call rbac.generateRbacRestrictedView('test_customer',
|
||||
$orderBy$
|
||||
reference
|
||||
$orderBy$,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:test-customer-TEST-DATA-GENERATOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Generates a customer reference number for a given test data counter.
|
||||
@@ -32,7 +32,7 @@ declare
|
||||
begin
|
||||
custRowId = uuid_generate_v4();
|
||||
custAdminName = 'customer-admin@' || custPrefix || '.example.com';
|
||||
custAdminUuid = createRbacUser(custAdminName);
|
||||
custAdminUuid = rbac.create_subject(custAdminName);
|
||||
|
||||
insert
|
||||
into test_customer (reference, prefix, adminUserName)
|
||||
@@ -40,9 +40,9 @@ begin
|
||||
|
||||
select * into newCust
|
||||
from test_customer where reference=custReference;
|
||||
call grantRoleToUser(
|
||||
getRoleId(testCustomerOwner(newCust)),
|
||||
getRoleId(testCustomerAdmin(newCust)),
|
||||
call rbac.grantRoleToSubject(
|
||||
rbac.getRoleId(testCustomerOwner(newCust)),
|
||||
rbac.getRoleId(testCustomerAdmin(newCust)),
|
||||
custAdminUuid,
|
||||
true);
|
||||
end; $$;
|
||||
@@ -59,7 +59,7 @@ create or replace procedure createTestCustomerTestData(
|
||||
begin
|
||||
for t in startCount..endCount
|
||||
loop
|
||||
call createTestCustomerTestData(testCustomerReference(t), intToVarChar(t, 3));
|
||||
call createTestCustomerTestData(testCustomerReference(t), base.intToVarChar(t, 3));
|
||||
commit;
|
||||
end loop;
|
||||
end; $$;
|
||||
@@ -67,12 +67,12 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:test-customer-TEST-DATA-GENERATION –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call defineContext('creating RBAC test customer', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||
call base.defineContext('creating RBAC test customer', null, 'superuser-alex@hostsharing.net', 'rbac.global#global:ADMIN');
|
||||
|
||||
call createTestCustomerTestData(99901, 'xxx');
|
||||
call createTestCustomerTestData(99902, 'yyy');
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:test-package-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists test_package
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
uuid uuid unique references rbac.object (uuid),
|
||||
version int not null default 0,
|
||||
customerUuid uuid references test_customer (uuid),
|
||||
name varchar(5),
|
||||
|
||||
@@ -42,7 +42,7 @@ subgraph package["`**package**`"]
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.->|XX| role:customer:OWNER
|
||||
role:rbac.global:ADMIN -.->|XX| role:customer:OWNER
|
||||
role:customer:OWNER -.-> role:customer:ADMIN
|
||||
role:customer:ADMIN -.-> role:customer:TENANT
|
||||
role:customer:ADMIN ==> role:package:OWNER
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset RbacObjectGenerator:test-package-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_package');
|
||||
call rbac.generateRelatedRbacObject('test_package');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset RbacRoleDescriptorsGenerator:test-package-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testPackage', 'test_package');
|
||||
call rbac.generateRbacRoleDescriptors('testPackage', 'test_package');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:test-package-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -33,31 +33,31 @@ declare
|
||||
newCustomer test_customer;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testPackageOWNER(NEW),
|
||||
permissions => array['DELETE', 'UPDATE'],
|
||||
incomingSuperRoles => array[testCustomerADMIN(newCustomer)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testPackageADMIN(NEW),
|
||||
incomingSuperRoles => array[testPackageOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testPackageTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testPackageADMIN(NEW)],
|
||||
outgoingSubRoles => array[testCustomerTENANT(newCustomer)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -81,7 +81,7 @@ execute procedure insertTriggerForTestPackage_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-update-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:test-package-rbac-update-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -99,7 +99,7 @@ declare
|
||||
newCustomer test_customer;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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);
|
||||
@@ -110,15 +110,15 @@ begin
|
||||
|
||||
if NEW.customerUuid <> OLD.customerUuid then
|
||||
|
||||
call revokeRoleFromRole(testPackageOWNER(OLD), testCustomerADMIN(oldCustomer));
|
||||
call grantRoleToRole(testPackageOWNER(NEW), testCustomerADMIN(newCustomer));
|
||||
call rbac.revokeRoleFromRole(testPackageOWNER(OLD), testCustomerADMIN(oldCustomer));
|
||||
call rbac.grantRoleToRole(testPackageOWNER(NEW), testCustomerADMIN(newCustomer));
|
||||
|
||||
call revokeRoleFromRole(testCustomerTENANT(oldCustomer), testPackageTENANT(OLD));
|
||||
call grantRoleToRole(testCustomerTENANT(newCustomer), testPackageTENANT(NEW));
|
||||
call rbac.revokeRoleFromRole(testCustomerTENANT(oldCustomer), testPackageTENANT(OLD));
|
||||
call rbac.grantRoleToRole(testCustomerTENANT(newCustomer), testPackageTENANT(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -142,7 +142,7 @@ execute procedure updateTriggerForTestPackage_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:test-package-rbac-GRANTING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
-- granting INSERT permission to test_customer ----------------------------
|
||||
@@ -154,13 +154,13 @@ do language plpgsql $$
|
||||
declare
|
||||
row test_customer;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_package permissions for pre-exising test_customer rows');
|
||||
call base.defineContext('create INSERT INTO test_package permissions for pre-exising test_customer rows');
|
||||
|
||||
FOR row IN SELECT * FROM test_customer
|
||||
-- unconditional for all rows in that table
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_package'),
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(row.uuid, 'INSERT', 'test_package'),
|
||||
testCustomerADMIN(row));
|
||||
END LOOP;
|
||||
end;
|
||||
@@ -175,22 +175,22 @@ create or replace function new_test_package_grants_insert_to_test_customer_tf()
|
||||
strict as $$
|
||||
begin
|
||||
-- unconditional for all rows in that table
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_package'),
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(NEW.uuid, 'INSERT', 'test_package'),
|
||||
testCustomerADMIN(NEW));
|
||||
-- end.
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_new_test_package_grants_insert_to_test_customer_tg
|
||||
create trigger z_new_test_package_grants_after_insert_tg
|
||||
after insert on test_customer
|
||||
for each row
|
||||
execute procedure new_test_package_grants_insert_to_test_customer_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test_package-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:test_package-rbac-CHECKING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -203,12 +203,12 @@ declare
|
||||
superObjectUuid uuid;
|
||||
begin
|
||||
-- check INSERT permission via direct foreign key: NEW.customerUuid
|
||||
if hasInsertPermission(NEW.customerUuid, 'test_package') then
|
||||
if rbac.hasInsertPermission(NEW.customerUuid, 'test_package') then
|
||||
return NEW;
|
||||
end if;
|
||||
|
||||
raise exception '[403] insert into test_package values(%) not allowed for current subjects % (%)',
|
||||
NEW, currentSubjects(), currentSubjectsUuids();
|
||||
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_package_insert_permission_check_tg
|
||||
@@ -219,10 +219,10 @@ create trigger test_package_insert_permission_check_tg
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacIdentityViewGenerator:test-package-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('test_package',
|
||||
call rbac.generateRbacIdentityViewFromProjection('test_package',
|
||||
$idName$
|
||||
name
|
||||
$idName$);
|
||||
@@ -230,9 +230,9 @@ call generateRbacIdentityViewFromProjection('test_package',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacRestrictedViewGenerator:test-package-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_package',
|
||||
call rbac.generateRbacRestrictedView('test_package',
|
||||
$orderBy$
|
||||
name
|
||||
$orderBy$,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:test-package-TEST-DATA-GENERATOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the given number of test packages for the given customer.
|
||||
@@ -22,17 +22,17 @@ begin
|
||||
pacName = cust.prefix || to_char(t, 'fm00');
|
||||
custAdminUser = 'customer-admin@' || cust.prefix || '.example.com';
|
||||
custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN';
|
||||
call defineContext('creating RBAC test package', null, 'superuser-fran@hostsharing.net', custAdminRole);
|
||||
call base.defineContext('creating RBAC test package', null, 'superuser-fran@hostsharing.net', custAdminRole);
|
||||
|
||||
insert
|
||||
into test_package (customerUuid, name, description)
|
||||
values (cust.uuid, pacName, 'Here you can add your own description of package ' || pacName || '.')
|
||||
returning * into pac;
|
||||
|
||||
call grantRoleToUser(
|
||||
getRoleId(testCustomerAdmin(cust)),
|
||||
findRoleId(testPackageAdmin(pac)),
|
||||
createRbacUser('pac-admin-' || pacName || '@' || cust.prefix || '.example.com'),
|
||||
call rbac.grantRoleToSubject(
|
||||
rbac.getRoleId(testCustomerAdmin(cust)),
|
||||
rbac.findRoleId(testPackageAdmin(pac)),
|
||||
rbac.create_subject('pac-admin-' || pacName || '@' || cust.prefix || '.example.com'),
|
||||
true);
|
||||
|
||||
end loop;
|
||||
@@ -59,7 +59,7 @@ $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-package-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:test-package-TEST-DATA-GENERATION –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:test-domain-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists test_domain
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
uuid uuid unique references rbac.object (uuid),
|
||||
packageUuid uuid references test_package (uuid),
|
||||
name character varying(253),
|
||||
description character varying(96)
|
||||
|
||||
@@ -54,7 +54,7 @@ subgraph package.customer["`**package.customer**`"]
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.->|XX| role:package.customer:OWNER
|
||||
role:rbac.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
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset RbacObjectGenerator:test-domain-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('test_domain');
|
||||
call rbac.generateRelatedRbacObject('test_domain');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset RbacRoleDescriptorsGenerator:test-domain-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('testDomain', 'test_domain');
|
||||
call rbac.generateRbacRoleDescriptors('testDomain', 'test_domain');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:test-domain-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -33,27 +33,27 @@ declare
|
||||
newPackage test_package;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testDomainOWNER(NEW),
|
||||
permissions => array['DELETE', 'UPDATE'],
|
||||
incomingSuperRoles => array[testPackageADMIN(newPackage)],
|
||||
outgoingSubRoles => array[testPackageTENANT(newPackage)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
testDomainADMIN(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[testDomainOWNER(NEW)],
|
||||
outgoingSubRoles => array[testPackageTENANT(newPackage)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -77,7 +77,7 @@ execute procedure insertTriggerForTestDomain_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-update-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:test-domain-rbac-update-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -95,7 +95,7 @@ declare
|
||||
newPackage test_package;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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);
|
||||
@@ -106,18 +106,18 @@ begin
|
||||
|
||||
if NEW.packageUuid <> OLD.packageUuid then
|
||||
|
||||
call revokeRoleFromRole(testDomainOWNER(OLD), testPackageADMIN(oldPackage));
|
||||
call grantRoleToRole(testDomainOWNER(NEW), testPackageADMIN(newPackage));
|
||||
call rbac.revokeRoleFromRole(testDomainOWNER(OLD), testPackageADMIN(oldPackage));
|
||||
call rbac.grantRoleToRole(testDomainOWNER(NEW), testPackageADMIN(newPackage));
|
||||
|
||||
call revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainOWNER(OLD));
|
||||
call grantRoleToRole(testPackageTENANT(newPackage), testDomainOWNER(NEW));
|
||||
call rbac.revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainOWNER(OLD));
|
||||
call rbac.grantRoleToRole(testPackageTENANT(newPackage), testDomainOWNER(NEW));
|
||||
|
||||
call revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainADMIN(OLD));
|
||||
call grantRoleToRole(testPackageTENANT(newPackage), testDomainADMIN(NEW));
|
||||
call rbac.revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainADMIN(OLD));
|
||||
call rbac.grantRoleToRole(testPackageTENANT(newPackage), testDomainADMIN(NEW));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -141,7 +141,7 @@ execute procedure updateTriggerForTestDomain_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:test-domain-rbac-GRANTING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
-- granting INSERT permission to test_package ----------------------------
|
||||
@@ -153,13 +153,13 @@ do language plpgsql $$
|
||||
declare
|
||||
row test_package;
|
||||
begin
|
||||
call defineContext('create INSERT INTO test_domain permissions for pre-exising test_package rows');
|
||||
call base.defineContext('create INSERT INTO test_domain permissions for pre-exising test_package rows');
|
||||
|
||||
FOR row IN SELECT * FROM test_package
|
||||
-- unconditional for all rows in that table
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'test_domain'),
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(row.uuid, 'INSERT', 'test_domain'),
|
||||
testPackageADMIN(row));
|
||||
END LOOP;
|
||||
end;
|
||||
@@ -174,22 +174,22 @@ create or replace function new_test_domain_grants_insert_to_test_package_tf()
|
||||
strict as $$
|
||||
begin
|
||||
-- unconditional for all rows in that table
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'test_domain'),
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(NEW.uuid, 'INSERT', 'test_domain'),
|
||||
testPackageADMIN(NEW));
|
||||
-- end.
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_new_test_domain_grants_insert_to_test_package_tg
|
||||
create trigger z_new_test_domain_grants_after_insert_tg
|
||||
after insert on test_package
|
||||
for each row
|
||||
execute procedure new_test_domain_grants_insert_to_test_package_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test_domain-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:test_domain-rbac-CHECKING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -202,12 +202,12 @@ declare
|
||||
superObjectUuid uuid;
|
||||
begin
|
||||
-- check INSERT permission via direct foreign key: NEW.packageUuid
|
||||
if hasInsertPermission(NEW.packageUuid, 'test_domain') then
|
||||
if rbac.hasInsertPermission(NEW.packageUuid, 'test_domain') then
|
||||
return NEW;
|
||||
end if;
|
||||
|
||||
raise exception '[403] insert into test_domain values(%) not allowed for current subjects % (%)',
|
||||
NEW, currentSubjects(), currentSubjectsUuids();
|
||||
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger test_domain_insert_permission_check_tg
|
||||
@@ -218,10 +218,10 @@ create trigger test_domain_insert_permission_check_tg
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacIdentityViewGenerator:test-domain-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('test_domain',
|
||||
call rbac.generateRbacIdentityViewFromProjection('test_domain',
|
||||
$idName$
|
||||
name
|
||||
$idName$);
|
||||
@@ -229,9 +229,9 @@ call generateRbacIdentityViewFromProjection('test_domain',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacRestrictedViewGenerator:test-domain-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_domain',
|
||||
call rbac.generateRbacRestrictedView('test_domain',
|
||||
$orderBy$
|
||||
name
|
||||
$orderBy$,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-domain-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-domain-TEST-DATA-GENERATOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates the given count of test unix users for a single package.
|
||||
@@ -21,11 +21,11 @@ begin
|
||||
for t in 0..(domainCount-1)
|
||||
loop
|
||||
pacAdmin = 'pac-admin-' || pac.name || '@' || pac.custPrefix || '.example.com';
|
||||
call defineContext('creating RBAC test domain', null, pacAdmin, null);
|
||||
call base.defineContext('creating RBAC test domain', null, pacAdmin, null);
|
||||
|
||||
insert
|
||||
into test_domain (name, packageUuid)
|
||||
values (pac.name || '-' || intToVarChar(t, 4), pac.uuid);
|
||||
values (pac.name || '-' || base.intToVarChar(t, 4), pac.uuid);
|
||||
end loop;
|
||||
end; $$;
|
||||
|
||||
@@ -54,7 +54,7 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-domain-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-domain-TEST-DATA-GENERATION –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists hs_office_contact
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
uuid uuid unique references rbac.object (uuid) initially deferred,
|
||||
version int not null default 0,
|
||||
caption varchar(128) not null,
|
||||
postalAddress text,
|
||||
@@ -17,8 +17,8 @@ create table if not exists hs_office_contact
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MAIN-TABLE-JOURNAL endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_contact');
|
||||
call base.create_journal('hs_office_contact');
|
||||
--//
|
||||
|
||||
@@ -32,7 +32,7 @@ end
|
||||
user:creator ==> role:contact:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN ==> role:contact:OWNER
|
||||
role:rbac.global:ADMIN ==> role:contact:OWNER
|
||||
role:contact:OWNER ==> role:contact:ADMIN
|
||||
role:contact:ADMIN ==> role:contact:REFERRER
|
||||
|
||||
@@ -40,6 +40,6 @@ role:contact:ADMIN ==> role:contact:REFERRER
|
||||
role:contact:OWNER ==> perm:contact:DELETE
|
||||
role:contact:ADMIN ==> perm:contact:UPDATE
|
||||
role:contact:REFERRER ==> perm:contact:SELECT
|
||||
role:global:GUEST ==> perm:contact:INSERT
|
||||
role:rbac.global:GUEST ==> perm:contact:INSERT
|
||||
|
||||
```
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_contact');
|
||||
call rbac.generateRelatedRbacObject('hs_office_contact');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
|
||||
call rbac.generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -32,28 +32,28 @@ create or replace procedure buildRbacSystemForHsOfficeContact(
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeContactOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
incomingSuperRoles => array[rbac.globalAdmin()],
|
||||
subjectUuids => array[rbac.currentSubjectUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeContactADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeContactOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeContactREFERRER(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficeContactADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -77,10 +77,10 @@ execute procedure insertTriggerForHsOfficeContact_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_contact',
|
||||
call rbac.generateRbacIdentityViewFromProjection('hs_office_contact',
|
||||
$idName$
|
||||
caption
|
||||
$idName$);
|
||||
@@ -88,9 +88,9 @@ call generateRbacIdentityViewFromProjection('hs_office_contact',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_contact',
|
||||
call rbac.generateRbacRestrictedView('hs_office_contact',
|
||||
$orderBy$
|
||||
caption
|
||||
$orderBy$,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
-- Once we don't need the external remote views anymore, create revert changesets.
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-mapping:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MIGRATION-mapping endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE hs_office_contact_legacy_id
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE hs_office_contact_legacy_id
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-sequence:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MIGRATION-sequence endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS hs_office_contact_legacy_id_seq
|
||||
@@ -27,7 +27,7 @@ CREATE SEQUENCE IF NOT EXISTS hs_office_contact_legacy_id_seq
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-default:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MIGRATION-default endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
ALTER TABLE hs_office_contact_legacy_id
|
||||
@@ -37,17 +37,17 @@ ALTER TABLE hs_office_contact_legacy_id
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-insert:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MIGRATION-insert endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CALL defineContext('schema-migration');
|
||||
CALL base.defineContext('schema-migration');
|
||||
INSERT INTO hs_office_contact_legacy_id(uuid, contact_id)
|
||||
SELECT uuid, nextVal('hs_office_contact_legacy_id_seq') FROM hs_office_contact;
|
||||
--/
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-insert-trigger:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MIGRATION-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function insertContactLegacyIdMapping()
|
||||
returns trigger
|
||||
@@ -72,7 +72,7 @@ create trigger createContactLegacyIdMapping
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-MIGRATION-delete-trigger:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-MIGRATION-delete-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
create or replace function deleteContactLegacyIdMapping()
|
||||
returns trigger
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-TEST-DATA-GENERATOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -14,10 +14,10 @@ declare
|
||||
postalAddr varchar;
|
||||
emailAddr varchar;
|
||||
begin
|
||||
emailAddr = 'contact-admin@' || cleanIdentifier(contCaption) || '.example.com';
|
||||
call defineContext('creating contact test-data');
|
||||
perform createRbacUser(emailAddr);
|
||||
call defineContext('creating contact test-data', null, emailAddr);
|
||||
emailAddr = 'contact-admin@' || base.cleanIdentifier(contCaption) || '.example.com';
|
||||
call base.defineContext('creating contact test-data');
|
||||
perform rbac.create_subject(emailAddr);
|
||||
call base.defineContext('creating contact test-data', null, emailAddr);
|
||||
|
||||
postalAddr := E'Vorname Nachname\nStraße Hnr\nPLZ Stadt';
|
||||
|
||||
@@ -44,7 +44,7 @@ create or replace procedure createHsOfficeContactTestData(
|
||||
begin
|
||||
for t in startCount..endCount
|
||||
loop
|
||||
call createHsOfficeContactTestData(intToVarChar(t, 4) || '#' || t);
|
||||
call createHsOfficeContactTestData(base.intToVarChar(t, 4) || '#' || t);
|
||||
commit;
|
||||
end loop;
|
||||
end; $$;
|
||||
@@ -52,7 +52,7 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-contact-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-contact-TEST-DATA-GENERATION –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-person-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficePersonType AS ENUM (
|
||||
@@ -16,7 +16,7 @@ CREATE CAST (character varying as HsOfficePersonType) WITH INOUT AS IMPLICIT;
|
||||
|
||||
create table if not exists hs_office_person
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
uuid uuid unique references rbac.object (uuid) initially deferred,
|
||||
version int not null default 0,
|
||||
personType HsOfficePersonType not null,
|
||||
tradeName varchar(96),
|
||||
@@ -28,8 +28,8 @@ create table if not exists hs_office_person
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-person-MAIN-TABLE-JOURNAL endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_person');
|
||||
call base.create_journal('hs_office_person');
|
||||
--//
|
||||
|
||||
@@ -32,12 +32,12 @@ end
|
||||
user:creator ==> role:person:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN ==> role:person:OWNER
|
||||
role:rbac.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:rbac.global:GUEST ==> perm:person:INSERT
|
||||
role:person:OWNER ==> perm:person:DELETE
|
||||
role:person:ADMIN ==> perm:person:UPDATE
|
||||
role:person:REFERRER ==> perm:person:SELECT
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset RbacObjectGenerator:hs-office-person-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_person');
|
||||
call rbac.generateRelatedRbacObject('hs_office_person');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset RbacRoleDescriptorsGenerator:hs-office-person-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
|
||||
call rbac.generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:hs-office-person-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -32,28 +32,28 @@ create or replace procedure buildRbacSystemForHsOfficePerson(
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficePersonOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
incomingSuperRoles => array[rbac.globalADMIN()],
|
||||
subjectUuids => array[rbac.currentSubjectUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficePersonADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficePersonOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficePersonREFERRER(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsOfficePersonADMIN(NEW)]
|
||||
);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -77,10 +77,10 @@ execute procedure insertTriggerForHsOfficePerson_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacIdentityViewGenerator:hs-office-person-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_person',
|
||||
call rbac.generateRbacIdentityViewFromProjection('hs_office_person',
|
||||
$idName$
|
||||
concat(tradeName, familyName, givenName)
|
||||
$idName$);
|
||||
@@ -88,9 +88,9 @@ call generateRbacIdentityViewFromProjection('hs_office_person',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacRestrictedViewGenerator:hs-office-person-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_person',
|
||||
call rbac.generateRbacRestrictedView('hs_office_person',
|
||||
$orderBy$
|
||||
concat(tradeName, familyName, givenName)
|
||||
$orderBy$,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-person-TEST-DATA-GENERATOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -20,10 +20,10 @@ declare
|
||||
emailAddr varchar;
|
||||
begin
|
||||
fullName := concat_ws(', ', newTradeName, newFamilyName, newGivenName);
|
||||
emailAddr = 'person-' || left(cleanIdentifier(fullName), 32) || '@example.com';
|
||||
call defineContext('creating person test-data');
|
||||
perform createRbacUser(emailAddr);
|
||||
call defineContext('creating person test-data', null, emailAddr);
|
||||
emailAddr = 'person-' || left(base.cleanIdentifier(fullName), 32) || '@example.com';
|
||||
call base.defineContext('creating person test-data');
|
||||
perform rbac.create_subject(emailAddr);
|
||||
call base.defineContext('creating person test-data', null, emailAddr);
|
||||
|
||||
raise notice 'creating test person: % by %', fullName, emailAddr;
|
||||
insert
|
||||
@@ -43,7 +43,7 @@ create or replace procedure createTestPersonTestData(
|
||||
begin
|
||||
for t in startCount..endCount
|
||||
loop
|
||||
call createHsOfficePersonTestData('LP', intToVarChar(t, 4));
|
||||
call createHsOfficePersonTestData('LP', base.intToVarChar(t, 4));
|
||||
commit;
|
||||
end loop;
|
||||
end; $$;
|
||||
@@ -51,7 +51,7 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-person-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-person-TEST-DATA-GENERATION –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficeRelationType AS ENUM (
|
||||
@@ -18,7 +18,7 @@ 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
|
||||
uuid uuid unique references rbac.object (uuid) initially deferred, -- on delete cascade
|
||||
version int not null default 0,
|
||||
anchorUuid uuid not null references hs_office_person(uuid),
|
||||
holderUuid uuid not null references hs_office_person(uuid),
|
||||
@@ -30,8 +30,8 @@ create table if not exists hs_office_relation
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-MAIN-TABLE-JOURNAL endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_relation');
|
||||
call base.create_journal('hs_office_relation');
|
||||
--//
|
||||
|
||||
@@ -72,16 +72,16 @@ end
|
||||
user:creator ==> role:relation:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:anchorPerson:OWNER
|
||||
role:rbac.global:ADMIN -.-> role:anchorPerson:OWNER
|
||||
role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN
|
||||
role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:holderPerson:OWNER
|
||||
role:rbac.global:ADMIN -.-> role:holderPerson:OWNER
|
||||
role:holderPerson:OWNER -.-> role:holderPerson:ADMIN
|
||||
role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:contact:OWNER
|
||||
role:rbac.global:ADMIN -.-> role:contact:OWNER
|
||||
role:contact:OWNER -.-> role:contact:ADMIN
|
||||
role:contact:ADMIN -.-> role:contact:REFERRER
|
||||
role:global:ADMIN ==> role:relation:OWNER
|
||||
role:rbac.global:ADMIN ==> role:relation:OWNER
|
||||
role:holderPerson:ADMIN ==> role:relation:OWNER
|
||||
role:relation:OWNER ==> role:relation:ADMIN
|
||||
role:relation:ADMIN ==> role:anchorPerson:OWNER
|
||||
|
||||
@@ -72,16 +72,16 @@ end
|
||||
user:creator ==> role:relation:OWNER
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:anchorPerson:OWNER
|
||||
role:rbac.global:ADMIN -.-> role:anchorPerson:OWNER
|
||||
role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN
|
||||
role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:holderPerson:OWNER
|
||||
role:rbac.global:ADMIN -.-> role:holderPerson:OWNER
|
||||
role:holderPerson:OWNER -.-> role:holderPerson:ADMIN
|
||||
role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:contact:OWNER
|
||||
role:rbac.global:ADMIN -.-> role:contact:OWNER
|
||||
role:contact:OWNER -.-> role:contact:ADMIN
|
||||
role:contact:ADMIN -.-> role:contact:REFERRER
|
||||
role:global:ADMIN ==> role:relation:OWNER
|
||||
role:rbac.global:ADMIN ==> role:relation:OWNER
|
||||
role:relation:OWNER ==> role:relation:ADMIN
|
||||
role:relation:ADMIN ==> role:relation:AGENT
|
||||
role:relation:AGENT ==> role:relation:TENANT
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_relation');
|
||||
call rbac.generateRelatedRbacObject('hs_office_relation');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeRelation', 'hs_office_relation');
|
||||
call rbac.generateRbacRoleDescriptors('hsOfficeRelation', 'hs_office_relation');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -35,7 +35,7 @@ declare
|
||||
newContact hs_office_contact;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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);
|
||||
@@ -47,25 +47,25 @@ begin
|
||||
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeRelationOWNER(NEW),
|
||||
permissions => array['DELETE'],
|
||||
incomingSuperRoles => array[globalADMIN()],
|
||||
userUuids => array[currentUserUuid()]
|
||||
incomingSuperRoles => array[rbac.globalAdmin()],
|
||||
subjectUuids => array[rbac.currentSubjectUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeRelationADMIN(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeRelationOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeRelationAGENT(NEW),
|
||||
incomingSuperRoles => array[hsOfficeRelationADMIN(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
perform rbac.defineRoleWithGrants(
|
||||
hsOfficeRelationTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[
|
||||
@@ -78,15 +78,15 @@ begin
|
||||
);
|
||||
|
||||
IF NEW.type = 'REPRESENTATIVE' THEN
|
||||
call grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW));
|
||||
call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newAnchorPerson));
|
||||
call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson));
|
||||
call rbac.grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW));
|
||||
call rbac.grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newAnchorPerson));
|
||||
call rbac.grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson));
|
||||
ELSE
|
||||
call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson));
|
||||
call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newAnchorPerson));
|
||||
call rbac.grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson));
|
||||
call rbac.grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newAnchorPerson));
|
||||
END IF;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -110,7 +110,7 @@ execute procedure insertTriggerForHsOfficeRelation_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-update-trigger:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-update-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -125,7 +125,7 @@ create or replace procedure updateRbacRulesForHsOfficeRelation(
|
||||
begin
|
||||
|
||||
if NEW.contactUuid is distinct from OLD.contactUuid then
|
||||
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
|
||||
delete from rbac.grants g where g.grantedbytriggerof = OLD.uuid;
|
||||
call buildRbacSystemForHsOfficeRelation(NEW);
|
||||
end if;
|
||||
end; $$;
|
||||
@@ -151,7 +151,7 @@ execute procedure updateTriggerForHsOfficeRelation_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-GRANTING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
-- granting INSERT permission to hs_office_person ----------------------------
|
||||
@@ -163,13 +163,13 @@ do language plpgsql $$
|
||||
declare
|
||||
row hs_office_person;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_relation permissions for pre-exising hs_office_person rows');
|
||||
call base.defineContext('create INSERT INTO hs_office_relation permissions for pre-exising hs_office_person rows');
|
||||
|
||||
FOR row IN SELECT * FROM hs_office_person
|
||||
-- unconditional for all rows in that table
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_relation'),
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(row.uuid, 'INSERT', 'hs_office_relation'),
|
||||
hsOfficePersonADMIN(row));
|
||||
END LOOP;
|
||||
end;
|
||||
@@ -184,8 +184,8 @@ create or replace function new_hs_office_relation_grants_insert_to_hs_office_per
|
||||
strict as $$
|
||||
begin
|
||||
-- unconditional for all rows in that table
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'),
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'),
|
||||
hsOfficePersonADMIN(NEW));
|
||||
-- end.
|
||||
return NEW;
|
||||
@@ -199,7 +199,7 @@ execute procedure new_hs_office_relation_grants_insert_to_hs_office_person_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs_office_relation-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs_office_relation-rbac-CHECKING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -212,12 +212,12 @@ declare
|
||||
superObjectUuid uuid;
|
||||
begin
|
||||
-- check INSERT permission via direct foreign key: NEW.anchorUuid
|
||||
if hasInsertPermission(NEW.anchorUuid, 'hs_office_relation') then
|
||||
if rbac.hasInsertPermission(NEW.anchorUuid, 'hs_office_relation') then
|
||||
return NEW;
|
||||
end if;
|
||||
|
||||
raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_relation_insert_permission_check_tg
|
||||
@@ -228,10 +228,10 @@ create trigger hs_office_relation_insert_permission_check_tg
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_relation',
|
||||
call rbac.generateRbacIdentityViewFromProjection('hs_office_relation',
|
||||
$idName$
|
||||
(select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|
||||
|| '-with-' || target.type || '-'
|
||||
@@ -241,9 +241,9 @@ call generateRbacIdentityViewFromProjection('hs_office_relation',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_relation',
|
||||
call rbac.generateRbacRestrictedView('hs_office_relation',
|
||||
$orderBy$
|
||||
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
|
||||
$orderBy$,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-TEST-DATA-GENERATOR endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -22,7 +22,7 @@ declare
|
||||
contact hs_office_contact;
|
||||
|
||||
begin
|
||||
idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName);
|
||||
idName := base.cleanIdentifier( anchorPersonName || '-' || holderPersonName);
|
||||
|
||||
select p.*
|
||||
into anchorPerson
|
||||
@@ -69,8 +69,8 @@ declare
|
||||
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.caption = intToVarChar(t, 4) || '#' || t into contact;
|
||||
select p.* from hs_office_person p where tradeName = base.intToVarChar(t, 4) into person;
|
||||
select c.* from hs_office_contact c where c.caption = base.intToVarChar(t, 4) || '#' || t into contact;
|
||||
|
||||
call createHsOfficeRelationTestData(person.uuid, contact.uuid, 'REPRESENTATIVE');
|
||||
commit;
|
||||
@@ -80,12 +80,12 @@ end; $$;
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-relation-TEST-DATA-GENERATION –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call defineContext('creating relation test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||
call base.defineContext('creating relation test-data', null, 'superuser-alex@hostsharing.net', 'rbac.global#global:ADMIN');
|
||||
|
||||
call createHsOfficeRelationTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
|
||||
call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-DETAILS-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-partner-DETAILS-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table hs_office_partner_details
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
uuid uuid unique references rbac.object (uuid) initially deferred,
|
||||
version int not null default 0,
|
||||
registrationOffice varchar(96),
|
||||
registrationNumber varchar(96),
|
||||
@@ -20,19 +20,19 @@ create table hs_office_partner_details
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-DETAILS-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-partner-DETAILS-TABLE-JOURNAL endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_partner_details');
|
||||
call base.create_journal('hs_office_partner_details');
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MAIN-TABLE:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-partner-MAIN-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table hs_office_partner
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
uuid uuid unique references rbac.object (uuid) initially deferred,
|
||||
version int not null default 0,
|
||||
partnerNumber numeric(5) unique not null,
|
||||
partnerRelUuid uuid not null references hs_office_relation(uuid), -- deleted in after delete trigger
|
||||
@@ -42,7 +42,7 @@ create table hs_office_partner
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-DELETE-DEPENDENTS-TRIGGER:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-partner-DELETE-DEPENDENTS-TRIGGER endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -80,8 +80,8 @@ create trigger hs_office_partner_delete_dependents_trigger
|
||||
execute procedure deleteHsOfficeDependentsOnPartnerDelete();
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
--changeset michael.hoennig:hs-office-partner-MAIN-TABLE-JOURNAL endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_partner');
|
||||
call base.create_journal('hs_office_partner');
|
||||
--//
|
||||
|
||||
@@ -87,16 +87,16 @@ subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER
|
||||
role:rbac.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:rbac.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:rbac.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:rbac.global:ADMIN -.-> role:partnerRel:OWNER
|
||||
role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
|
||||
role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
|
||||
role:partnerRel:AGENT -.-> role:partnerRel:TENANT
|
||||
@@ -108,7 +108,7 @@ role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
|
||||
role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:ADMIN ==> perm:partner:INSERT
|
||||
role:rbac.global:ADMIN ==> perm:partner:INSERT
|
||||
role:partnerRel:OWNER ==> perm:partner:DELETE
|
||||
role:partnerRel:ADMIN ==> perm:partner:UPDATE
|
||||
role:partnerRel:TENANT ==> perm:partner:SELECT
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset RbacObjectGenerator:hs-office-partner-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_partner');
|
||||
call rbac.generateRelatedRbacObject('hs_office_partner');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset RbacRoleDescriptorsGenerator:hs-office-partner-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
|
||||
call rbac.generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:hs-office-partner-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -34,7 +34,7 @@ declare
|
||||
newPartnerDetails hs_office_partner_details;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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);
|
||||
@@ -42,14 +42,14 @@ begin
|
||||
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'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -73,7 +73,7 @@ execute procedure insertTriggerForHsOfficePartner_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-update-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:hs-office-partner-rbac-update-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -93,7 +93,7 @@ declare
|
||||
newPartnerDetails hs_office_partner_details;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.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);
|
||||
@@ -110,27 +110,27 @@ begin
|
||||
|
||||
if NEW.partnerRelUuid <> OLD.partnerRelUuid then
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
call rbac.revokePermissionFromRole(rbac.getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationADMIN(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
call rbac.revokePermissionFromRole(rbac.getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationADMIN(oldPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTENANT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
|
||||
call rbac.revokePermissionFromRole(rbac.getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTENANT(oldPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
call rbac.revokePermissionFromRole(rbac.getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call rbac.revokePermissionFromRole(rbac.getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
call rbac.revokePermissionFromRole(rbac.getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(oldPartnerRel));
|
||||
call rbac.grantPermissionToRole(rbac.createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
|
||||
|
||||
end if;
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -154,26 +154,26 @@ execute procedure updateTriggerForHsOfficePartner_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:hs-office-partner-rbac-GRANTING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
-- granting INSERT permission to global ----------------------------
|
||||
-- granting INSERT permission to rbac.global ----------------------------
|
||||
|
||||
/*
|
||||
Grants INSERT INTO hs_office_partner permissions to specified role of pre-existing global rows.
|
||||
Grants INSERT INTO hs_office_partner permissions to specified role of pre-existing rbac.global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
row rbac.global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_partner permissions for pre-exising global rows');
|
||||
call base.defineContext('create INSERT INTO hs_office_partner permissions for pre-exising rbac.global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
FOR row IN SELECT * FROM rbac.global
|
||||
-- unconditional for all rows in that table
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_partner'),
|
||||
globalADMIN());
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(row.uuid, 'INSERT', 'hs_office_partner'),
|
||||
rbac.globalADMIN());
|
||||
END LOOP;
|
||||
end;
|
||||
$$;
|
||||
@@ -181,28 +181,28 @@ $$;
|
||||
/**
|
||||
Grants hs_office_partner INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function new_hs_office_partner_grants_insert_to_global_tf()
|
||||
create or replace function rbac.new_hsof_partner_grants_insert_to_global_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
-- unconditional for all rows in that table
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'),
|
||||
globalADMIN());
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'),
|
||||
rbac.globalADMIN());
|
||||
-- end.
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_new_hs_office_partner_grants_insert_to_global_tg
|
||||
after insert on global
|
||||
create trigger z_new_hs_office_partner_grants_after_insert_tg
|
||||
after insert on rbac.global
|
||||
for each row
|
||||
execute procedure new_hs_office_partner_grants_insert_to_global_tf();
|
||||
execute procedure rbac.new_hsof_partner_grants_insert_to_global_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs_office_partner-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:hs_office_partner-rbac-CHECKING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -214,13 +214,13 @@ create or replace function hs_office_partner_insert_permission_check_tf()
|
||||
declare
|
||||
superObjectUuid uuid;
|
||||
begin
|
||||
-- check INSERT INSERT if global ADMIN
|
||||
if isGlobalAdmin() then
|
||||
-- check INSERT INSERT if rbac.global ADMIN
|
||||
if rbac.isGlobalAdmin() then
|
||||
return NEW;
|
||||
end if;
|
||||
|
||||
raise exception '[403] insert into hs_office_partner values(%) not allowed for current subjects % (%)',
|
||||
NEW, currentSubjects(), currentSubjectsUuids();
|
||||
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_partner_insert_permission_check_tg
|
||||
@@ -231,10 +231,10 @@ create trigger hs_office_partner_insert_permission_check_tg
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacIdentityViewGenerator:hs-office-partner-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromProjection('hs_office_partner',
|
||||
call rbac.generateRbacIdentityViewFromProjection('hs_office_partner',
|
||||
$idName$
|
||||
'P-' || partnerNumber
|
||||
$idName$);
|
||||
@@ -242,9 +242,9 @@ call generateRbacIdentityViewFromProjection('hs_office_partner',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacRestrictedViewGenerator:hs-office-partner-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_partner',
|
||||
call rbac.generateRbacRestrictedView('hs_office_partner',
|
||||
$orderBy$
|
||||
'P-' || partnerNumber
|
||||
$orderBy$,
|
||||
|
||||
@@ -18,6 +18,6 @@ subgraph partnerDetails["`**partnerDetails**`"]
|
||||
end
|
||||
|
||||
%% granting permissions to roles
|
||||
role:global:ADMIN ==> perm:partnerDetails:INSERT
|
||||
role:rbac.global:ADMIN ==> perm:partnerDetails:INSERT
|
||||
|
||||
```
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
|
||||
--changeset RbacObjectGenerator:hs-office-partner-details-rbac-OBJECT endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_partner_details');
|
||||
call rbac.generateRelatedRbacObject('hs_office_partner_details');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
--changeset RbacRoleDescriptorsGenerator:hs-office-partner-details-rbac-ROLE-DESCRIPTORS endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficePartnerDetails', 'hs_office_partner_details');
|
||||
call rbac.generateRbacRoleDescriptors('hsOfficePartnerDetails', 'hs_office_partner_details');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-insert-trigger:1 endDelimiter:--//
|
||||
--changeset RolesGrantsAndPermissionsGenerator:hs-office-partner-details-rbac-insert-trigger endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
@@ -32,9 +32,9 @@ create or replace procedure buildRbacSystemForHsOfficePartnerDetails(
|
||||
declare
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
call rbac.leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
@@ -58,26 +58,26 @@ execute procedure insertTriggerForHsOfficePartnerDetails_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:hs-office-partner-details-rbac-GRANTING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
-- granting INSERT permission to global ----------------------------
|
||||
-- granting INSERT permission to rbac.global ----------------------------
|
||||
|
||||
/*
|
||||
Grants INSERT INTO hs_office_partner_details permissions to specified role of pre-existing global rows.
|
||||
Grants INSERT INTO hs_office_partner_details permissions to specified role of pre-existing rbac.global rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row global;
|
||||
row rbac.global;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_office_partner_details permissions for pre-exising global rows');
|
||||
call base.defineContext('create INSERT INTO hs_office_partner_details permissions for pre-exising rbac.global rows');
|
||||
|
||||
FOR row IN SELECT * FROM global
|
||||
FOR row IN SELECT * FROM rbac.global
|
||||
-- unconditional for all rows in that table
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'),
|
||||
globalADMIN());
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'),
|
||||
rbac.globalADMIN());
|
||||
END LOOP;
|
||||
end;
|
||||
$$;
|
||||
@@ -85,28 +85,28 @@ $$;
|
||||
/**
|
||||
Grants hs_office_partner_details INSERT permission to specified role of new global rows.
|
||||
*/
|
||||
create or replace function new_hs_office_partner_details_grants_insert_to_global_tf()
|
||||
create or replace function rbac.new_hsof_partner_details_grants_insert_to_global_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
-- unconditional for all rows in that table
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'),
|
||||
globalADMIN());
|
||||
call rbac.grantPermissionToRole(
|
||||
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'),
|
||||
rbac.globalADMIN());
|
||||
-- end.
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_new_hs_office_partner_details_grants_insert_to_global_tg
|
||||
after insert on global
|
||||
create trigger z_new_hs_office_partner_details_grants_after_insert_tg
|
||||
after insert on rbac.global
|
||||
for each row
|
||||
execute procedure new_hs_office_partner_details_grants_insert_to_global_tf();
|
||||
execute procedure rbac.new_hsof_partner_details_grants_insert_to_global_tf();
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs_office_partner_details-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||
--changeset InsertTriggerGenerator:hs_office_partner_details-rbac-CHECKING-INSERT-PERMISSION endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -118,13 +118,13 @@ create or replace function hs_office_partner_details_insert_permission_check_tf(
|
||||
declare
|
||||
superObjectUuid uuid;
|
||||
begin
|
||||
-- check INSERT INSERT if global ADMIN
|
||||
if isGlobalAdmin() then
|
||||
-- check INSERT INSERT if rbac.global ADMIN
|
||||
if rbac.isGlobalAdmin() then
|
||||
return NEW;
|
||||
end if;
|
||||
|
||||
raise exception '[403] insert into hs_office_partner_details values(%) not allowed for current subjects % (%)',
|
||||
NEW, currentSubjects(), currentSubjectsUuids();
|
||||
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
|
||||
end; $$;
|
||||
|
||||
create trigger hs_office_partner_details_insert_permission_check_tg
|
||||
@@ -135,10 +135,10 @@ create trigger hs_office_partner_details_insert_permission_check_tg
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacIdentityViewGenerator:hs-office-partner-details-rbac-IDENTITY-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromQuery('hs_office_partner_details',
|
||||
call rbac.generateRbacIdentityViewFromQuery('hs_office_partner_details',
|
||||
$idName$
|
||||
SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName
|
||||
FROM hs_office_partner_details AS partnerDetails
|
||||
@@ -149,9 +149,9 @@ call generateRbacIdentityViewFromQuery('hs_office_partner_details',
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset RbacRestrictedViewGenerator:hs-office-partner-details-rbac-RESTRICTED-VIEW endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_partner_details',
|
||||
call rbac.generateRbacRestrictedView('hs_office_partner_details',
|
||||
$orderBy$
|
||||
uuid
|
||||
$orderBy$,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user