introduce-booking-module (#41)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/41 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
@ -0,0 +1,17 @@
|
||||
openapi-processor-mapping: v2
|
||||
|
||||
options:
|
||||
package-name: net.hostsharing.hsadminng.hs.booking.generated.api.v1
|
||||
model-name-suffix: Resource
|
||||
bean-validation: true
|
||||
|
||||
map:
|
||||
result: org.springframework.http.ResponseEntity
|
||||
|
||||
types:
|
||||
- type: array => java.util.List
|
||||
- type: string:uuid => java.util.UUID
|
||||
|
||||
paths:
|
||||
/api/hs/booking/items/{bookingItemUuid}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
20
src/main/resources/api-definition/hs-booking/auth.yaml
Normal file
20
src/main/resources/api-definition/hs-booking/auth.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
components:
|
||||
|
||||
parameters:
|
||||
|
||||
currentUser:
|
||||
name: current-user
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
in: header
|
||||
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.
|
@ -0,0 +1,40 @@
|
||||
components:
|
||||
|
||||
responses:
|
||||
NotFound:
|
||||
description: The specified was not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user 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.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Conflict:
|
||||
description: The request could not be completed due to a conflict with the current state of the target resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
schemas:
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
required:
|
||||
- code
|
||||
- message
|
@ -0,0 +1,113 @@
|
||||
|
||||
components:
|
||||
|
||||
schemas:
|
||||
|
||||
HsBookingItem:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
caption:
|
||||
type: string
|
||||
validFrom:
|
||||
type: string
|
||||
format: date
|
||||
validTo:
|
||||
type: string
|
||||
format: date
|
||||
resources:
|
||||
$ref: '#/components/schemas/BookingResources'
|
||||
required:
|
||||
- uuid
|
||||
- validFrom
|
||||
- validTo
|
||||
- resources
|
||||
|
||||
HsBookingItemPatch:
|
||||
type: object
|
||||
properties:
|
||||
caption:
|
||||
type: string
|
||||
nullable: true
|
||||
validTo:
|
||||
type: string
|
||||
format: date
|
||||
nullable: true
|
||||
resources:
|
||||
$ref: '#/components/schemas/BookingResources'
|
||||
|
||||
HsBookingItemInsert:
|
||||
type: object
|
||||
properties:
|
||||
debitorUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: false
|
||||
caption:
|
||||
type: string
|
||||
minLength: 3
|
||||
maxLength:
|
||||
nullable: false
|
||||
validFrom:
|
||||
type: string
|
||||
format: date
|
||||
nullable: false
|
||||
validTo:
|
||||
type: string
|
||||
format: date
|
||||
nullable: true
|
||||
resources:
|
||||
$ref: '#/components/schemas/BookingResources'
|
||||
required:
|
||||
- caption
|
||||
- debitorUuid
|
||||
- validFrom
|
||||
- resources
|
||||
additionalProperties: false
|
||||
|
||||
BookingResources:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/ManagedServerBookingResources'
|
||||
- $ref: '#/components/schemas/ManagedWebspaceBookingResources'
|
||||
|
||||
ManagedServerBookingResources:
|
||||
type: object
|
||||
properties:
|
||||
caption:
|
||||
type: string
|
||||
minLength: 3
|
||||
maxLength:
|
||||
nullable: false
|
||||
CPU:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 16
|
||||
SSD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
HDD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
additionalProperties: false
|
||||
|
||||
ManagedWebspaceBookingResources:
|
||||
type: object
|
||||
properties:
|
||||
disk:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 16
|
||||
SSD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
HDD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
additionalProperties: false
|
||||
|
@ -0,0 +1,83 @@
|
||||
get:
|
||||
tags:
|
||||
- hs-booking-items
|
||||
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/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the booking item to fetch.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
patch:
|
||||
tags:
|
||||
- hs-booking-items
|
||||
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/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
requestBody:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItemPatch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- hs-booking-items
|
||||
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/assumedRoles'
|
||||
- name: bookingItemUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the booking item to delete.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
"404":
|
||||
$ref: 'error-responses.yaml#/components/responses/NotFound'
|
@ -0,0 +1,58 @@
|
||||
get:
|
||||
summary: Returns a list of all booking items for a specified debitor.
|
||||
description: Returns the list of all booking items for a specified debitor which are visible to the current user or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-booking-items
|
||||
operationId: listBookingItemsByDebitorUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUuid
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The UUID of the debitor, whose booking items are to be listed.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
post:
|
||||
summary: Adds a new booking item.
|
||||
tags:
|
||||
- hs-booking-items
|
||||
operationId: addBookingItem
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
description: A JSON object describing the new booking item.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItemInsert'
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'hs-booking-item-schemas.yaml#/components/schemas/HsBookingItem'
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
||||
"409":
|
||||
$ref: 'error-responses.yaml#/components/responses/Conflict'
|
17
src/main/resources/api-definition/hs-booking/hs-booking.yaml
Normal file
17
src/main/resources/api-definition/hs-booking/hs-booking.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Hostsharing hsadmin-ng API
|
||||
version: v0
|
||||
servers:
|
||||
- url: http://localhost:8080
|
||||
description: Local development default URL.
|
||||
|
||||
paths:
|
||||
|
||||
# Items
|
||||
|
||||
/api/hs/booking/items:
|
||||
$ref: "hs-booking-items.yaml"
|
||||
|
||||
/api/hs/booking/items/{bookingItemUuid}:
|
||||
$ref: "hs-booking-items-with-uuid.yaml"
|
@ -7,7 +7,7 @@
|
||||
create table if not exists hs_office_sepamandate
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
version int not null default 0,
|
||||
version int not null default 0,
|
||||
debitorUuid uuid not null references hs_office_debitor(uuid),
|
||||
bankAccountUuid uuid not null references hs_office_bankaccount(uuid),
|
||||
reference varchar(96) not null,
|
||||
|
@ -0,0 +1,24 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset booking-item-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists hs_booking_item
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid),
|
||||
version int not null default 0,
|
||||
debitorUuid uuid not null references hs_office_debitor(uuid),
|
||||
validity daterange not null,
|
||||
caption varchar(80) not null,
|
||||
resources jsonb not null
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_booking_item');
|
||||
--//
|
@ -0,0 +1,285 @@
|
||||
### rbac bookingItem
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
flowchart TB
|
||||
|
||||
subgraph debitor.debitorRel.anchorPerson["`**debitor.debitorRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.debitorRel.anchorPerson:roles[ ]
|
||||
style debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.debitorRel.anchorPerson:OWNER[[debitor.debitorRel.anchorPerson:OWNER]]
|
||||
role:debitor.debitorRel.anchorPerson:ADMIN[[debitor.debitorRel.anchorPerson:ADMIN]]
|
||||
role:debitor.debitorRel.anchorPerson:REFERRER[[debitor.debitorRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.debitorRel.holderPerson["`**debitor.debitorRel.holderPerson**`"]
|
||||
direction TB
|
||||
style debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.debitorRel.holderPerson:roles[ ]
|
||||
style debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.debitorRel.holderPerson:OWNER[[debitor.debitorRel.holderPerson:OWNER]]
|
||||
role:debitor.debitorRel.holderPerson:ADMIN[[debitor.debitorRel.holderPerson:ADMIN]]
|
||||
role:debitor.debitorRel.holderPerson:REFERRER[[debitor.debitorRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.anchorPerson:roles[ ]
|
||||
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]]
|
||||
role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]]
|
||||
role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
|
||||
direction TB
|
||||
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.holderPerson:roles[ ]
|
||||
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]]
|
||||
role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]]
|
||||
role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.debitorRel["`**debitor.debitorRel**`"]
|
||||
direction TB
|
||||
style debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.debitorRel:roles[ ]
|
||||
style debitor.debitorRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.debitorRel:OWNER[[debitor.debitorRel:OWNER]]
|
||||
role:debitor.debitorRel:ADMIN[[debitor.debitorRel:ADMIN]]
|
||||
role:debitor.debitorRel:AGENT[[debitor.debitorRel:AGENT]]
|
||||
role:debitor.debitorRel:TENANT[[debitor.debitorRel:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.partnerRel["`**debitor.partnerRel**`"]
|
||||
direction TB
|
||||
style debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.partnerRel:roles[ ]
|
||||
style debitor.partnerRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.partnerRel:OWNER[[debitor.partnerRel:OWNER]]
|
||||
role:debitor.partnerRel:ADMIN[[debitor.partnerRel:ADMIN]]
|
||||
role:debitor.partnerRel:AGENT[[debitor.partnerRel:AGENT]]
|
||||
role:debitor.partnerRel:TENANT[[debitor.partnerRel:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph bookingItem["`**bookingItem**`"]
|
||||
direction TB
|
||||
style bookingItem fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph bookingItem:roles[ ]
|
||||
style bookingItem:roles fill:#dd4901,stroke:white
|
||||
|
||||
role:bookingItem:OWNER[[bookingItem:OWNER]]
|
||||
role:bookingItem:ADMIN[[bookingItem:ADMIN]]
|
||||
role:bookingItem:TENANT[[bookingItem:TENANT]]
|
||||
end
|
||||
|
||||
subgraph bookingItem:permissions[ ]
|
||||
style bookingItem:permissions fill:#dd4901,stroke:white
|
||||
|
||||
perm:bookingItem:INSERT{{bookingItem:INSERT}}
|
||||
perm:bookingItem:DELETE{{bookingItem:DELETE}}
|
||||
perm:bookingItem:UPDATE{{bookingItem:UPDATE}}
|
||||
perm:bookingItem:SELECT{{bookingItem:SELECT}}
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.partnerRel.contact["`**debitor.partnerRel.contact**`"]
|
||||
direction TB
|
||||
style debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.partnerRel.contact:roles[ ]
|
||||
style debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.partnerRel.contact:OWNER[[debitor.partnerRel.contact:OWNER]]
|
||||
role:debitor.partnerRel.contact:ADMIN[[debitor.partnerRel.contact:ADMIN]]
|
||||
role:debitor.partnerRel.contact:REFERRER[[debitor.partnerRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.partnerRel.holderPerson["`**debitor.partnerRel.holderPerson**`"]
|
||||
direction TB
|
||||
style debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.partnerRel.holderPerson:roles[ ]
|
||||
style debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.partnerRel.holderPerson:OWNER[[debitor.partnerRel.holderPerson:OWNER]]
|
||||
role:debitor.partnerRel.holderPerson:ADMIN[[debitor.partnerRel.holderPerson:ADMIN]]
|
||||
role:debitor.partnerRel.holderPerson:REFERRER[[debitor.partnerRel.holderPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor["`**debitor**`"]
|
||||
direction TB
|
||||
style debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
end
|
||||
|
||||
subgraph debitor.refundBankAccount["`**debitor.refundBankAccount**`"]
|
||||
direction TB
|
||||
style debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.refundBankAccount:roles[ ]
|
||||
style debitor.refundBankAccount:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.refundBankAccount:OWNER[[debitor.refundBankAccount:OWNER]]
|
||||
role:debitor.refundBankAccount:ADMIN[[debitor.refundBankAccount:ADMIN]]
|
||||
role:debitor.refundBankAccount:REFERRER[[debitor.refundBankAccount:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.partnerRel.anchorPerson["`**debitor.partnerRel.anchorPerson**`"]
|
||||
direction TB
|
||||
style debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.partnerRel.anchorPerson:roles[ ]
|
||||
style debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.partnerRel.anchorPerson:OWNER[[debitor.partnerRel.anchorPerson:OWNER]]
|
||||
role:debitor.partnerRel.anchorPerson:ADMIN[[debitor.partnerRel.anchorPerson:ADMIN]]
|
||||
role:debitor.partnerRel.anchorPerson:REFERRER[[debitor.partnerRel.anchorPerson:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel.contact["`**debitorRel.contact**`"]
|
||||
direction TB
|
||||
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel.contact:roles[ ]
|
||||
style debitorRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]]
|
||||
role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]]
|
||||
role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitor.debitorRel.contact["`**debitor.debitorRel.contact**`"]
|
||||
direction TB
|
||||
style debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitor.debitorRel.contact:roles[ ]
|
||||
style debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitor.debitorRel.contact:OWNER[[debitor.debitorRel.contact:OWNER]]
|
||||
role:debitor.debitorRel.contact:ADMIN[[debitor.debitorRel.contact:ADMIN]]
|
||||
role:debitor.debitorRel.contact:REFERRER[[debitor.debitorRel.contact:REFERRER]]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph debitorRel["`**debitorRel**`"]
|
||||
direction TB
|
||||
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||
|
||||
subgraph debitorRel:roles[ ]
|
||||
style debitorRel:roles fill:#99bcdb,stroke:white
|
||||
|
||||
role:debitorRel:OWNER[[debitorRel:OWNER]]
|
||||
role:debitorRel:ADMIN[[debitorRel:ADMIN]]
|
||||
role:debitorRel:AGENT[[debitorRel:AGENT]]
|
||||
role:debitorRel:TENANT[[debitorRel:TENANT]]
|
||||
end
|
||||
end
|
||||
|
||||
%% granting roles to roles
|
||||
role:global:ADMIN -.-> role:debitor.debitorRel.anchorPerson:OWNER
|
||||
role:debitor.debitorRel.anchorPerson:OWNER -.-> role:debitor.debitorRel.anchorPerson:ADMIN
|
||||
role:debitor.debitorRel.anchorPerson:ADMIN -.-> role:debitor.debitorRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.debitorRel.holderPerson:OWNER
|
||||
role:debitor.debitorRel.holderPerson:OWNER -.-> role:debitor.debitorRel.holderPerson:ADMIN
|
||||
role:debitor.debitorRel.holderPerson:ADMIN -.-> role:debitor.debitorRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.debitorRel.contact:OWNER
|
||||
role:debitor.debitorRel.contact:OWNER -.-> role:debitor.debitorRel.contact:ADMIN
|
||||
role:debitor.debitorRel.contact:ADMIN -.-> role:debitor.debitorRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.debitorRel:OWNER
|
||||
role:debitor.debitorRel:OWNER -.-> role:debitor.debitorRel:ADMIN
|
||||
role:debitor.debitorRel:ADMIN -.-> role:debitor.debitorRel:AGENT
|
||||
role:debitor.debitorRel:AGENT -.-> role:debitor.debitorRel:TENANT
|
||||
role:debitor.debitorRel.contact:ADMIN -.-> role:debitor.debitorRel:TENANT
|
||||
role:debitor.debitorRel:TENANT -.-> role:debitor.debitorRel.anchorPerson:REFERRER
|
||||
role:debitor.debitorRel:TENANT -.-> role:debitor.debitorRel.holderPerson:REFERRER
|
||||
role:debitor.debitorRel:TENANT -.-> role:debitor.debitorRel.contact:REFERRER
|
||||
role:debitor.debitorRel.anchorPerson:ADMIN -.-> role:debitor.debitorRel:OWNER
|
||||
role:debitor.debitorRel.holderPerson:ADMIN -.-> role:debitor.debitorRel:AGENT
|
||||
role:global:ADMIN -.-> role:debitor.refundBankAccount:OWNER
|
||||
role:debitor.refundBankAccount:OWNER -.-> role:debitor.refundBankAccount:ADMIN
|
||||
role:debitor.refundBankAccount:ADMIN -.-> role:debitor.refundBankAccount:REFERRER
|
||||
role:debitor.refundBankAccount:ADMIN -.-> role:debitor.debitorRel:AGENT
|
||||
role:debitor.debitorRel:AGENT -.-> role:debitor.refundBankAccount:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.partnerRel.anchorPerson:OWNER
|
||||
role:debitor.partnerRel.anchorPerson:OWNER -.-> role:debitor.partnerRel.anchorPerson:ADMIN
|
||||
role:debitor.partnerRel.anchorPerson:ADMIN -.-> role:debitor.partnerRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.partnerRel.holderPerson:OWNER
|
||||
role:debitor.partnerRel.holderPerson:OWNER -.-> role:debitor.partnerRel.holderPerson:ADMIN
|
||||
role:debitor.partnerRel.holderPerson:ADMIN -.-> role:debitor.partnerRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.partnerRel.contact:OWNER
|
||||
role:debitor.partnerRel.contact:OWNER -.-> role:debitor.partnerRel.contact:ADMIN
|
||||
role:debitor.partnerRel.contact:ADMIN -.-> role:debitor.partnerRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:debitor.partnerRel:OWNER
|
||||
role:debitor.partnerRel:OWNER -.-> role:debitor.partnerRel:ADMIN
|
||||
role:debitor.partnerRel:ADMIN -.-> role:debitor.partnerRel:AGENT
|
||||
role:debitor.partnerRel:AGENT -.-> role:debitor.partnerRel:TENANT
|
||||
role:debitor.partnerRel.contact:ADMIN -.-> role:debitor.partnerRel:TENANT
|
||||
role:debitor.partnerRel:TENANT -.-> role:debitor.partnerRel.anchorPerson:REFERRER
|
||||
role:debitor.partnerRel:TENANT -.-> role:debitor.partnerRel.holderPerson:REFERRER
|
||||
role:debitor.partnerRel:TENANT -.-> role:debitor.partnerRel.contact:REFERRER
|
||||
role:debitor.partnerRel.anchorPerson:ADMIN -.-> role:debitor.partnerRel:OWNER
|
||||
role:debitor.partnerRel.holderPerson:ADMIN -.-> role:debitor.partnerRel:AGENT
|
||||
role:debitor.partnerRel:ADMIN -.-> role:debitor.debitorRel:ADMIN
|
||||
role:debitor.partnerRel:AGENT -.-> role:debitor.debitorRel:AGENT
|
||||
role:debitor.debitorRel:AGENT -.-> role:debitor.partnerRel:TENANT
|
||||
role:global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER
|
||||
role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN
|
||||
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel.holderPerson:OWNER
|
||||
role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel.contact:OWNER
|
||||
role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
|
||||
role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
|
||||
role:global:ADMIN -.-> role:debitorRel:OWNER
|
||||
role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
|
||||
role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
|
||||
role:debitorRel:AGENT -.-> role:debitorRel:TENANT
|
||||
role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
|
||||
role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
|
||||
role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER
|
||||
role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
|
||||
role:debitorRel:AGENT ==> role:bookingItem:OWNER
|
||||
role:bookingItem:OWNER ==> role:bookingItem:ADMIN
|
||||
role:bookingItem:ADMIN ==> role:bookingItem:TENANT
|
||||
role:bookingItem:TENANT ==> role:debitorRel:TENANT
|
||||
|
||||
%% granting permissions to roles
|
||||
role:debitorRel:ADMIN ==> perm:bookingItem:INSERT
|
||||
role:global:ADMIN ==> perm:bookingItem:DELETE
|
||||
role:bookingItem:OWNER ==> perm:bookingItem:UPDATE
|
||||
role:bookingItem:TENANT ==> perm:bookingItem:SELECT
|
||||
|
||||
```
|
@ -0,0 +1,199 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_booking_item');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsBookingItem', 'hs_booking_item');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-rbac-insert-trigger:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
|
||||
*/
|
||||
|
||||
create or replace procedure buildRbacSystemForHsBookingItem(
|
||||
NEW hs_booking_item
|
||||
)
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
newDebitor hs_office_debitor;
|
||||
newDebitorRel hs_office_relation;
|
||||
|
||||
begin
|
||||
call enterTriggerForObjectUuid(NEW.uuid);
|
||||
|
||||
SELECT * FROM hs_office_debitor WHERE uuid = NEW.debitorUuid INTO newDebitor;
|
||||
assert newDebitor.uuid is not null, format('newDebitor must not be null for NEW.debitorUuid = %s', NEW.debitorUuid);
|
||||
|
||||
SELECT debitorRel.*
|
||||
FROM hs_office_relation debitorRel
|
||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||
WHERE debitor.uuid = NEW.debitorUuid
|
||||
INTO newDebitorRel;
|
||||
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s', NEW.debitorUuid);
|
||||
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsBookingItemOWNER(NEW),
|
||||
permissions => array['UPDATE'],
|
||||
incomingSuperRoles => array[hsOfficeRelationAGENT(newDebitorRel)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsBookingItemADMIN(NEW),
|
||||
incomingSuperRoles => array[hsBookingItemOWNER(NEW)]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
hsBookingItemTENANT(NEW),
|
||||
permissions => array['SELECT'],
|
||||
incomingSuperRoles => array[hsBookingItemADMIN(NEW)],
|
||||
outgoingSubRoles => array[hsOfficeRelationTENANT(newDebitorRel)]
|
||||
);
|
||||
|
||||
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), globalAdmin());
|
||||
|
||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_booking_item row.
|
||||
*/
|
||||
|
||||
create or replace function insertTriggerForHsBookingItem_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
call buildRbacSystemForHsBookingItem(NEW);
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger insertTriggerForHsBookingItem_tg
|
||||
after insert on hs_booking_item
|
||||
for each row
|
||||
execute procedure insertTriggerForHsBookingItem_tf();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates INSERT INTO hs_booking_item permissions for the related hs_office_relation rows.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
row hs_office_relation;
|
||||
begin
|
||||
call defineContext('create INSERT INTO hs_booking_item permissions for the related hs_office_relation rows');
|
||||
|
||||
FOR row IN SELECT * FROM hs_office_relation
|
||||
WHERE type in ('DEBITOR') -- TODO.rbac: currently manually patched, needs to be generated
|
||||
LOOP
|
||||
call grantPermissionToRole(
|
||||
createPermission(row.uuid, 'INSERT', 'hs_booking_item'),
|
||||
hsOfficeRelationADMIN(row));
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Adds hs_booking_item INSERT permission to specified role of new hs_office_relation rows.
|
||||
*/
|
||||
create or replace function hs_booking_item_hs_office_relation_insert_tf()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
begin
|
||||
if NEW.type = 'DEBITOR' then -- TODO.rbac: currently manually patched, needs to be generated
|
||||
call grantPermissionToRole(
|
||||
createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'),
|
||||
hsOfficeRelationADMIN(NEW));
|
||||
end if;
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
|
||||
create trigger z_hs_booking_item_hs_office_relation_insert_tg
|
||||
after insert on hs_office_relation
|
||||
for each row
|
||||
execute procedure hs_booking_item_hs_office_relation_insert_tf();
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to hs_booking_item,
|
||||
where the check is performed by an indirect role.
|
||||
|
||||
An indirect role is a role which depends on an object uuid which is not a direct foreign key
|
||||
of the source entity, but needs to be fetched via joined tables.
|
||||
*/
|
||||
create or replace function hs_booking_item_insert_permission_check_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
|
||||
declare
|
||||
superRoleObjectUuid uuid;
|
||||
|
||||
begin
|
||||
superRoleObjectUuid := (SELECT debitorRel.uuid
|
||||
FROM hs_office_relation debitorRel
|
||||
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
|
||||
WHERE debitor.uuid = NEW.debitorUuid
|
||||
);
|
||||
assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null';
|
||||
|
||||
if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_booking_item') ) then
|
||||
raise exception
|
||||
'[403] insert into hs_booking_item not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger hs_booking_item_insert_permission_check_tg
|
||||
before insert on hs_booking_item
|
||||
for each row
|
||||
execute procedure hs_booking_item_insert_permission_check_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call generateRbacIdentityViewFromQuery('hs_booking_item',
|
||||
$idName$
|
||||
SELECT i.uuid as uuid, d.idName || ':' || i.caption as idName
|
||||
FROM hs_booking_item i
|
||||
JOIN hs_office_debitor_iv d ON d.uuid = i.debitorUuid
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_booking_item',
|
||||
$orderBy$
|
||||
validity
|
||||
$orderBy$,
|
||||
$updates$
|
||||
version = new.version,
|
||||
validity = new.validity,
|
||||
resources = new.resources
|
||||
$updates$);
|
||||
--//
|
||||
|
@ -0,0 +1,52 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single hs_booking_item test record.
|
||||
*/
|
||||
create or replace procedure createHsBookingItemTransactionTestData(
|
||||
givenPartnerNumber numeric,
|
||||
givenDebitorSuffix char(2)
|
||||
)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
relatedDebitor hs_office_debitor;
|
||||
begin
|
||||
currentTask := 'creating booking-item test-data ' || givenPartnerNumber::text || givenDebitorSuffix;
|
||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||
|
||||
select debitor.* into relatedDebitor
|
||||
from hs_office_debitor debitor
|
||||
join hs_office_relation debitorRel on debitorRel.uuid = debitor.debitorRelUuid
|
||||
join hs_office_relation partnerRel on partnerRel.holderUuid = debitorRel.anchorUuid
|
||||
join hs_office_partner partner on partner.partnerRelUuid = partnerRel.uuid
|
||||
where partner.partnerNumber = givenPartnerNumber and debitor.debitorNumberSuffix = givenDebitorSuffix;
|
||||
|
||||
raise notice 'creating test booking-item: %', givenPartnerNumber::text || givenDebitorSuffix::text;
|
||||
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
|
||||
insert
|
||||
into hs_booking_item (uuid, debitoruuid, caption, validity, resources)
|
||||
values (uuid_generate_v4(), relatedDebitor.uuid, 'some ManagedServer', daterange('20221001', null, '[]'), '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb),
|
||||
(uuid_generate_v4(), relatedDebitor.uuid, 'some CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb),
|
||||
(uuid_generate_v4(), relatedDebitor.uuid, 'some Whatever', daterange('20240401', null, '[]'), '{ "CPU": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-item-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsBookingItemTransactionTestData(10001, '11');
|
||||
call createHsBookingItemTransactionTestData(10002, '12');
|
||||
call createHsBookingItemTransactionTestData(10003, '13');
|
||||
end;
|
||||
$$;
|
@ -127,3 +127,9 @@ databaseChangeLog:
|
||||
file: db/changelog/5-hs-office/512-coopassets/5126-hs-office-coopassets-migration.sql
|
||||
- include:
|
||||
file: db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/6-hs-booking/601-booking-item/6010-hs-booking-item.sql
|
||||
- include:
|
||||
file: db/changelog/6-hs-booking/601-booking-item/6013-hs-booking-item-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/6-hs-booking/601-booking-item/6018-hs-booking-item-test-data.sql
|
||||
|
Reference in New Issue
Block a user