add optional alarm-contact to hosting-asset #64
@ -16,7 +16,9 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.EntityNotFoundException;
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import jakarta.persistence.PersistenceContext;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@ -26,6 +28,9 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAss
|
|||||||
@RestController
|
@RestController
|
||||||
public class HsHostingAssetController implements HsHostingAssetsApi {
|
public class HsHostingAssetController implements HsHostingAssetsApi {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
@ -119,7 +124,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
|
|||||||
|
|
||||||
final var current = assetRepo.findByUuid(assetUuid).orElseThrow();
|
final var current = assetRepo.findByUuid(assetUuid).orElseThrow();
|
||||||
|
|
||||||
new HsHostingAssetEntityPatcher(current).apply(body);
|
new HsHostingAssetEntityPatcher(em, current).apply(body);
|
||||||
|
|
||||||
final var saved = validated(assetRepo.save(current));
|
final var saved = validated(assetRepo.save(current));
|
||||||
final var mapped = mapper.map(saved, HsHostingAssetResource.class);
|
final var mapped = mapper.map(saved, HsHostingAssetResource.class);
|
||||||
|
@ -8,6 +8,7 @@ import lombok.Getter;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||||
@ -48,6 +49,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
|
|||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
|
||||||
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.REFERRER;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||||
@ -95,6 +97,10 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private HsHostingAssetType type;
|
private HsHostingAssetType type;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "alarmcontactuuid")
|
||||||
|
private HsOfficeContactEntity alarmContact;
|
||||||
|
|
||||||
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true, fetch = FetchType.LAZY)
|
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true, fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name="parentassetuuid", referencedColumnName="uuid")
|
@JoinColumn(name="parentassetuuid", referencedColumnName="uuid")
|
||||||
private List<HsHostingAssetEntity> subHostingAssets;
|
private List<HsHostingAssetEntity> subHostingAssets;
|
||||||
@ -136,7 +142,7 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
return rbacViewFor("asset", HsHostingAssetEntity.class)
|
return rbacViewFor("asset", HsHostingAssetEntity.class)
|
||||||
.withIdentityView(SQL.projection("identifier"))
|
.withIdentityView(SQL.projection("identifier"))
|
||||||
.withRestrictedViewOrderBy(SQL.expression("identifier"))
|
.withRestrictedViewOrderBy(SQL.expression("identifier"))
|
||||||
.withUpdatableColumns("version", "caption", "config")
|
.withUpdatableColumns("version", "caption", "config", "assignedToAssetUuid", "alarmContactUuid")
|
||||||
.toRole(GLOBAL, ADMIN).grantPermission(INSERT) // TODO.impl: Why is this necessary to insert test data?
|
.toRole(GLOBAL, ADMIN).grantPermission(INSERT) // TODO.impl: Why is this necessary to insert test data?
|
||||||
|
|
||||||
.importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(),
|
.importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(),
|
||||||
@ -155,6 +161,11 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
directlyFetchedByDependsOnColumn(),
|
directlyFetchedByDependsOnColumn(),
|
||||||
NULLABLE)
|
NULLABLE)
|
||||||
|
|
||||||
|
.importEntityAlias("alarmContact", HsOfficeContactEntity.class, usingDefaultCase(),
|
||||||
|
dependsOnColumn("alarmContactUuid"),
|
||||||
|
directlyFetchedByDependsOnColumn(),
|
||||||
|
NULLABLE)
|
||||||
|
|
||||||
.createRole(OWNER, (with) -> {
|
.createRole(OWNER, (with) -> {
|
||||||
with.incomingSuperRole("bookingItem", ADMIN);
|
with.incomingSuperRole("bookingItem", ADMIN);
|
||||||
with.incomingSuperRole("parentAsset", ADMIN);
|
with.incomingSuperRole("parentAsset", ADMIN);
|
||||||
@ -167,13 +178,15 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
})
|
})
|
||||||
.createSubRole(AGENT, (with) -> {
|
.createSubRole(AGENT, (with) -> {
|
||||||
with.outgoingSubRole("assignedToAsset", TENANT);
|
with.outgoingSubRole("assignedToAsset", TENANT);
|
||||||
|
with.outgoingSubRole("alarmContact", REFERRER);
|
||||||
})
|
})
|
||||||
.createSubRole(TENANT, (with) -> {
|
.createSubRole(TENANT, (with) -> {
|
||||||
with.outgoingSubRole("bookingItem", TENANT);
|
with.outgoingSubRole("bookingItem", TENANT);
|
||||||
with.outgoingSubRole("parentAsset", TENANT);
|
with.outgoingSubRole("parentAsset", TENANT);
|
||||||
|
with.incomingSuperRole("alarmContact", ADMIN);
|
||||||
with.permission(SELECT);
|
with.permission(SELECT);
|
||||||
})
|
})
|
||||||
.limitDiagramTo("asset", "bookingItem", "bookingItem.debitorRel", "parentAsset", "assignedToAsset", "global");
|
.limitDiagramTo("asset", "bookingItem", "bookingItem.debitorRel", "parentAsset", "assignedToAsset", "alarmContact", "global");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
package net.hostsharing.hsadminng.hs.hosting.asset;
|
package net.hostsharing.hsadminng.hs.hosting.asset;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource;
|
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||||
import net.hostsharing.hsadminng.mapper.KeyValueMap;
|
import net.hostsharing.hsadminng.mapper.KeyValueMap;
|
||||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class HsHostingAssetEntityPatcher implements EntityPatcher<HsHostingAssetPatchResource> {
|
public class HsHostingAssetEntityPatcher implements EntityPatcher<HsHostingAssetPatchResource> {
|
||||||
|
|
||||||
|
private final EntityManager em;
|
||||||
private final HsHostingAssetEntity entity;
|
private final HsHostingAssetEntity entity;
|
||||||
|
|
||||||
public HsHostingAssetEntityPatcher(final HsHostingAssetEntity entity) {
|
HsHostingAssetEntityPatcher(final EntityManager em, final HsHostingAssetEntity entity) {
|
||||||
|
this.em = em;
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,5 +25,11 @@ public class HsHostingAssetEntityPatcher implements EntityPatcher<HsHostingAsset
|
|||||||
.ifPresent(entity::setCaption);
|
.ifPresent(entity::setCaption);
|
||||||
Optional.ofNullable(resource.getConfig())
|
Optional.ofNullable(resource.getConfig())
|
||||||
.ifPresent(r -> entity.getConfig().patch(KeyValueMap.from(resource.getConfig())));
|
.ifPresent(r -> entity.getConfig().patch(KeyValueMap.from(resource.getConfig())));
|
||||||
|
OptionalFromJson.of(resource.getAlarmContactUuid())
|
||||||
|
// HOWTO: patch nullable JSON resource uuid to an ntity reference
|
||||||
|
.ifPresent(newValue -> entity.setAlarmContact(
|
||||||
|
Optional.ofNullable(newValue)
|
||||||
|
.map(uuid -> em.getReference(HsOfficeContactEntity.class, newValue))
|
||||||
|
.orElse(null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
caption:
|
caption:
|
||||||
type: string
|
type: string
|
||||||
|
alarmContact:
|
||||||
|
$ref: '../hs-office/hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||||
config:
|
config:
|
||||||
$ref: '#/components/schemas/HsHostingAssetConfiguration'
|
$ref: '#/components/schemas/HsHostingAssetConfiguration'
|
||||||
required:
|
required:
|
||||||
@ -46,6 +48,10 @@ components:
|
|||||||
caption:
|
caption:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
alarmContactUuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
config:
|
config:
|
||||||
$ref: '#/components/schemas/HsHostingAssetConfiguration'
|
$ref: '#/components/schemas/HsHostingAssetConfiguration'
|
||||||
|
|
||||||
@ -72,6 +78,10 @@ components:
|
|||||||
minLength: 3
|
minLength: 3
|
||||||
maxLength: 80
|
maxLength: 80
|
||||||
nullable: false
|
nullable: false
|
||||||
|
alarmContactUuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
config:
|
config:
|
||||||
$ref: '#/components/schemas/HsHostingAssetConfiguration'
|
$ref: '#/components/schemas/HsHostingAssetConfiguration'
|
||||||
required:
|
required:
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
### rbac bookingItem
|
||||||
|
|
||||||
|
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
|
flowchart TB
|
||||||
|
|
||||||
|
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:AGENT[[bookingItem:AGENT]]
|
||||||
|
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 project["`**project**`"]
|
||||||
|
direction TB
|
||||||
|
style project fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
|
subgraph project:roles[ ]
|
||||||
|
style project:roles fill:#99bcdb,stroke:white
|
||||||
|
|
||||||
|
role:project:OWNER[[project:OWNER]]
|
||||||
|
role:project:ADMIN[[project:ADMIN]]
|
||||||
|
role:project:AGENT[[project:AGENT]]
|
||||||
|
role:project:TENANT[[project:TENANT]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% granting roles to roles
|
||||||
|
role:project:OWNER -.-> role:project:ADMIN
|
||||||
|
role:project:ADMIN -.-> role:project:AGENT
|
||||||
|
role:project:AGENT -.-> role:project:TENANT
|
||||||
|
role:project:AGENT ==> role:bookingItem:OWNER
|
||||||
|
role:bookingItem:OWNER ==> role:bookingItem:ADMIN
|
||||||
|
role:bookingItem:ADMIN ==> role:bookingItem:AGENT
|
||||||
|
role:bookingItem:AGENT ==> role:bookingItem:TENANT
|
||||||
|
role:bookingItem:TENANT ==> role:project:TENANT
|
||||||
|
|
||||||
|
%% granting permissions to roles
|
||||||
|
role:global:ADMIN ==> perm:bookingItem:INSERT
|
||||||
|
role:global:ADMIN ==> perm:bookingItem:DELETE
|
||||||
|
role:project:ADMIN ==> perm:bookingItem:INSERT
|
||||||
|
role:bookingItem:ADMIN ==> perm:bookingItem:UPDATE
|
||||||
|
role:bookingItem:TENANT ==> perm:bookingItem:SELECT
|
||||||
|
|
||||||
|
```
|
@ -0,0 +1,277 @@
|
|||||||
|
--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
|
||||||
|
newProject hs_booking_project;
|
||||||
|
newParentItem hs_booking_item;
|
||||||
|
|
||||||
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
|
SELECT * FROM hs_booking_project WHERE uuid = NEW.projectUuid INTO newProject;
|
||||||
|
|
||||||
|
SELECT * FROM hs_booking_item WHERE uuid = NEW.parentItemUuid INTO newParentItem;
|
||||||
|
|
||||||
|
perform createRoleWithGrants(
|
||||||
|
hsBookingItemOWNER(NEW),
|
||||||
|
incomingSuperRoles => array[
|
||||||
|
hsBookingItemAGENT(newParentItem),
|
||||||
|
hsBookingProjectAGENT(newProject)]
|
||||||
|
);
|
||||||
|
|
||||||
|
perform createRoleWithGrants(
|
||||||
|
hsBookingItemADMIN(NEW),
|
||||||
|
permissions => array['UPDATE'],
|
||||||
|
incomingSuperRoles => array[hsBookingItemOWNER(NEW)]
|
||||||
|
);
|
||||||
|
|
||||||
|
perform createRoleWithGrants(
|
||||||
|
hsBookingItemAGENT(NEW),
|
||||||
|
incomingSuperRoles => array[hsBookingItemADMIN(NEW)]
|
||||||
|
);
|
||||||
|
|
||||||
|
perform createRoleWithGrants(
|
||||||
|
hsBookingItemTENANT(NEW),
|
||||||
|
permissions => array['SELECT'],
|
||||||
|
incomingSuperRoles => array[hsBookingItemAGENT(NEW)],
|
||||||
|
outgoingSubRoles => array[
|
||||||
|
hsBookingItemTENANT(newParentItem),
|
||||||
|
hsBookingProjectTENANT(newProject)]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- granting INSERT permission to global ----------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
Grants INSERT INTO hs_booking_item permissions to specified role of pre-existing global rows.
|
||||||
|
*/
|
||||||
|
do language plpgsql $$
|
||||||
|
declare
|
||||||
|
row global;
|
||||||
|
begin
|
||||||
|
call defineContext('create INSERT INTO hs_booking_item permissions for pre-exising global rows');
|
||||||
|
|
||||||
|
FOR row IN SELECT * FROM global
|
||||||
|
-- unconditional for all rows in that table
|
||||||
|
LOOP
|
||||||
|
call grantPermissionToRole(
|
||||||
|
createPermission(row.uuid, 'INSERT', 'hs_booking_item'),
|
||||||
|
globalADMIN());
|
||||||
|
END LOOP;
|
||||||
|
end;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grants hs_booking_item INSERT permission to specified role of new global rows.
|
||||||
|
*/
|
||||||
|
create or replace function new_hs_booking_item_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_booking_item'),
|
||||||
|
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_booking_item_grants_insert_to_global_tg
|
||||||
|
after insert on global
|
||||||
|
for each row
|
||||||
|
execute procedure new_hs_booking_item_grants_insert_to_global_tf();
|
||||||
|
|
||||||
|
-- granting INSERT permission to hs_booking_project ----------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
Grants INSERT INTO hs_booking_item permissions to specified role of pre-existing hs_booking_project rows.
|
||||||
|
*/
|
||||||
|
do language plpgsql $$
|
||||||
|
declare
|
||||||
|
row hs_booking_project;
|
||||||
|
begin
|
||||||
|
call defineContext('create INSERT INTO hs_booking_item permissions for pre-exising hs_booking_project rows');
|
||||||
|
|
||||||
|
FOR row IN SELECT * FROM hs_booking_project
|
||||||
|
-- unconditional for all rows in that table
|
||||||
|
LOOP
|
||||||
|
call grantPermissionToRole(
|
||||||
|
createPermission(row.uuid, 'INSERT', 'hs_booking_item'),
|
||||||
|
hsBookingProjectADMIN(row));
|
||||||
|
END LOOP;
|
||||||
|
end;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grants hs_booking_item INSERT permission to specified role of new hs_booking_project rows.
|
||||||
|
*/
|
||||||
|
create or replace function new_hs_booking_item_grants_insert_to_hs_booking_project_tf()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql
|
||||||
|
strict as $$
|
||||||
|
begin
|
||||||
|
-- unconditional for all rows in that table
|
||||||
|
call grantPermissionToRole(
|
||||||
|
createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'),
|
||||||
|
hsBookingProjectADMIN(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_hs_booking_item_grants_insert_to_hs_booking_project_tg
|
||||||
|
after insert on hs_booking_project
|
||||||
|
for each row
|
||||||
|
execute procedure new_hs_booking_item_grants_insert_to_hs_booking_project_tf();
|
||||||
|
|
||||||
|
-- granting INSERT permission to hs_booking_item ----------------------------
|
||||||
|
|
||||||
|
-- Granting INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_hosting_asset rows slipped,
|
||||||
|
-- because there cannot yet be any pre-existing rows in the same table yet.
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grants hs_booking_item INSERT permission to specified role of new hs_booking_item rows.
|
||||||
|
*/
|
||||||
|
create or replace function new_hs_booking_item_grants_insert_to_hs_booking_item_tf()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql
|
||||||
|
strict as $$
|
||||||
|
begin
|
||||||
|
-- unconditional for all rows in that table
|
||||||
|
call grantPermissionToRole(
|
||||||
|
createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'),
|
||||||
|
hsBookingItemADMIN(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_hs_booking_item_grants_insert_to_hs_booking_item_tg
|
||||||
|
after insert on hs_booking_item
|
||||||
|
for each row
|
||||||
|
execute procedure new_hs_booking_item_grants_insert_to_hs_booking_item_tf();
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs_booking_item-rbac-CHECKING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Checks if the user respectively the assumed roles are allowed to insert a row to hs_booking_item.
|
||||||
|
*/
|
||||||
|
create or replace function hs_booking_item_insert_permission_check_tf()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
superObjectUuid uuid;
|
||||||
|
begin
|
||||||
|
-- check INSERT INSERT if global ADMIN
|
||||||
|
if isGlobalAdmin() then
|
||||||
|
return NEW;
|
||||||
|
end if;
|
||||||
|
-- check INSERT permission via direct foreign key: NEW.projectUuid
|
||||||
|
if hasInsertPermission(NEW.projectUuid, 'hs_booking_item') then
|
||||||
|
return NEW;
|
||||||
|
end if;
|
||||||
|
-- check INSERT permission via direct foreign key: NEW.parentItemUuid
|
||||||
|
if hasInsertPermission(NEW.parentItemUuid, 'hs_booking_item') then
|
||||||
|
return NEW;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
raise exception '[403] insert into hs_booking_item values(%) not allowed for current subjects % (%)',
|
||||||
|
NEW, currentSubjects(), currentSubjectsUuids();
|
||||||
|
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 generateRbacIdentityViewFromProjection('hs_booking_item',
|
||||||
|
$idName$
|
||||||
|
caption
|
||||||
|
$idName$);
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs-booking-item-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
call generateRbacRestrictedView('hs_booking_item',
|
||||||
|
$orderBy$
|
||||||
|
validity
|
||||||
|
$orderBy$,
|
||||||
|
$updates$
|
||||||
|
version = new.version,
|
||||||
|
caption = new.caption,
|
||||||
|
validity = new.validity,
|
||||||
|
resources = new.resources
|
||||||
|
$updates$);
|
||||||
|
--//
|
||||||
|
|
@ -33,6 +33,7 @@ create table if not exists hs_hosting_asset
|
|||||||
identifier varchar(80) not null,
|
identifier varchar(80) not null,
|
||||||
caption varchar(80),
|
caption varchar(80),
|
||||||
config jsonb not null,
|
config jsonb not null,
|
||||||
|
alarmContactUuid uuid null references hs_office_contact(uuid) initially deferred,
|
||||||
|
|
||||||
constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset
|
constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset
|
||||||
check (bookingItemUuid is not null or parentAssetUuid is not null)
|
check (bookingItemUuid is not null or parentAssetUuid is not null)
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
### rbac asset inCaseOf:CLOUD_SERVER
|
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
|
||||||
flowchart TB
|
|
||||||
|
|
||||||
subgraph asset["`**asset**`"]
|
|
||||||
direction TB
|
|
||||||
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph asset:roles[ ]
|
|
||||||
style asset:roles fill:#dd4901,stroke:white
|
|
||||||
|
|
||||||
role:asset:OWNER[[asset:OWNER]]
|
|
||||||
role:asset:ADMIN[[asset:ADMIN]]
|
|
||||||
role:asset:TENANT[[asset:TENANT]]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph asset:permissions[ ]
|
|
||||||
style asset:permissions fill:#dd4901,stroke:white
|
|
||||||
|
|
||||||
perm:asset:INSERT{{asset:INSERT}}
|
|
||||||
perm:asset:DELETE{{asset:DELETE}}
|
|
||||||
perm:asset:UPDATE{{asset:UPDATE}}
|
|
||||||
perm:asset:SELECT{{asset:SELECT}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph bookingItem["`**bookingItem**`"]
|
|
||||||
direction TB
|
|
||||||
style bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph bookingItem:roles[ ]
|
|
||||||
style bookingItem:roles fill:#99bcdb,stroke:white
|
|
||||||
|
|
||||||
role:bookingItem:OWNER[[bookingItem:OWNER]]
|
|
||||||
role:bookingItem:ADMIN[[bookingItem:ADMIN]]
|
|
||||||
role:bookingItem:AGENT[[bookingItem:AGENT]]
|
|
||||||
role:bookingItem:TENANT[[bookingItem:TENANT]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph parentServer["`**parentServer**`"]
|
|
||||||
direction TB
|
|
||||||
style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph parentServer:roles[ ]
|
|
||||||
style parentServer:roles fill:#99bcdb,stroke:white
|
|
||||||
|
|
||||||
role:parentServer:ADMIN[[parentServer:ADMIN]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
%% granting roles to roles
|
|
||||||
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
|
|
||||||
role:bookingItem:ADMIN -.-> role:bookingItem:AGENT
|
|
||||||
role:bookingItem:AGENT -.-> role:bookingItem:TENANT
|
|
||||||
role:bookingItem:ADMIN ==> role:asset:OWNER
|
|
||||||
role:asset:OWNER ==> role:asset:ADMIN
|
|
||||||
role:asset:ADMIN ==> role:asset:TENANT
|
|
||||||
role:asset:TENANT ==> role:bookingItem:TENANT
|
|
||||||
|
|
||||||
%% granting permissions to roles
|
|
||||||
role:bookingItem:AGENT ==> perm:asset:INSERT
|
|
||||||
role:asset:OWNER ==> perm:asset:DELETE
|
|
||||||
role:asset:ADMIN ==> perm:asset:UPDATE
|
|
||||||
role:asset:TENANT ==> perm:asset:SELECT
|
|
||||||
role:global:ADMIN ==> perm:asset:INSERT
|
|
||||||
|
|
||||||
```
|
|
@ -1,72 +0,0 @@
|
|||||||
### rbac asset inCaseOf:MANAGED_SERVER
|
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
|
||||||
flowchart TB
|
|
||||||
|
|
||||||
subgraph asset["`**asset**`"]
|
|
||||||
direction TB
|
|
||||||
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph asset:roles[ ]
|
|
||||||
style asset:roles fill:#dd4901,stroke:white
|
|
||||||
|
|
||||||
role:asset:OWNER[[asset:OWNER]]
|
|
||||||
role:asset:ADMIN[[asset:ADMIN]]
|
|
||||||
role:asset:TENANT[[asset:TENANT]]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph asset:permissions[ ]
|
|
||||||
style asset:permissions fill:#dd4901,stroke:white
|
|
||||||
|
|
||||||
perm:asset:INSERT{{asset:INSERT}}
|
|
||||||
perm:asset:DELETE{{asset:DELETE}}
|
|
||||||
perm:asset:UPDATE{{asset:UPDATE}}
|
|
||||||
perm:asset:SELECT{{asset:SELECT}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph bookingItem["`**bookingItem**`"]
|
|
||||||
direction TB
|
|
||||||
style bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph bookingItem:roles[ ]
|
|
||||||
style bookingItem:roles fill:#99bcdb,stroke:white
|
|
||||||
|
|
||||||
role:bookingItem:OWNER[[bookingItem:OWNER]]
|
|
||||||
role:bookingItem:ADMIN[[bookingItem:ADMIN]]
|
|
||||||
role:bookingItem:AGENT[[bookingItem:AGENT]]
|
|
||||||
role:bookingItem:TENANT[[bookingItem:TENANT]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph parentServer["`**parentServer**`"]
|
|
||||||
direction TB
|
|
||||||
style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph parentServer:roles[ ]
|
|
||||||
style parentServer:roles fill:#99bcdb,stroke:white
|
|
||||||
|
|
||||||
role:parentServer:ADMIN[[parentServer:ADMIN]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
%% granting roles to roles
|
|
||||||
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
|
|
||||||
role:bookingItem:ADMIN -.-> role:bookingItem:AGENT
|
|
||||||
role:bookingItem:AGENT -.-> role:bookingItem:TENANT
|
|
||||||
role:bookingItem:ADMIN ==> role:asset:OWNER
|
|
||||||
role:asset:OWNER ==> role:asset:ADMIN
|
|
||||||
role:asset:ADMIN ==> role:asset:TENANT
|
|
||||||
role:asset:TENANT ==> role:bookingItem:TENANT
|
|
||||||
|
|
||||||
%% granting permissions to roles
|
|
||||||
role:bookingItem:AGENT ==> perm:asset:INSERT
|
|
||||||
role:asset:OWNER ==> perm:asset:DELETE
|
|
||||||
role:asset:ADMIN ==> perm:asset:UPDATE
|
|
||||||
role:asset:TENANT ==> perm:asset:SELECT
|
|
||||||
role:global:ADMIN ==> perm:asset:INSERT
|
|
||||||
|
|
||||||
```
|
|
@ -1,73 +0,0 @@
|
|||||||
### rbac asset inCaseOf:MANAGED_WEBSPACE
|
|
||||||
|
|
||||||
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
|
||||||
flowchart TB
|
|
||||||
|
|
||||||
subgraph asset["`**asset**`"]
|
|
||||||
direction TB
|
|
||||||
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph asset:roles[ ]
|
|
||||||
style asset:roles fill:#dd4901,stroke:white
|
|
||||||
|
|
||||||
role:asset:OWNER[[asset:OWNER]]
|
|
||||||
role:asset:ADMIN[[asset:ADMIN]]
|
|
||||||
role:asset:TENANT[[asset:TENANT]]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph asset:permissions[ ]
|
|
||||||
style asset:permissions fill:#dd4901,stroke:white
|
|
||||||
|
|
||||||
perm:asset:INSERT{{asset:INSERT}}
|
|
||||||
perm:asset:DELETE{{asset:DELETE}}
|
|
||||||
perm:asset:UPDATE{{asset:UPDATE}}
|
|
||||||
perm:asset:SELECT{{asset:SELECT}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph bookingItem["`**bookingItem**`"]
|
|
||||||
direction TB
|
|
||||||
style bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph bookingItem:roles[ ]
|
|
||||||
style bookingItem:roles fill:#99bcdb,stroke:white
|
|
||||||
|
|
||||||
role:bookingItem:OWNER[[bookingItem:OWNER]]
|
|
||||||
role:bookingItem:ADMIN[[bookingItem:ADMIN]]
|
|
||||||
role:bookingItem:AGENT[[bookingItem:AGENT]]
|
|
||||||
role:bookingItem:TENANT[[bookingItem:TENANT]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph parentServer["`**parentServer**`"]
|
|
||||||
direction TB
|
|
||||||
style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
|
||||||
|
|
||||||
subgraph parentServer:roles[ ]
|
|
||||||
style parentServer:roles fill:#99bcdb,stroke:white
|
|
||||||
|
|
||||||
role:parentServer:ADMIN[[parentServer:ADMIN]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
%% granting roles to roles
|
|
||||||
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
|
|
||||||
role:bookingItem:ADMIN -.-> role:bookingItem:AGENT
|
|
||||||
role:bookingItem:AGENT -.-> role:bookingItem:TENANT
|
|
||||||
role:bookingItem:ADMIN ==> role:asset:OWNER
|
|
||||||
role:asset:OWNER ==> role:asset:ADMIN
|
|
||||||
role:asset:ADMIN ==> role:asset:TENANT
|
|
||||||
role:asset:TENANT ==> role:bookingItem:TENANT
|
|
||||||
|
|
||||||
%% granting permissions to roles
|
|
||||||
role:bookingItem:AGENT ==> perm:asset:INSERT
|
|
||||||
role:parentServer:ADMIN ==> perm:asset:INSERT
|
|
||||||
role:asset:OWNER ==> perm:asset:DELETE
|
|
||||||
role:asset:ADMIN ==> perm:asset:UPDATE
|
|
||||||
role:asset:TENANT ==> perm:asset:SELECT
|
|
||||||
role:global:ADMIN ==> perm:asset:INSERT
|
|
||||||
|
|
||||||
```
|
|
@ -6,6 +6,19 @@ This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manua
|
|||||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||||
flowchart TB
|
flowchart TB
|
||||||
|
|
||||||
|
subgraph alarmContact["`**alarmContact**`"]
|
||||||
|
direction TB
|
||||||
|
style alarmContact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
|
subgraph alarmContact:roles[ ]
|
||||||
|
style alarmContact:roles fill:#99bcdb,stroke:white
|
||||||
|
|
||||||
|
role:alarmContact:OWNER[[alarmContact:OWNER]]
|
||||||
|
role:alarmContact:ADMIN[[alarmContact:ADMIN]]
|
||||||
|
role:alarmContact:REFERRER[[alarmContact:REFERRER]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
subgraph asset["`**asset**`"]
|
subgraph asset["`**asset**`"]
|
||||||
direction TB
|
direction TB
|
||||||
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
style asset fill:#dd4901,stroke:#274d6e,stroke-width:8px
|
||||||
@ -25,6 +38,7 @@ subgraph asset["`**asset**`"]
|
|||||||
perm:asset:INSERT{{asset:INSERT}}
|
perm:asset:INSERT{{asset:INSERT}}
|
||||||
perm:asset:DELETE{{asset:DELETE}}
|
perm:asset:DELETE{{asset:DELETE}}
|
||||||
perm:asset:UPDATE{{asset:UPDATE}}
|
perm:asset:UPDATE{{asset:UPDATE}}
|
||||||
|
perm:asset:SELECT{{asset:SELECT}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -39,16 +53,58 @@ subgraph assignedToAsset["`**assignedToAsset**`"]
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
subgraph bookingItem["`**bookingItem**`"]
|
||||||
|
direction TB
|
||||||
|
style bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
|
subgraph bookingItem:roles[ ]
|
||||||
|
style bookingItem:roles fill:#99bcdb,stroke:white
|
||||||
|
|
||||||
|
role:bookingItem:OWNER[[bookingItem:OWNER]]
|
||||||
|
role:bookingItem:ADMIN[[bookingItem:ADMIN]]
|
||||||
|
role:bookingItem:AGENT[[bookingItem:AGENT]]
|
||||||
|
role:bookingItem:TENANT[[bookingItem:TENANT]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph parentAsset["`**parentAsset**`"]
|
||||||
|
direction TB
|
||||||
|
style parentAsset fill:#99bcdb,stroke:#274d6e,stroke-width:8px
|
||||||
|
|
||||||
|
subgraph parentAsset:roles[ ]
|
||||||
|
style parentAsset:roles fill:#99bcdb,stroke:white
|
||||||
|
|
||||||
|
role:parentAsset:ADMIN[[parentAsset:ADMIN]]
|
||||||
|
role:parentAsset:AGENT[[parentAsset:AGENT]]
|
||||||
|
role:parentAsset:TENANT[[parentAsset:TENANT]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
%% granting roles to roles
|
%% granting roles to roles
|
||||||
|
role:bookingItem:OWNER -.-> role:bookingItem:ADMIN
|
||||||
|
role:bookingItem:ADMIN -.-> role:bookingItem:AGENT
|
||||||
|
role:bookingItem:AGENT -.-> role:bookingItem:TENANT
|
||||||
|
role:global:ADMIN -.-> role:alarmContact:OWNER
|
||||||
|
role:alarmContact:OWNER -.-> role:alarmContact:ADMIN
|
||||||
|
role:alarmContact:ADMIN -.-> role:alarmContact:REFERRER
|
||||||
|
role:bookingItem:ADMIN ==> role:asset:OWNER
|
||||||
|
role:parentAsset:ADMIN ==> role:asset:OWNER
|
||||||
role:asset:OWNER ==> role:asset:ADMIN
|
role:asset:OWNER ==> role:asset:ADMIN
|
||||||
|
role:bookingItem:AGENT ==> role:asset:ADMIN
|
||||||
|
role:parentAsset:AGENT ==> role:asset:ADMIN
|
||||||
role:asset:ADMIN ==> role:asset:AGENT
|
role:asset:ADMIN ==> role:asset:AGENT
|
||||||
role:asset:AGENT ==> role:assignedToAsset:TENANT
|
role:asset:AGENT ==> role:assignedToAsset:TENANT
|
||||||
|
role:asset:AGENT ==> role:alarmContact:REFERRER
|
||||||
role:asset:AGENT ==> role:asset:TENANT
|
role:asset:AGENT ==> role:asset:TENANT
|
||||||
role:assignedToAsset:TENANT ==> role:asset:TENANT
|
role:asset:TENANT ==> role:bookingItem:TENANT
|
||||||
|
role:asset:TENANT ==> role:parentAsset:TENANT
|
||||||
|
role:alarmContact:ADMIN ==> role:asset:TENANT
|
||||||
|
|
||||||
%% granting permissions to roles
|
%% granting permissions to roles
|
||||||
role:global:ADMIN ==> perm:asset:INSERT
|
role:global:ADMIN ==> perm:asset:INSERT
|
||||||
|
role:parentAsset:ADMIN ==> perm:asset:INSERT
|
||||||
role:asset:OWNER ==> perm:asset:DELETE
|
role:asset:OWNER ==> perm:asset:DELETE
|
||||||
role:asset:ADMIN ==> perm:asset:UPDATE
|
role:asset:ADMIN ==> perm:asset:UPDATE
|
||||||
|
role:asset:TENANT ==> perm:asset:SELECT
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -32,6 +32,7 @@ create or replace procedure buildRbacSystemForHsHostingAsset(
|
|||||||
declare
|
declare
|
||||||
newBookingItem hs_booking_item;
|
newBookingItem hs_booking_item;
|
||||||
newAssignedToAsset hs_hosting_asset;
|
newAssignedToAsset hs_hosting_asset;
|
||||||
|
newAlarmContact hs_office_contact;
|
||||||
newParentAsset hs_hosting_asset;
|
newParentAsset hs_hosting_asset;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -41,6 +42,8 @@ begin
|
|||||||
|
|
||||||
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.assignedToAssetUuid INTO newAssignedToAsset;
|
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.assignedToAssetUuid INTO newAssignedToAsset;
|
||||||
|
|
||||||
|
SELECT * FROM hs_office_contact WHERE uuid = NEW.alarmContactUuid INTO newAlarmContact;
|
||||||
|
|
||||||
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.parentAssetUuid INTO newParentAsset;
|
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.parentAssetUuid INTO newParentAsset;
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
@ -63,14 +66,17 @@ begin
|
|||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsHostingAssetAGENT(NEW),
|
hsHostingAssetAGENT(NEW),
|
||||||
incomingSuperRoles => array[hsHostingAssetADMIN(NEW)],
|
incomingSuperRoles => array[hsHostingAssetADMIN(NEW)],
|
||||||
outgoingSubRoles => array[hsHostingAssetTENANT(newAssignedToAsset)]
|
outgoingSubRoles => array[
|
||||||
|
hsHostingAssetTENANT(newAssignedToAsset),
|
||||||
|
hsOfficeContactREFERRER(newAlarmContact)]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
hsHostingAssetTENANT(NEW),
|
hsHostingAssetTENANT(NEW),
|
||||||
|
permissions => array['SELECT'],
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsHostingAssetAGENT(NEW),
|
hsHostingAssetAGENT(NEW),
|
||||||
hsHostingAssetTENANT(newAssignedToAsset)],
|
hsOfficeContactADMIN(newAlarmContact)],
|
||||||
outgoingSubRoles => array[
|
outgoingSubRoles => array[
|
||||||
hsBookingItemTENANT(newBookingItem),
|
hsBookingItemTENANT(newBookingItem),
|
||||||
hsHostingAssetTENANT(newParentAsset)]
|
hsHostingAssetTENANT(newParentAsset)]
|
||||||
@ -99,6 +105,48 @@ execute procedure insertTriggerForHsHostingAsset_tf();
|
|||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs-hosting-asset-rbac-update-trigger:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
create or replace procedure updateRbacRulesForHsHostingAsset(
|
||||||
|
OLD hs_hosting_asset,
|
||||||
|
NEW hs_hosting_asset
|
||||||
|
)
|
||||||
|
language plpgsql as $$
|
||||||
|
begin
|
||||||
|
|
||||||
|
if NEW.assignedToAssetUuid is distinct from OLD.assignedToAssetUuid
|
||||||
|
or NEW.alarmContactUuid is distinct from OLD.alarmContactUuid then
|
||||||
|
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
|
||||||
|
call buildRbacSystemForHsHostingAsset(NEW);
|
||||||
|
end if;
|
||||||
|
end; $$;
|
||||||
|
|
||||||
|
/*
|
||||||
|
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_hosting_asset row.
|
||||||
|
*/
|
||||||
|
|
||||||
|
create or replace function updateTriggerForHsHostingAsset_tf()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql
|
||||||
|
strict as $$
|
||||||
|
begin
|
||||||
|
call updateRbacRulesForHsHostingAsset(OLD, NEW);
|
||||||
|
return NEW;
|
||||||
|
end; $$;
|
||||||
|
|
||||||
|
create trigger updateTriggerForHsHostingAsset_tg
|
||||||
|
after update on hs_hosting_asset
|
||||||
|
for each row
|
||||||
|
execute procedure updateTriggerForHsHostingAsset_tf();
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-hosting-asset-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
--changeset hs-hosting-asset-rbac-GRANTING-INSERT-PERMISSION:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
@ -146,49 +194,6 @@ create trigger z_new_hs_hosting_asset_grants_insert_to_global_tg
|
|||||||
for each row
|
for each row
|
||||||
execute procedure new_hs_hosting_asset_grants_insert_to_global_tf();
|
execute procedure new_hs_hosting_asset_grants_insert_to_global_tf();
|
||||||
|
|
||||||
-- granting INSERT permission to hs_booking_item ----------------------------
|
|
||||||
|
|
||||||
/*
|
|
||||||
Grants INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_booking_item rows.
|
|
||||||
*/
|
|
||||||
do language plpgsql $$
|
|
||||||
declare
|
|
||||||
row hs_booking_item;
|
|
||||||
begin
|
|
||||||
call defineContext('create INSERT INTO hs_hosting_asset permissions for pre-exising hs_booking_item rows');
|
|
||||||
|
|
||||||
FOR row IN SELECT * FROM hs_booking_item
|
|
||||||
-- unconditional for all rows in that table
|
|
||||||
LOOP
|
|
||||||
call grantPermissionToRole(
|
|
||||||
createPermission(row.uuid, 'INSERT', 'hs_hosting_asset'),
|
|
||||||
hsBookingItemAGENT(row));
|
|
||||||
END LOOP;
|
|
||||||
end;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Grants hs_hosting_asset INSERT permission to specified role of new hs_booking_item rows.
|
|
||||||
*/
|
|
||||||
create or replace function new_hs_hosting_asset_grants_insert_to_hs_booking_item_tf()
|
|
||||||
returns trigger
|
|
||||||
language plpgsql
|
|
||||||
strict as $$
|
|
||||||
begin
|
|
||||||
-- unconditional for all rows in that table
|
|
||||||
call grantPermissionToRole(
|
|
||||||
createPermission(NEW.uuid, 'INSERT', 'hs_hosting_asset'),
|
|
||||||
hsBookingItemAGENT(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_hs_hosting_asset_grants_insert_to_hs_booking_item_tg
|
|
||||||
after insert on hs_booking_item
|
|
||||||
for each row
|
|
||||||
execute procedure new_hs_hosting_asset_grants_insert_to_hs_booking_item_tf();
|
|
||||||
|
|
||||||
-- granting INSERT permission to hs_hosting_asset ----------------------------
|
-- granting INSERT permission to hs_hosting_asset ----------------------------
|
||||||
|
|
||||||
-- Granting INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_hosting_asset rows slipped,
|
-- Granting INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_hosting_asset rows slipped,
|
||||||
@ -234,10 +239,6 @@ begin
|
|||||||
if isGlobalAdmin() then
|
if isGlobalAdmin() then
|
||||||
return NEW;
|
return NEW;
|
||||||
end if;
|
end if;
|
||||||
-- check INSERT permission via direct foreign key: NEW.bookingItemUuid
|
|
||||||
if hasInsertPermission(NEW.bookingItemUuid, 'hs_hosting_asset') then
|
|
||||||
return NEW;
|
|
||||||
end if;
|
|
||||||
-- check INSERT permission via direct foreign key: NEW.parentAssetUuid
|
-- check INSERT permission via direct foreign key: NEW.parentAssetUuid
|
||||||
if hasInsertPermission(NEW.parentAssetUuid, 'hs_hosting_asset') then
|
if hasInsertPermission(NEW.parentAssetUuid, 'hs_hosting_asset') then
|
||||||
return NEW;
|
return NEW;
|
||||||
@ -275,7 +276,9 @@ call generateRbacRestrictedView('hs_hosting_asset',
|
|||||||
$updates$
|
$updates$
|
||||||
version = new.version,
|
version = new.version,
|
||||||
caption = new.caption,
|
caption = new.caption,
|
||||||
config = new.config
|
config = new.config,
|
||||||
|
assignedToAssetUuid = new.assignedToAssetUuid,
|
||||||
|
alarmContactUuid = new.alarmContactUuid
|
||||||
$updates$);
|
$updates$);
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -150,7 +150,8 @@ public class ArchitectureTest {
|
|||||||
.should().onlyBeAccessed().byClassesThat()
|
.should().onlyBeAccessed().byClassesThat()
|
||||||
.resideInAnyPackage(
|
.resideInAnyPackage(
|
||||||
"..hs.booking.(*)..",
|
"..hs.booking.(*)..",
|
||||||
"..hs.hosting.(*).."
|
"..hs.hosting.(*)..",
|
||||||
|
"..hs.validation" // TODO.impl: Some Validators need to be refactored to booking package.
|
||||||
);
|
);
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@ -195,7 +196,9 @@ public class ArchitectureTest {
|
|||||||
"..hs.office.partner..",
|
"..hs.office.partner..",
|
||||||
"..hs.office.debitor..",
|
"..hs.office.debitor..",
|
||||||
"..hs.office.membership..",
|
"..hs.office.membership..",
|
||||||
"..hs.office.migration..");
|
"..hs.office.migration..",
|
||||||
|
"..hs.hosting.asset.."
|
||||||
|
);
|
||||||
|
|
||||||
@ArchTest
|
@ArchTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@ -97,9 +97,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
|
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
|
||||||
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream()
|
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll());
|
||||||
.map(s -> s.replace("hs_office_", ""))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
attempt(em, () -> {
|
attempt(em, () -> {
|
||||||
@ -124,7 +122,6 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
"hs_booking_item#somenewbookingitem:OWNER",
|
"hs_booking_item#somenewbookingitem:OWNER",
|
||||||
"hs_booking_item#somenewbookingitem:TENANT"));
|
"hs_booking_item#somenewbookingitem:TENANT"));
|
||||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
||||||
.map(s -> s.replace("hs_office_", ""))
|
|
||||||
.containsExactlyInAnyOrder(fromFormatted(
|
.containsExactlyInAnyOrder(fromFormatted(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
|
|
||||||
@ -138,7 +135,6 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
// admin
|
// admin
|
||||||
"{ grant perm:hs_booking_item#somenewbookingitem:UPDATE to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
|
"{ grant perm:hs_booking_item#somenewbookingitem:UPDATE to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
|
||||||
"{ grant role:hs_booking_item#somenewbookingitem:ADMIN to role:hs_booking_item#somenewbookingitem:OWNER by system and assume }",
|
"{ grant role:hs_booking_item#somenewbookingitem:ADMIN to role:hs_booking_item#somenewbookingitem:OWNER by system and assume }",
|
||||||
"{ grant perm:hs_booking_item#somenewbookingitem:INSERT>hs_hosting_asset to role:hs_booking_item#somenewbookingitem:AGENT by system and assume }",
|
|
||||||
|
|
||||||
// agent
|
// agent
|
||||||
"{ grant role:hs_booking_item#somenewbookingitem:AGENT to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
|
"{ grant role:hs_booking_item#somenewbookingitem:AGENT to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
|
||||||
|
@ -7,6 +7,8 @@ import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
|||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||||
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||||
@ -54,6 +56,9 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeDebitorRepository debitorRepo;
|
HsOfficeDebitorRepository debitorRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
HsOfficeContactRepository contactRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
JpaAttempt jpaAttempt;
|
JpaAttempt jpaAttempt;
|
||||||
|
|
||||||
@ -425,6 +430,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
|
|
||||||
final var givenAsset = givenSomeTemporaryHostingAsset("2001", MANAGED_SERVER,
|
final var givenAsset = givenSomeTemporaryHostingAsset("2001", MANAGED_SERVER,
|
||||||
config("monit_max_ssd_usage", 80), config("monit_max_hdd_usage", 90), config("monit_max_cpu_usage", 90), config("monit_max_ram_usage", 70));
|
config("monit_max_ssd_usage", 80), config("monit_max_hdd_usage", 90), config("monit_max_cpu_usage", 90), config("monit_max_ram_usage", 70));
|
||||||
|
final var alarmContactUuid = givenContact().getUuid();
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -432,13 +438,14 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
|
"alarmContactUuid": "%s",
|
||||||
"config": {
|
"config": {
|
||||||
"monit_max_ssd_usage": 85,
|
"monit_max_ssd_usage": 85,
|
||||||
"monit_max_hdd_usage": null,
|
"monit_max_hdd_usage": null,
|
||||||
"monit_min_free_ssd": 5
|
"monit_min_free_ssd": 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""")
|
""".formatted(alarmContactUuid))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.patch("http://localhost/api/hs/hosting/assets/" + givenAsset.getUuid())
|
.patch("http://localhost/api/hs/hosting/assets/" + givenAsset.getUuid())
|
||||||
@ -450,6 +457,11 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"identifier": "vm2001",
|
"identifier": "vm2001",
|
||||||
"caption": "some test-asset",
|
"caption": "some test-asset",
|
||||||
|
"alarmContact": {
|
||||||
|
"uuid": "%s",
|
||||||
|
"caption": "second contact",
|
||||||
|
"emailAddresses": { "main": "contact-admin@secondcontact.example.com" }
|
||||||
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"monit_max_cpu_usage": 90,
|
"monit_max_cpu_usage": 90,
|
||||||
"monit_max_ram_usage": 70,
|
"monit_max_ram_usage": 70,
|
||||||
@ -457,12 +469,15 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"monit_min_free_ssd": 5
|
"monit_min_free_ssd": 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""".formatted(alarmContactUuid)));
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
// finally, the asset is actually updated
|
// finally, the asset is actually updated
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent().get()
|
assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent().get()
|
||||||
.matches(asset -> {
|
.matches(asset -> {
|
||||||
|
assertThat(asset.getAlarmContact().toString()).isEqualTo(
|
||||||
|
"contact(caption='second contact', emailAddresses='{ main: contact-admin@secondcontact.example.com }')");
|
||||||
assertThat(asset.getConfig().toString()).isEqualTo(
|
assertThat(asset.getConfig().toString()).isEqualTo(
|
||||||
"{ monit_max_cpu_usage: 90, monit_max_ram_usage: 70, monit_max_ssd_usage: 85, monit_min_free_ssd: 5 }");
|
"{ monit_max_cpu_usage: 90, monit_max_ram_usage: 70, monit_max_ssd_usage: 85, monit_min_free_ssd: 5 }");
|
||||||
return true;
|
return true;
|
||||||
@ -470,6 +485,13 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HsOfficeContactEntity givenContact() {
|
||||||
|
return jpaAttempt.transacted(() -> {
|
||||||
|
context.define("superuser-alex@hostsharing.net");
|
||||||
|
return contactRepo.findContactByOptionalCaptionLike("second").stream().findFirst().orElseThrow();
|
||||||
|
}).returnedValue();
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Order(5)
|
@Order(5)
|
||||||
class DeleteAsset {
|
class DeleteAsset {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.hs.hosting.asset;
|
package net.hostsharing.hsadminng.hs.hosting.asset;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource;
|
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.mapper.KeyValueMap;
|
import net.hostsharing.hsadminng.mapper.KeyValueMap;
|
||||||
import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
|
import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -31,6 +31,7 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
> {
|
> {
|
||||||
|
|
||||||
private static final UUID INITIAL_BOOKING_ITEM_UUID = UUID.randomUUID();
|
private static final UUID INITIAL_BOOKING_ITEM_UUID = UUID.randomUUID();
|
||||||
|
private static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
private static final Map<String, Object> INITIAL_CONFIG = patchMap(
|
private static final Map<String, Object> INITIAL_CONFIG = patchMap(
|
||||||
entry("CPU", 1),
|
entry("CPU", 1),
|
||||||
@ -47,6 +48,9 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
entry("SSD", 256),
|
entry("SSD", 256),
|
||||||
entry("MEM", 64)
|
entry("MEM", 64)
|
||||||
);
|
);
|
||||||
|
final HsOfficeContactEntity givenInitialContact = HsOfficeContactEntity.builder()
|
||||||
|
.uuid(UUID.randomUUID())
|
||||||
|
.build();
|
||||||
|
|
||||||
private static final String INITIAL_CAPTION = "initial caption";
|
private static final String INITIAL_CAPTION = "initial caption";
|
||||||
private static final String PATCHED_CAPTION = "patched caption";
|
private static final String PATCHED_CAPTION = "patched caption";
|
||||||
@ -56,10 +60,10 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void initMocks() {
|
void initMocks() {
|
||||||
lenient().when(em.getReference(eq(HsOfficeDebitorEntity.class), any())).thenAnswer(invocation ->
|
|
||||||
HsOfficeDebitorEntity.builder().uuid(invocation.getArgument(1)).build());
|
|
||||||
lenient().when(em.getReference(eq(HsHostingAssetEntity.class), any())).thenAnswer(invocation ->
|
lenient().when(em.getReference(eq(HsHostingAssetEntity.class), any())).thenAnswer(invocation ->
|
||||||
HsHostingAssetEntity.builder().uuid(invocation.getArgument(1)).build());
|
HsHostingAssetEntity.builder().uuid(invocation.getArgument(1)).build());
|
||||||
|
lenient().when(em.getReference(eq(HsOfficeContactEntity.class), any())).thenAnswer(invocation ->
|
||||||
|
HsOfficeContactEntity.builder().uuid(invocation.getArgument(1)).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,6 +73,7 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
entity.setBookingItem(TEST_BOOKING_ITEM);
|
entity.setBookingItem(TEST_BOOKING_ITEM);
|
||||||
entity.getConfig().putAll(KeyValueMap.from(INITIAL_CONFIG));
|
entity.getConfig().putAll(KeyValueMap.from(INITIAL_CONFIG));
|
||||||
entity.setCaption(INITIAL_CAPTION);
|
entity.setCaption(INITIAL_CAPTION);
|
||||||
|
entity.setAlarmContact(givenInitialContact);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +84,7 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HsHostingAssetEntityPatcher createPatcher(final HsHostingAssetEntity server) {
|
protected HsHostingAssetEntityPatcher createPatcher(final HsHostingAssetEntity server) {
|
||||||
return new HsHostingAssetEntityPatcher(server);
|
return new HsHostingAssetEntityPatcher(em, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -96,7 +101,17 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
PATCH_CONFIG,
|
PATCH_CONFIG,
|
||||||
HsHostingAssetEntity::putConfig,
|
HsHostingAssetEntity::putConfig,
|
||||||
PATCHED_CONFIG)
|
PATCHED_CONFIG)
|
||||||
.notNullable()
|
.notNullable(),
|
||||||
|
new JsonNullableProperty<>(
|
||||||
|
"alarmContact",
|
||||||
|
HsHostingAssetPatchResource::setAlarmContactUuid,
|
||||||
|
PATCHED_CONTACT_UUID,
|
||||||
|
HsHostingAssetEntity::setAlarmContact,
|
||||||
|
newContact(PATCHED_CONTACT_UUID))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HsOfficeContactEntity newContact(final UUID uuid) {
|
||||||
|
return HsOfficeContactEntity.builder().uuid(uuid).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
"{ grant role:hs_booking_item#fir01:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
"{ grant role:hs_booking_item#fir01:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
||||||
"{ grant role:hs_hosting_asset#fir00:TENANT to role:hs_hosting_asset#fir00:AGENT by system and assume }",
|
"{ grant role:hs_hosting_asset#fir00:TENANT to role:hs_hosting_asset#fir00:AGENT by system and assume }",
|
||||||
"{ grant role:hs_hosting_asset#vm1011:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
"{ grant role:hs_hosting_asset#vm1011:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
||||||
|
"{ grant perm:hs_hosting_asset#fir00:SELECT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
||||||
|
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user