From 9d8592c16bc9d543fcc25b35402586e6d37882df Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 19 Apr 2024 09:47:04 +0200 Subject: [PATCH] working version with HsHostingAsset + type --- .../HsHostingAssetController.java} | 57 +-- .../HsHostingAssetEntity.java} | 75 ++- .../HsHostingAssetEntityPatcher.java} | 12 +- .../asset/HsHostingAssetRepository.java | 26 + .../hs/hosting/asset/HsHostingAssetType.java | 28 ++ .../server/HsHostingServerRepository.java | 26 - .../hs-hosting/api-mappings.yaml | 2 +- ...mas.yaml => hs-hosting-asset-schemas.yaml} | 46 +- ....yaml => hs-hosting-assets-with-uuid.yaml} | 34 +- ...ng-servers.yaml => hs-hosting-assets.yaml} | 24 +- .../api-definition/hs-hosting/hs-hosting.yaml | 8 +- .../7010-hs-hosting-asset.sql | 42 ++ ...7013-hs-hosting-asset-rbac-CLOUD_SERVER.md | 462 +++++++++++++++++ ...13-hs-hosting-asset-rbac-MANAGED_SERVER.md | 462 +++++++++++++++++ ...-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md | 468 ++++++++++++++++++ .../7013-hs-hosting-asset-rbac.sql} | 92 ++-- .../7018-hs-hosting-asset-test-data.sql} | 29 +- .../7010-hs-hosting-server.sql | 23 - .../7013-hs-hosting-server-rbac.md | 305 ------------ .../db/changelog/db.changelog-master.yaml | 6 +- .../hsadminng/arch/ArchitectureTest.java | 2 +- ...HostingAssetControllerAcceptanceTest.java} | 123 +++-- .../HsHostingAssetEntityPatcherUnitTest.java} | 34 +- .../asset/HsHostingAssetEntityUnitTest.java | 49 ++ ...ostingAssetRepositoryIntegrationTest.java} | 173 +++---- .../server/HsHostingServerEntityUnitTest.java | 36 -- .../hs/office/migration/ImportOfficeData.java | 2 +- 27 files changed, 1946 insertions(+), 700 deletions(-) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/{server/HsHostingServerController.java => asset/HsHostingAssetController.java} (60%) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/{server/HsHostingServerEntity.java => asset/HsHostingAssetEntity.java} (58%) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/{server/HsHostingServerEntityPatcher.java => asset/HsHostingAssetEntityPatcher.java} (60%) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepository.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepository.java rename src/main/resources/api-definition/hs-hosting/{hs-hosting-server-schemas.yaml => hs-hosting-asset-schemas.yaml} (54%) rename src/main/resources/api-definition/hs-hosting/{hs-hosting-servers-with-uuid.yaml => hs-hosting-assets-with-uuid.yaml} (67%) rename src/main/resources/api-definition/hs-hosting/{hs-hosting-servers.yaml => hs-hosting-assets.yaml} (62%) create mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql create mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md create mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md create mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md rename src/main/resources/db/changelog/7-hs-hosting/{701-hosting-server/7013-hs-hosting-server-rbac.sql => 701-hosting-asset/7013-hs-hosting-asset-rbac.sql} (56%) rename src/main/resources/db/changelog/7-hs-hosting/{701-hosting-server/7018-hs-hosting-server-test-data.sql => 701-hosting-asset/7018-hs-hosting-asset-test-data.sql} (51%) delete mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7010-hs-hosting-server.sql delete mode 100644 src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.md rename src/test/java/net/hostsharing/hsadminng/hs/hosting/{server/HsHostingServerControllerAcceptanceTest.java => asset/HsHostingAssetControllerAcceptanceTest.java} (72%) rename src/test/java/net/hostsharing/hsadminng/hs/hosting/{server/HsHostingServerEntityPatcherUnitTest.java => asset/HsHostingAssetEntityPatcherUnitTest.java} (73%) create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java rename src/test/java/net/hostsharing/hsadminng/hs/hosting/{server/HsHostingServerRepositoryIntegrationTest.java => asset/HsHostingAssetRepositoryIntegrationTest.java} (56%) delete mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java similarity index 60% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerController.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java index 85ce8d4b..78606936 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java @@ -1,11 +1,11 @@ -package net.hostsharing.hsadminng.hs.hosting.server; +package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingServersApi; +import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetsApi; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsServerInsertResource; -import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsServerPatchResource; -import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsServerResource; +import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetInsertResource; +import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource; +import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetResource; import net.hostsharing.hsadminng.mapper.KeyValueMap; import net.hostsharing.hsadminng.mapper.Mapper; import org.springframework.beans.factory.annotation.Autowired; @@ -18,8 +18,9 @@ import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; + @RestController -public class HsHostingServerController implements HsHostingServersApi { +public class HsHostingAssetController implements HsHostingAssetsApi { @Autowired private Context context; @@ -28,70 +29,70 @@ public class HsHostingServerController implements HsHostingServersApi { private Mapper mapper; @Autowired - private HsHostingServerRepository serverRepo; + private HsHostingAssetRepository assetRepo; @Override @Transactional(readOnly = true) - public ResponseEntity> listServersByDebitorUuid( + public ResponseEntity> listAssetsByDebitorUuid( final String currentUser, final String assumedRoles, final UUID debitorUuid) { context.define(currentUser, assumedRoles); - final var entities = serverRepo.findAllByDebitorUuid(debitorUuid); + final var entities = assetRepo.findAllByDebitorUuid(debitorUuid); - final var resources = mapper.mapList(entities, HsServerResource.class); + final var resources = mapper.mapList(entities, HsHostingAssetResource.class); return ResponseEntity.ok(resources); } @Override @Transactional - public ResponseEntity addServer( + public ResponseEntity addAsset( final String currentUser, final String assumedRoles, - final HsServerInsertResource body) { + final HsHostingAssetInsertResource body) { context.define(currentUser, assumedRoles); - final var entityToSave = mapper.map(body, HsHostingServerEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); + final var entityToSave = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); - final var saved = serverRepo.save(entityToSave); + final var saved = assetRepo.save(entityToSave); final var uri = MvcUriComponentsBuilder.fromController(getClass()) - .path("/api/hs/hosting/servers/{id}") + .path("/api/hs/hosting/assets/{id}") .buildAndExpand(saved.getUuid()) .toUri(); - final var mapped = mapper.map(saved, HsServerResource.class); + final var mapped = mapper.map(saved, HsHostingAssetResource.class); return ResponseEntity.created(uri).body(mapped); } @Override @Transactional(readOnly = true) - public ResponseEntity getServerByUuid( + public ResponseEntity getAssetByUuid( final String currentUser, final String assumedRoles, final UUID serverUuid) { context.define(currentUser, assumedRoles); - final var result = serverRepo.findByUuid(serverUuid); + final var result = assetRepo.findByUuid(serverUuid); return result .map(serverEntity -> ResponseEntity.ok( - mapper.map(serverEntity, HsServerResource.class))) + mapper.map(serverEntity, HsHostingAssetResource.class))) .orElseGet(() -> ResponseEntity.notFound().build()); } @Override @Transactional - public ResponseEntity deleteServerUuid( + public ResponseEntity deleteAssetUuid( final String currentUser, final String assumedRoles, final UUID serverUuid) { context.define(currentUser, assumedRoles); - final var result = serverRepo.deleteByUuid(serverUuid); + final var result = assetRepo.deleteByUuid(serverUuid); return result == 0 ? ResponseEntity.notFound().build() : ResponseEntity.noContent().build(); @@ -99,25 +100,25 @@ public class HsHostingServerController implements HsHostingServersApi { @Override @Transactional - public ResponseEntity patchServer( + public ResponseEntity patchAsset( final String currentUser, final String assumedRoles, final UUID serverUuid, - final HsServerPatchResource body) { + final HsHostingAssetPatchResource body) { context.define(currentUser, assumedRoles); - final var current = serverRepo.findByUuid(serverUuid).orElseThrow(); + final var current = assetRepo.findByUuid(serverUuid).orElseThrow(); - new HsHostingServerEntityPatcher(current).apply(body); + new HsHostingAssetEntityPatcher(current).apply(body); - final var saved = serverRepo.save(current); - final var mapped = mapper.map(saved, HsServerResource.class); + final var saved = assetRepo.save(current); + final var mapped = mapper.map(saved, HsHostingAssetResource.class); return ResponseEntity.ok(mapped); } @SuppressWarnings("unchecked") - final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { + final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { entity.putConfig(KeyValueMap.from(resource.getConfig())); }; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java similarity index 58% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntity.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java index f46b2f04..0d7678e9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java @@ -1,4 +1,4 @@ -package net.hostsharing.hsadminng.hs.hosting.server; +package net.hostsharing.hsadminng.hs.hosting.asset; import io.hypersistence.utils.hibernate.type.json.JsonType; import lombok.AccessLevel; @@ -18,6 +18,8 @@ import org.hibernate.annotations.Type; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; @@ -31,8 +33,15 @@ import java.util.Map; import java.util.UUID; import static java.util.Optional.ofNullable; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inCaseOf; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingCase; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NULLABLE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.DELETE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT; @@ -47,17 +56,20 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @Builder @Entity -@Table(name = "hs_hosting_server_rv") +@Table(name = "hs_hosting_asset_rv") @Getter @Setter @NoArgsConstructor @AllArgsConstructor -public class HsHostingServerEntity implements Stringifyable, RbacObject { +public class HsHostingAssetEntity implements Stringifyable, RbacObject { - private static Stringify stringify = stringify(HsHostingServerEntity.class) - .withProp(e -> e.getBookingItem().toShortString()) - .withProp(HsHostingServerEntity::getCaption) - .withProp(HsHostingServerEntity::getConfig) + private static Stringify stringify = stringify(HsHostingAssetEntity.class) + .withProp(HsHostingAssetEntity::getBookingItem) + .withProp(HsHostingAssetEntity::getType) + .withProp(HsHostingAssetEntity::getParentAsset) + .withProp(HsHostingAssetEntity::getIdentifier) + .withProp(HsHostingAssetEntity::getCaption) + .withProp(HsHostingAssetEntity::getConfig) .quotedValues(false); @Id @@ -71,6 +83,17 @@ public class HsHostingServerEntity implements Stringifyable, RbacObject { @JoinColumn(name = "bookingitemuuid") private HsBookingItemEntity bookingItem; + @ManyToOne(optional = true) + @JoinColumn(name = "parentassetuuid") + private HsHostingAssetEntity parentAsset; + + @Column(name = "type") + @Enumerated(EnumType.STRING) + private HsHostingAssetType type; + + @Column(name = "identifier") + private String identifier; // vm1234, xyz00, example.org, xyz00_abc + @Column(name = "caption") private String caption; @@ -105,24 +128,38 @@ public class HsHostingServerEntity implements Stringifyable, RbacObject { @Override public String toShortString() { return ofNullable(bookingItem).map(HsBookingItemEntity::toShortString).orElse("D-???????:?") + - ":" + caption; + ":" + identifier; } public static RbacView rbac() { - return rbacViewFor("server", HsHostingServerEntity.class) + return rbacViewFor("asset", HsHostingAssetEntity.class) .withIdentityView(SQL.query(""" - SELECT server.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(server.caption) as idName - FROM hs_hosting_server server - JOIN hs_booking_item_iv bookingItemIV ON bookingItemIV.uuid = server.bookingItemUuid + SELECT asset.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(asset.identifier) as idName + FROM hs_hosting_asset asset + JOIN hs_booking_item_iv bookingItemIV ON bookingItemIV.uuid = asset.bookingItemUuid """)) - .withRestrictedViewOrderBy(SQL.expression("caption")) + .withRestrictedViewOrderBy(SQL.expression("identifier")) .withUpdatableColumns("version", "caption", "config") - .importEntityAlias("bookingItem", HsBookingItemEntity.class, - dependsOnColumn("bookingItemUuid"), - directlyFetchedByDependsOnColumn(), - NOT_NULL) - .toRole("bookingItem", AGENT).grantPermission(INSERT) + .importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(), + dependsOnColumn("bookingItemUuid"), + directlyFetchedByDependsOnColumn(), + NOT_NULL) + + .switchOnColumn("type", + inCaseOf(CLOUD_SERVER.name(), + then -> then.toRole("bookingItem", AGENT).grantPermission(INSERT)), + inCaseOf(MANAGED_SERVER.name(), + then -> then.toRole("bookingItem", AGENT).grantPermission(INSERT)), + inCaseOf(MANAGED_WEBSPACE.name(), then -> + then.importEntityAlias("parentServer", HsHostingAssetEntity.class, usingCase(MANAGED_SERVER), + dependsOnColumn("parentAssetUuid"), + directlyFetchedByDependsOnColumn(), + NULLABLE) + // TODO.rbac: implement multiple INSERT-rules, e.g. for Asset.bookingItem + Asset.parentAsset + //.toRole("parentServer", AGENT).grantPermission(INSERT) + ) + ) .createRole(OWNER, (with) -> { with.incomingSuperRole("bookingItem", ADMIN); @@ -138,6 +175,6 @@ public class HsHostingServerEntity implements Stringifyable, RbacObject { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac"); + rbac().generateWithBaseFileName("7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityPatcher.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcher.java similarity index 60% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityPatcher.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcher.java index 19266950..a555be19 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityPatcher.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcher.java @@ -1,22 +1,22 @@ -package net.hostsharing.hsadminng.hs.hosting.server; +package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsServerPatchResource; +import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource; import net.hostsharing.hsadminng.mapper.EntityPatcher; import net.hostsharing.hsadminng.mapper.KeyValueMap; import net.hostsharing.hsadminng.mapper.OptionalFromJson; import java.util.Optional; -public class HsHostingServerEntityPatcher implements EntityPatcher { +public class HsHostingAssetEntityPatcher implements EntityPatcher { - private final HsHostingServerEntity entity; + private final HsHostingAssetEntity entity; - public HsHostingServerEntityPatcher(final HsHostingServerEntity entity) { + public HsHostingAssetEntityPatcher(final HsHostingAssetEntity entity) { this.entity = entity; } @Override - public void apply(final HsServerPatchResource resource) { + public void apply(final HsHostingAssetPatchResource resource) { OptionalFromJson.of(resource.getCaption()) .ifPresent(entity::setCaption); Optional.ofNullable(resource.getConfig()) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepository.java new file mode 100644 index 00000000..67808097 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepository.java @@ -0,0 +1,26 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface HsHostingAssetRepository extends Repository { + + List findAll(); + Optional findByUuid(final UUID serverUuid); + + @Query(""" + SELECT s FROM HsHostingAssetEntity s + WHERE s.bookingItem.debitor.uuid = :debitorUuid + """) + List findAllByDebitorUuid(final UUID debitorUuid); + + HsHostingAssetEntity save(HsHostingAssetEntity current); + + int deleteByUuid(final UUID uuid); + + long count(); +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java new file mode 100644 index 00000000..9e99a8c5 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java @@ -0,0 +1,28 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +public enum HsHostingAssetType { + CLOUD_SERVER, // named e.g. vm1234 + MANAGED_SERVER, // named e.g. vm1234 + MANAGED_WEBSPACE(MANAGED_SERVER), // named eg. xyz00 + UNIX_USER(MANAGED_WEBSPACE), // named e.g. xyz00-abc + DOMAIN_SETUP(UNIX_USER), // named e.g. example.org + + // TODO.spec: SECURE_MX + EMAIL_ALIAS(MANAGED_WEBSPACE), // named e.g. xyz00-abc + EMAIL_ADDRESS(DOMAIN_SETUP), // named e.g. sample@example.org + PGSQL_USER(MANAGED_WEBSPACE), // named e.g. xyz00_abc + PGSQL_DATABASE(MANAGED_WEBSPACE), // named e.g. xyz00_abc, TODO.spec: or PGSQL_USER? + MARIADB_USER(MANAGED_WEBSPACE), // named e.g. xyz00_abc + MARIADB_DATABASE(MANAGED_WEBSPACE); // named e.g. xyz00_abc, TODO.spec: or MARIADB_USER? + + + public final HsHostingAssetType parentAssetType; + + HsHostingAssetType(final HsHostingAssetType parentAssetType) { + this.parentAssetType = parentAssetType; + } + + HsHostingAssetType() { + this(null); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepository.java deleted file mode 100644 index ce53b584..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.hostsharing.hsadminng.hs.hosting.server; - -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.Repository; - -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -public interface HsHostingServerRepository extends Repository { - - List findAll(); - Optional findByUuid(final UUID serverUuid); - - @Query(""" - SELECT s FROM HsHostingServerEntity s - WHERE s.bookingItem.debitor.uuid = :debitorUuid - """) - List findAllByDebitorUuid(final UUID debitorUuid); - - HsHostingServerEntity save(HsHostingServerEntity current); - - int deleteByUuid(final UUID uuid); - - long count(); -} diff --git a/src/main/resources/api-definition/hs-hosting/api-mappings.yaml b/src/main/resources/api-definition/hs-hosting/api-mappings.yaml index 301899f0..93f3cfe6 100644 --- a/src/main/resources/api-definition/hs-hosting/api-mappings.yaml +++ b/src/main/resources/api-definition/hs-hosting/api-mappings.yaml @@ -13,5 +13,5 @@ map: - type: string:uuid => java.util.UUID paths: - /api/hs/hosting/servers/{serverUuid}: + /api/hs/hosting/assets/{assetUuid}: null: org.openapitools.jackson.nullable.JsonNullable diff --git a/src/main/resources/api-definition/hs-hosting/hs-hosting-server-schemas.yaml b/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml similarity index 54% rename from src/main/resources/api-definition/hs-hosting/hs-hosting-server-schemas.yaml rename to src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml index 20e5d19b..f3ecb6a3 100644 --- a/src/main/resources/api-definition/hs-hosting/hs-hosting-server-schemas.yaml +++ b/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml @@ -3,51 +3,81 @@ components: schemas: - HsServer: + HsHostingAssetType: + type: string + enum: + - CLOUD_SERVER + - MANAGED_SERVER + - MANAGED_WEBSPACE + - UNIX_USER + - DOMAIN_SETUP + - EMAIL_ALIAS + - EMAIL_ADDRESS + - PGSQL_USER + - PGSQL_DATABASE + - MARIADB_USER + - MARIADB_DATABASE + + HsHostingAsset: type: object properties: uuid: type: string format: uuid + type: + $ref: '#/components/schemas/HsHostingAssetType' + identifier: + type: string caption: type: string config: - $ref: '#/components/schemas/ServerConfiguration' + $ref: '#/components/schemas/HsHostingAssetConfiguration' required: + - type + - ídentifier - uuid - config - HsServerPatch: + HsHostingAssetPatch: type: object properties: caption: type: string nullable: true config: - $ref: '#/components/schemas/ServerConfiguration' + $ref: '#/components/schemas/HsHostingAssetConfiguration' - HsServerInsert: + HsHostingAssetInsert: type: object properties: bookingItemUuid: type: string format: uuid nullable: false + type: + $ref: '#/components/schemas/HsHostingAssetType' + identifier: + type: string + minLength: 3 + maxLength: 80 + nullable: false caption: type: string minLength: 3 maxLength: 80 nullable: false config: - $ref: '#/components/schemas/ServerConfiguration' + $ref: '#/components/schemas/HsHostingAssetConfiguration' required: + - type + - identifier - caption - debitorUuid - config additionalProperties: false - ServerConfiguration: - # forces generating a java.lang.Object containing a Map, instead of class ServerConfiguration + HsHostingAssetConfiguration: + # forces generating a java.lang.Object containing a Map, instead of class AssetConfiguration anyOf: - type: object properties: diff --git a/src/main/resources/api-definition/hs-hosting/hs-hosting-servers-with-uuid.yaml b/src/main/resources/api-definition/hs-hosting/hs-hosting-assets-with-uuid.yaml similarity index 67% rename from src/main/resources/api-definition/hs-hosting/hs-hosting-servers-with-uuid.yaml rename to src/main/resources/api-definition/hs-hosting/hs-hosting-assets-with-uuid.yaml index 91f280d6..6630d245 100644 --- a/src/main/resources/api-definition/hs-hosting/hs-hosting-servers-with-uuid.yaml +++ b/src/main/resources/api-definition/hs-hosting/hs-hosting-assets-with-uuid.yaml @@ -1,25 +1,25 @@ get: tags: - - hs-hosting-servers - description: 'Fetch a single managed server by its uuid, if visible for the current subject.' - operationId: getServerByUuid + - hs-hosting-assets + description: 'Fetch a single managed asset by its uuid, if visible for the current subject.' + operationId: getAssetByUuid parameters: - $ref: 'auth.yaml#/components/parameters/currentUser' - $ref: 'auth.yaml#/components/parameters/assumedRoles' - - name: serverUuid + - name: assetUuid in: path required: true schema: type: string format: uuid - description: UUID of the managed server to fetch. + description: UUID of the hosting asset to fetch. responses: "200": description: OK content: 'application/json': schema: - $ref: 'hs-hosting-server-schemas.yaml#/components/schemas/HsServer' + $ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAsset' "401": $ref: 'error-responses.yaml#/components/responses/Unauthorized' @@ -28,13 +28,13 @@ get: patch: tags: - - hs-hosting-servers - description: 'Updates a single managed server identified by its uuid, if permitted for the current subject.' - operationId: patchServer + - hs-hosting-assets + description: 'Updates a single hosting asset identified by its uuid, if permitted for the current subject.' + operationId: patchAsset parameters: - $ref: 'auth.yaml#/components/parameters/currentUser' - $ref: 'auth.yaml#/components/parameters/assumedRoles' - - name: serverUuid + - name: assetUuid in: path required: true schema: @@ -44,14 +44,14 @@ patch: content: 'application/json': schema: - $ref: 'hs-hosting-server-schemas.yaml#/components/schemas/HsServerPatch' + $ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAssetPatch' responses: "200": description: OK content: 'application/json': schema: - $ref: 'hs-hosting-server-schemas.yaml#/components/schemas/HsServer' + $ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAsset' "401": $ref: 'error-responses.yaml#/components/responses/Unauthorized' "403": @@ -59,19 +59,19 @@ patch: delete: tags: - - hs-hosting-servers - description: 'Delete a single managed server identified by its uuid, if permitted for the current subject.' - operationId: deleteServerUuid + - hs-hosting-assets + description: 'Delete a single hosting asset identified by its uuid, if permitted for the current subject.' + operationId: deleteAssetUuid parameters: - $ref: 'auth.yaml#/components/parameters/currentUser' - $ref: 'auth.yaml#/components/parameters/assumedRoles' - - name: serverUuid + - name: assetUuid in: path required: true schema: type: string format: uuid - description: UUID of the managed server to delete. + description: UUID of the hosting asset to delete. responses: "204": description: No Content diff --git a/src/main/resources/api-definition/hs-hosting/hs-hosting-servers.yaml b/src/main/resources/api-definition/hs-hosting/hs-hosting-assets.yaml similarity index 62% rename from src/main/resources/api-definition/hs-hosting/hs-hosting-servers.yaml rename to src/main/resources/api-definition/hs-hosting/hs-hosting-assets.yaml index f41e1ddd..d74766ed 100644 --- a/src/main/resources/api-definition/hs-hosting/hs-hosting-servers.yaml +++ b/src/main/resources/api-definition/hs-hosting/hs-hosting-assets.yaml @@ -1,9 +1,9 @@ get: - summary: Returns a list of all managed servers for a specified debitor. - description: Returns the list of all managed servers for a debitor which are visible to the current user or any of it's assumed roles. + summary: Returns a list of all hosting assets for a specified debitor. + description: Returns the list of all hosting assets for a debitor which are visible to the current user or any of it's assumed roles. tags: - - hs-hosting-servers - operationId: listServersByDebitorUuid + - hs-hosting-assets + operationId: listAssetsByDebitorUuid parameters: - $ref: 'auth.yaml#/components/parameters/currentUser' - $ref: 'auth.yaml#/components/parameters/assumedRoles' @@ -13,7 +13,7 @@ get: schema: type: string format: uuid - description: The UUID of the debitor, whose managed servers are to be listed. + description: The UUID of the debitor, whose hosting assets are to be listed. responses: "200": description: OK @@ -22,34 +22,34 @@ get: schema: type: array items: - $ref: 'hs-hosting-server-schemas.yaml#/components/schemas/HsServer' + $ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAsset' "401": $ref: 'error-responses.yaml#/components/responses/Unauthorized' "403": $ref: 'error-responses.yaml#/components/responses/Forbidden' post: - summary: Adds a new managed server. + summary: Adds a new hosting asset. tags: - - hs-hosting-servers - operationId: addServer + - hs-hosting-assets + operationId: addAsset parameters: - $ref: 'auth.yaml#/components/parameters/currentUser' - $ref: 'auth.yaml#/components/parameters/assumedRoles' requestBody: - description: A JSON object describing the new managed server. + description: A JSON object describing the new hosting asset. required: true content: application/json: schema: - $ref: 'hs-hosting-server-schemas.yaml#/components/schemas/HsServerInsert' + $ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAssetInsert' responses: "201": description: Created content: 'application/json': schema: - $ref: 'hs-hosting-server-schemas.yaml#/components/schemas/HsServer' + $ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAsset' "401": $ref: 'error-responses.yaml#/components/responses/Unauthorized' "403": diff --git a/src/main/resources/api-definition/hs-hosting/hs-hosting.yaml b/src/main/resources/api-definition/hs-hosting/hs-hosting.yaml index a88038b8..4f8f29d5 100644 --- a/src/main/resources/api-definition/hs-hosting/hs-hosting.yaml +++ b/src/main/resources/api-definition/hs-hosting/hs-hosting.yaml @@ -10,8 +10,8 @@ paths: # Items - /api/hs/hosting/servers: - $ref: "hs-hosting-servers.yaml" + /api/hs/hosting/assets: + $ref: "hs-hosting-assets.yaml" - /api/hs/hosting/servers/{serverUuid}: - $ref: "hs-hosting-servers-with-uuid.yaml" + /api/hs/hosting/assets/{assetUuid}: + $ref: "hs-hosting-assets-with-uuid.yaml" diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql new file mode 100644 index 00000000..b827eea8 --- /dev/null +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql @@ -0,0 +1,42 @@ +--liquibase formatted sql + +-- ============================================================================ +--changeset hosting-asset-MAIN-TABLE:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +create type HsHostingAssetType as enum ( + 'CLOUD_SERVER', + 'MANAGED_SERVER', + 'MANAGED_WEBSPACE', + 'UNIX_USER', + 'DOMAIN_SETUP', + 'EMAIL_ALIAS', + 'EMAIL_ADDRESS', + 'PGSQL_USER', + 'PGSQL_DATABASE', + 'MARIADB_USER', + 'MARIADB_DATABASE' +); + +CREATE CAST (character varying as HsHostingAssetType) WITH INOUT AS IMPLICIT; + +create table if not exists hs_hosting_asset +( + uuid uuid unique references RbacObject (uuid), + version int not null default 0, + bookingItemUuid uuid not null references hs_booking_item(uuid), + type HsHostingAssetType, + parentAssetUuid uuid null references hs_hosting_asset(uuid), + identifier varchar(80) not null, + caption varchar(80) not null, + config jsonb not null +); +--// + + +-- ============================================================================ +--changeset hs-hosting-asset-MAIN-TABLE-JOURNAL:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +call create_journal('hs_hosting_asset'); +--// diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md new file mode 100644 index 00000000..3bc75f3b --- /dev/null +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-CLOUD_SERVER.md @@ -0,0 +1,462 @@ +### rbac asset inCaseOf:CLOUD_SERVER + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph parentServer.bookingItem["`**parentServer.bookingItem**`"] + direction TB + style parentServer.bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem:roles[ ] + style parentServer.bookingItem:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem:OWNER[[parentServer.bookingItem:OWNER]] + role:parentServer.bookingItem:ADMIN[[parentServer.bookingItem:ADMIN]] + role:parentServer.bookingItem:AGENT[[parentServer.bookingItem:AGENT]] + role:parentServer.bookingItem:TENANT[[parentServer.bookingItem:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitorRel.anchorPerson["`**parentServer.bookingItem.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.holderPerson["`**parentServer.bookingItem.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer["`**parentServer**`"] + direction TB + style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson["`**parentServer.bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson["`**parentServer.bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel.anchorPerson["`**bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.anchorPerson:OWNER[[bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.contact["`**parentServer.bookingItem.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.contact:OWNER[[parentServer.bookingItem.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel["`**bookingItem.debitor.partnerRel**`"] + direction TB + style bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel:roles[ ] + style bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel:OWNER[[bookingItem.debitor.partnerRel:OWNER]] + role:bookingItem.debitor.partnerRel:ADMIN[[bookingItem.debitor.partnerRel:ADMIN]] + role:bookingItem.debitor.partnerRel:AGENT[[bookingItem.debitor.partnerRel:AGENT]] + role:bookingItem.debitor.partnerRel:TENANT[[bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.partnerRel.anchorPerson["`**bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.anchorPerson:OWNER[[bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel["`**bookingItem.debitorRel**`"] + direction TB + style bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel:roles[ ] + style bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel:OWNER[[bookingItem.debitorRel:OWNER]] + role:bookingItem.debitorRel:ADMIN[[bookingItem.debitorRel:ADMIN]] + role:bookingItem.debitorRel:AGENT[[bookingItem.debitorRel:AGENT]] + role:bookingItem.debitorRel:TENANT[[bookingItem.debitorRel:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.contact["`**parentServer.bookingItem.debitor.partnerRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.contact:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.contact:OWNER[[parentServer.bookingItem.debitor.partnerRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.contact:ADMIN[[parentServer.bookingItem.debitor.partnerRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.contact:REFERRER[[parentServer.bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.anchorPerson["`**bookingItem.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.anchorPerson:OWNER[[bookingItem.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitorRel.anchorPerson:ADMIN[[bookingItem.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitorRel.anchorPerson:REFERRER[[bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.debitorRel["`**parentServer.bookingItem.debitor.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel:roles[ ] + style parentServer.bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel:OWNER[[parentServer.bookingItem.debitor.debitorRel:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel:ADMIN[[parentServer.bookingItem.debitor.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel:AGENT[[parentServer.bookingItem.debitor.debitorRel:AGENT]] + role:parentServer.bookingItem.debitor.debitorRel:TENANT[[parentServer.bookingItem.debitor.debitorRel:TENANT]] + end +end + +subgraph bookingItem.debitorRel.holderPerson["`**bookingItem.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.holderPerson:roles[ ] + style bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.holderPerson:OWNER[[bookingItem.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitorRel.holderPerson:ADMIN[[bookingItem.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitorRel.holderPerson:REFERRER[[bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.refundBankAccount["`**bookingItem.debitor.refundBankAccount**`"] + direction TB + style bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.refundBankAccount:roles[ ] + style bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.refundBankAccount:OWNER[[bookingItem.debitor.refundBankAccount:OWNER]] + role:bookingItem.debitor.refundBankAccount:ADMIN[[bookingItem.debitor.refundBankAccount:ADMIN]] + role:bookingItem.debitor.refundBankAccount:REFERRER[[bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel["`**parentServer.bookingItem.debitor.partnerRel**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel:roles[ ] + style parentServer.bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel:OWNER[[parentServer.bookingItem.debitor.partnerRel:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel:ADMIN[[parentServer.bookingItem.debitor.partnerRel:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel:AGENT[[parentServer.bookingItem.debitor.partnerRel:AGENT]] + role:parentServer.bookingItem.debitor.partnerRel:TENANT[[parentServer.bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.debitorRel.contact["`**bookingItem.debitor.debitorRel.contact**`"] + direction TB + style bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.contact:roles[ ] + style bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.contact:OWNER[[bookingItem.debitor.debitorRel.contact:OWNER]] + role:bookingItem.debitor.debitorRel.contact:ADMIN[[bookingItem.debitor.debitorRel.contact:ADMIN]] + role:bookingItem.debitor.debitorRel.contact:REFERRER[[bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor["`**parentServer.bookingItem.debitor**`"] + direction TB + style parentServer.bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson["`**parentServer.bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.contact["`**bookingItem.debitor.partnerRel.contact**`"] + direction TB + style bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.contact:roles[ ] + style bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.contact:OWNER[[bookingItem.debitor.partnerRel.contact:OWNER]] + role:bookingItem.debitor.partnerRel.contact:ADMIN[[bookingItem.debitor.partnerRel.contact:ADMIN]] + role:bookingItem.debitor.partnerRel.contact:REFERRER[[bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel["`**parentServer.bookingItem.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel:roles[ ] + style parentServer.bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel:OWNER[[parentServer.bookingItem.debitorRel:OWNER]] + role:parentServer.bookingItem.debitorRel:ADMIN[[parentServer.bookingItem.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitorRel:AGENT[[parentServer.bookingItem.debitorRel:AGENT]] + role:parentServer.bookingItem.debitorRel:TENANT[[parentServer.bookingItem.debitorRel:TENANT]] + 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["`**parentServer.parentServer**`"] + direction TB + style parentServer.parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.contact["`**parentServer.bookingItem.debitor.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.contact:OWNER[[parentServer.bookingItem.debitor.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitor.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.holderPerson["`**bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.holderPerson:OWNER[[bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:bookingItem.debitor.partnerRel.holderPerson:ADMIN[[bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.holderPerson:REFERRER[[bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.contact["`**bookingItem.debitorRel.contact**`"] + direction TB + style bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.contact:roles[ ] + style bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.contact:OWNER[[bookingItem.debitorRel.contact:OWNER]] + role:bookingItem.debitorRel.contact:ADMIN[[bookingItem.debitorRel.contact:ADMIN]] + role:bookingItem.debitorRel.contact:REFERRER[[bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.refundBankAccount["`**parentServer.bookingItem.debitor.refundBankAccount**`"] + direction TB + style parentServer.bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.refundBankAccount:roles[ ] + style parentServer.bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.refundBankAccount:OWNER[[parentServer.bookingItem.debitor.refundBankAccount:OWNER]] + role:parentServer.bookingItem.debitor.refundBankAccount:ADMIN[[parentServer.bookingItem.debitor.refundBankAccount:ADMIN]] + role:parentServer.bookingItem.debitor.refundBankAccount:REFERRER[[parentServer.bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph bookingItem.debitor["`**bookingItem.debitor**`"] + direction TB + style bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph bookingItem.debitor.debitorRel.holderPerson["`**bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.holderPerson:OWNER[[bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitor.debitorRel.holderPerson:ADMIN[[bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.holderPerson:REFERRER[[bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel["`**bookingItem.debitor.debitorRel**`"] + direction TB + style bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel:roles[ ] + style bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel:OWNER[[bookingItem.debitor.debitorRel:OWNER]] + role:bookingItem.debitor.debitorRel:ADMIN[[bookingItem.debitor.debitorRel:ADMIN]] + role:bookingItem.debitor.debitorRel:AGENT[[bookingItem.debitor.debitorRel:AGENT]] + role:bookingItem.debitor.debitorRel:TENANT[[bookingItem.debitor.debitorRel:TENANT]] + end +end + +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 parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +%% granting roles to roles +role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER +role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER +role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER +role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN +role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER +role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN +role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER +role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN +role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER +role:bookingItem:OWNER -.-> role:bookingItem:ADMIN +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN +role:bookingItem:ADMIN -.-> role:bookingItem:AGENT +role:bookingItem:AGENT -.-> role:bookingItem:TENANT +role:bookingItem:TENANT -.-> role:bookingItem.debitorRel: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 + +``` diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md new file mode 100644 index 00000000..aa856ea9 --- /dev/null +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_SERVER.md @@ -0,0 +1,462 @@ +### rbac asset inCaseOf:MANAGED_SERVER + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph parentServer.bookingItem["`**parentServer.bookingItem**`"] + direction TB + style parentServer.bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem:roles[ ] + style parentServer.bookingItem:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem:OWNER[[parentServer.bookingItem:OWNER]] + role:parentServer.bookingItem:ADMIN[[parentServer.bookingItem:ADMIN]] + role:parentServer.bookingItem:AGENT[[parentServer.bookingItem:AGENT]] + role:parentServer.bookingItem:TENANT[[parentServer.bookingItem:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitorRel.anchorPerson["`**parentServer.bookingItem.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.holderPerson["`**parentServer.bookingItem.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer["`**parentServer**`"] + direction TB + style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson["`**parentServer.bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson["`**parentServer.bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel.anchorPerson["`**bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.anchorPerson:OWNER[[bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.contact["`**parentServer.bookingItem.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.contact:OWNER[[parentServer.bookingItem.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel["`**bookingItem.debitor.partnerRel**`"] + direction TB + style bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel:roles[ ] + style bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel:OWNER[[bookingItem.debitor.partnerRel:OWNER]] + role:bookingItem.debitor.partnerRel:ADMIN[[bookingItem.debitor.partnerRel:ADMIN]] + role:bookingItem.debitor.partnerRel:AGENT[[bookingItem.debitor.partnerRel:AGENT]] + role:bookingItem.debitor.partnerRel:TENANT[[bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.partnerRel.anchorPerson["`**bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.anchorPerson:OWNER[[bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel["`**bookingItem.debitorRel**`"] + direction TB + style bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel:roles[ ] + style bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel:OWNER[[bookingItem.debitorRel:OWNER]] + role:bookingItem.debitorRel:ADMIN[[bookingItem.debitorRel:ADMIN]] + role:bookingItem.debitorRel:AGENT[[bookingItem.debitorRel:AGENT]] + role:bookingItem.debitorRel:TENANT[[bookingItem.debitorRel:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.contact["`**parentServer.bookingItem.debitor.partnerRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.contact:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.contact:OWNER[[parentServer.bookingItem.debitor.partnerRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.contact:ADMIN[[parentServer.bookingItem.debitor.partnerRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.contact:REFERRER[[parentServer.bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.anchorPerson["`**bookingItem.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.anchorPerson:OWNER[[bookingItem.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitorRel.anchorPerson:ADMIN[[bookingItem.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitorRel.anchorPerson:REFERRER[[bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.debitorRel["`**parentServer.bookingItem.debitor.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel:roles[ ] + style parentServer.bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel:OWNER[[parentServer.bookingItem.debitor.debitorRel:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel:ADMIN[[parentServer.bookingItem.debitor.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel:AGENT[[parentServer.bookingItem.debitor.debitorRel:AGENT]] + role:parentServer.bookingItem.debitor.debitorRel:TENANT[[parentServer.bookingItem.debitor.debitorRel:TENANT]] + end +end + +subgraph bookingItem.debitorRel.holderPerson["`**bookingItem.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.holderPerson:roles[ ] + style bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.holderPerson:OWNER[[bookingItem.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitorRel.holderPerson:ADMIN[[bookingItem.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitorRel.holderPerson:REFERRER[[bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.refundBankAccount["`**bookingItem.debitor.refundBankAccount**`"] + direction TB + style bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.refundBankAccount:roles[ ] + style bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.refundBankAccount:OWNER[[bookingItem.debitor.refundBankAccount:OWNER]] + role:bookingItem.debitor.refundBankAccount:ADMIN[[bookingItem.debitor.refundBankAccount:ADMIN]] + role:bookingItem.debitor.refundBankAccount:REFERRER[[bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel["`**parentServer.bookingItem.debitor.partnerRel**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel:roles[ ] + style parentServer.bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel:OWNER[[parentServer.bookingItem.debitor.partnerRel:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel:ADMIN[[parentServer.bookingItem.debitor.partnerRel:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel:AGENT[[parentServer.bookingItem.debitor.partnerRel:AGENT]] + role:parentServer.bookingItem.debitor.partnerRel:TENANT[[parentServer.bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.debitorRel.contact["`**bookingItem.debitor.debitorRel.contact**`"] + direction TB + style bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.contact:roles[ ] + style bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.contact:OWNER[[bookingItem.debitor.debitorRel.contact:OWNER]] + role:bookingItem.debitor.debitorRel.contact:ADMIN[[bookingItem.debitor.debitorRel.contact:ADMIN]] + role:bookingItem.debitor.debitorRel.contact:REFERRER[[bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor["`**parentServer.bookingItem.debitor**`"] + direction TB + style parentServer.bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson["`**parentServer.bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.contact["`**bookingItem.debitor.partnerRel.contact**`"] + direction TB + style bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.contact:roles[ ] + style bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.contact:OWNER[[bookingItem.debitor.partnerRel.contact:OWNER]] + role:bookingItem.debitor.partnerRel.contact:ADMIN[[bookingItem.debitor.partnerRel.contact:ADMIN]] + role:bookingItem.debitor.partnerRel.contact:REFERRER[[bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel["`**parentServer.bookingItem.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel:roles[ ] + style parentServer.bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel:OWNER[[parentServer.bookingItem.debitorRel:OWNER]] + role:parentServer.bookingItem.debitorRel:ADMIN[[parentServer.bookingItem.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitorRel:AGENT[[parentServer.bookingItem.debitorRel:AGENT]] + role:parentServer.bookingItem.debitorRel:TENANT[[parentServer.bookingItem.debitorRel:TENANT]] + 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["`**parentServer.parentServer**`"] + direction TB + style parentServer.parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.contact["`**parentServer.bookingItem.debitor.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.contact:OWNER[[parentServer.bookingItem.debitor.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitor.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.holderPerson["`**bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.holderPerson:OWNER[[bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:bookingItem.debitor.partnerRel.holderPerson:ADMIN[[bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.holderPerson:REFERRER[[bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.contact["`**bookingItem.debitorRel.contact**`"] + direction TB + style bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.contact:roles[ ] + style bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.contact:OWNER[[bookingItem.debitorRel.contact:OWNER]] + role:bookingItem.debitorRel.contact:ADMIN[[bookingItem.debitorRel.contact:ADMIN]] + role:bookingItem.debitorRel.contact:REFERRER[[bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.refundBankAccount["`**parentServer.bookingItem.debitor.refundBankAccount**`"] + direction TB + style parentServer.bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.refundBankAccount:roles[ ] + style parentServer.bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.refundBankAccount:OWNER[[parentServer.bookingItem.debitor.refundBankAccount:OWNER]] + role:parentServer.bookingItem.debitor.refundBankAccount:ADMIN[[parentServer.bookingItem.debitor.refundBankAccount:ADMIN]] + role:parentServer.bookingItem.debitor.refundBankAccount:REFERRER[[parentServer.bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph bookingItem.debitor["`**bookingItem.debitor**`"] + direction TB + style bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph bookingItem.debitor.debitorRel.holderPerson["`**bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.holderPerson:OWNER[[bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitor.debitorRel.holderPerson:ADMIN[[bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.holderPerson:REFERRER[[bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel["`**bookingItem.debitor.debitorRel**`"] + direction TB + style bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel:roles[ ] + style bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel:OWNER[[bookingItem.debitor.debitorRel:OWNER]] + role:bookingItem.debitor.debitorRel:ADMIN[[bookingItem.debitor.debitorRel:ADMIN]] + role:bookingItem.debitor.debitorRel:AGENT[[bookingItem.debitor.debitorRel:AGENT]] + role:bookingItem.debitor.debitorRel:TENANT[[bookingItem.debitor.debitorRel:TENANT]] + end +end + +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 parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +%% granting roles to roles +role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER +role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER +role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER +role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN +role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER +role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN +role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER +role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN +role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER +role:bookingItem:OWNER -.-> role:bookingItem:ADMIN +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN +role:bookingItem:ADMIN -.-> role:bookingItem:AGENT +role:bookingItem:AGENT -.-> role:bookingItem:TENANT +role:bookingItem:TENANT -.-> role:bookingItem.debitorRel: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 + +``` diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md new file mode 100644 index 00000000..1b01c8ff --- /dev/null +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac-MANAGED_WEBSPACE.md @@ -0,0 +1,468 @@ +### rbac asset inCaseOf:MANAGED_WEBSPACE + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph parentServer.bookingItem["`**parentServer.bookingItem**`"] + direction TB + style parentServer.bookingItem fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem:roles[ ] + style parentServer.bookingItem:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem:OWNER[[parentServer.bookingItem:OWNER]] + role:parentServer.bookingItem:ADMIN[[parentServer.bookingItem:ADMIN]] + role:parentServer.bookingItem:AGENT[[parentServer.bookingItem:AGENT]] + role:parentServer.bookingItem:TENANT[[parentServer.bookingItem:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitorRel.anchorPerson["`**parentServer.bookingItem.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.holderPerson["`**parentServer.bookingItem.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer["`**parentServer**`"] + direction TB + style parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson["`**parentServer.bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson["`**parentServer.bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel.anchorPerson["`**bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.anchorPerson:OWNER[[bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel.contact["`**parentServer.bookingItem.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel.contact:OWNER[[parentServer.bookingItem.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel["`**bookingItem.debitor.partnerRel**`"] + direction TB + style bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel:roles[ ] + style bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel:OWNER[[bookingItem.debitor.partnerRel:OWNER]] + role:bookingItem.debitor.partnerRel:ADMIN[[bookingItem.debitor.partnerRel:ADMIN]] + role:bookingItem.debitor.partnerRel:AGENT[[bookingItem.debitor.partnerRel:AGENT]] + role:bookingItem.debitor.partnerRel:TENANT[[bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.partnerRel.anchorPerson["`**bookingItem.debitor.partnerRel.anchorPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.anchorPerson:roles[ ] + style bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.anchorPerson:OWNER[[bookingItem.debitor.partnerRel.anchorPerson:OWNER]] + role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel["`**bookingItem.debitorRel**`"] + direction TB + style bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel:roles[ ] + style bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel:OWNER[[bookingItem.debitorRel:OWNER]] + role:bookingItem.debitorRel:ADMIN[[bookingItem.debitorRel:ADMIN]] + role:bookingItem.debitorRel:AGENT[[bookingItem.debitorRel:AGENT]] + role:bookingItem.debitorRel:TENANT[[bookingItem.debitorRel:TENANT]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel.contact["`**parentServer.bookingItem.debitor.partnerRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel.contact:roles[ ] + style parentServer.bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel.contact:OWNER[[parentServer.bookingItem.debitor.partnerRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel.contact:ADMIN[[parentServer.bookingItem.debitor.partnerRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel.contact:REFERRER[[parentServer.bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.anchorPerson["`**bookingItem.debitorRel.anchorPerson**`"] + direction TB + style bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.anchorPerson:roles[ ] + style bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.anchorPerson:OWNER[[bookingItem.debitorRel.anchorPerson:OWNER]] + role:bookingItem.debitorRel.anchorPerson:ADMIN[[bookingItem.debitorRel.anchorPerson:ADMIN]] + role:bookingItem.debitorRel.anchorPerson:REFERRER[[bookingItem.debitorRel.anchorPerson:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.debitorRel["`**parentServer.bookingItem.debitor.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel:roles[ ] + style parentServer.bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel:OWNER[[parentServer.bookingItem.debitor.debitorRel:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel:ADMIN[[parentServer.bookingItem.debitor.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel:AGENT[[parentServer.bookingItem.debitor.debitorRel:AGENT]] + role:parentServer.bookingItem.debitor.debitorRel:TENANT[[parentServer.bookingItem.debitor.debitorRel:TENANT]] + end +end + +subgraph bookingItem.debitorRel.holderPerson["`**bookingItem.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.holderPerson:roles[ ] + style bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.holderPerson:OWNER[[bookingItem.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitorRel.holderPerson:ADMIN[[bookingItem.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitorRel.holderPerson:REFERRER[[bookingItem.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.refundBankAccount["`**bookingItem.debitor.refundBankAccount**`"] + direction TB + style bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.refundBankAccount:roles[ ] + style bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.refundBankAccount:OWNER[[bookingItem.debitor.refundBankAccount:OWNER]] + role:bookingItem.debitor.refundBankAccount:ADMIN[[bookingItem.debitor.refundBankAccount:ADMIN]] + role:bookingItem.debitor.refundBankAccount:REFERRER[[bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.partnerRel["`**parentServer.bookingItem.debitor.partnerRel**`"] + direction TB + style parentServer.bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.partnerRel:roles[ ] + style parentServer.bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.partnerRel:OWNER[[parentServer.bookingItem.debitor.partnerRel:OWNER]] + role:parentServer.bookingItem.debitor.partnerRel:ADMIN[[parentServer.bookingItem.debitor.partnerRel:ADMIN]] + role:parentServer.bookingItem.debitor.partnerRel:AGENT[[parentServer.bookingItem.debitor.partnerRel:AGENT]] + role:parentServer.bookingItem.debitor.partnerRel:TENANT[[parentServer.bookingItem.debitor.partnerRel:TENANT]] + end +end + +subgraph bookingItem.debitor.debitorRel.contact["`**bookingItem.debitor.debitorRel.contact**`"] + direction TB + style bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.contact:roles[ ] + style bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.contact:OWNER[[bookingItem.debitor.debitorRel.contact:OWNER]] + role:bookingItem.debitor.debitorRel.contact:ADMIN[[bookingItem.debitor.debitorRel.contact:ADMIN]] + role:bookingItem.debitor.debitorRel.contact:REFERRER[[bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor["`**parentServer.bookingItem.debitor**`"] + direction TB + style parentServer.bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson["`**parentServer.bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.contact["`**bookingItem.debitor.partnerRel.contact**`"] + direction TB + style bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.contact:roles[ ] + style bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.contact:OWNER[[bookingItem.debitor.partnerRel.contact:OWNER]] + role:bookingItem.debitor.partnerRel.contact:ADMIN[[bookingItem.debitor.partnerRel.contact:ADMIN]] + role:bookingItem.debitor.partnerRel.contact:REFERRER[[bookingItem.debitor.partnerRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitorRel["`**parentServer.bookingItem.debitorRel**`"] + direction TB + style parentServer.bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitorRel:roles[ ] + style parentServer.bookingItem.debitorRel:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitorRel:OWNER[[parentServer.bookingItem.debitorRel:OWNER]] + role:parentServer.bookingItem.debitorRel:ADMIN[[parentServer.bookingItem.debitorRel:ADMIN]] + role:parentServer.bookingItem.debitorRel:AGENT[[parentServer.bookingItem.debitorRel:AGENT]] + role:parentServer.bookingItem.debitorRel:TENANT[[parentServer.bookingItem.debitorRel:TENANT]] + 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["`**parentServer.parentServer**`"] + direction TB + style parentServer.parentServer fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph parentServer.bookingItem.debitor.debitorRel.contact["`**parentServer.bookingItem.debitor.debitorRel.contact**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.contact:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.contact:OWNER[[parentServer.bookingItem.debitor.debitorRel.contact:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.contact:ADMIN[[parentServer.bookingItem.debitor.debitorRel.contact:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.contact:REFERRER[[parentServer.bookingItem.debitor.debitorRel.contact:REFERRER]] + end +end + +subgraph bookingItem.debitor.partnerRel.holderPerson["`**bookingItem.debitor.partnerRel.holderPerson**`"] + direction TB + style bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.partnerRel.holderPerson:roles[ ] + style bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.partnerRel.holderPerson:OWNER[[bookingItem.debitor.partnerRel.holderPerson:OWNER]] + role:bookingItem.debitor.partnerRel.holderPerson:ADMIN[[bookingItem.debitor.partnerRel.holderPerson:ADMIN]] + role:bookingItem.debitor.partnerRel.holderPerson:REFERRER[[bookingItem.debitor.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitorRel.contact["`**bookingItem.debitorRel.contact**`"] + direction TB + style bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitorRel.contact:roles[ ] + style bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitorRel.contact:OWNER[[bookingItem.debitorRel.contact:OWNER]] + role:bookingItem.debitorRel.contact:ADMIN[[bookingItem.debitorRel.contact:ADMIN]] + role:bookingItem.debitorRel.contact:REFERRER[[bookingItem.debitorRel.contact:REFERRER]] + end +end + +subgraph parentServer.bookingItem.debitor.refundBankAccount["`**parentServer.bookingItem.debitor.refundBankAccount**`"] + direction TB + style parentServer.bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.refundBankAccount:roles[ ] + style parentServer.bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.refundBankAccount:OWNER[[parentServer.bookingItem.debitor.refundBankAccount:OWNER]] + role:parentServer.bookingItem.debitor.refundBankAccount:ADMIN[[parentServer.bookingItem.debitor.refundBankAccount:ADMIN]] + role:parentServer.bookingItem.debitor.refundBankAccount:REFERRER[[parentServer.bookingItem.debitor.refundBankAccount:REFERRER]] + end +end + +subgraph bookingItem.debitor["`**bookingItem.debitor**`"] + direction TB + style bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px +end + +subgraph bookingItem.debitor.debitorRel.holderPerson["`**bookingItem.debitor.debitorRel.holderPerson**`"] + direction TB + style bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel.holderPerson:roles[ ] + style bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel.holderPerson:OWNER[[bookingItem.debitor.debitorRel.holderPerson:OWNER]] + role:bookingItem.debitor.debitorRel.holderPerson:ADMIN[[bookingItem.debitor.debitorRel.holderPerson:ADMIN]] + role:bookingItem.debitor.debitorRel.holderPerson:REFERRER[[bookingItem.debitor.debitorRel.holderPerson:REFERRER]] + end +end + +subgraph bookingItem.debitor.debitorRel["`**bookingItem.debitor.debitorRel**`"] + direction TB + style bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph bookingItem.debitor.debitorRel:roles[ ] + style bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white + + role:bookingItem.debitor.debitorRel:OWNER[[bookingItem.debitor.debitorRel:OWNER]] + role:bookingItem.debitor.debitorRel:ADMIN[[bookingItem.debitor.debitorRel:ADMIN]] + role:bookingItem.debitor.debitorRel:AGENT[[bookingItem.debitor.debitorRel:AGENT]] + role:bookingItem.debitor.debitorRel:TENANT[[bookingItem.debitor.debitorRel:TENANT]] + end +end + +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 parentServer.bookingItem.debitor.debitorRel.anchorPerson["`**parentServer.bookingItem.debitor.debitorRel.anchorPerson**`"] + direction TB + style parentServer.bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles[ ] + style parentServer.bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:OWNER]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] + role:parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[parentServer.bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] + end +end + +%% granting roles to roles +role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER +role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER +role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN +role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT +role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT +role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER +role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN +role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER +role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN +role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER +role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN +role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER +role:bookingItem:OWNER -.-> role:bookingItem:ADMIN +role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN +role:bookingItem:ADMIN -.-> role:bookingItem:AGENT +role:bookingItem:AGENT -.-> role:bookingItem:TENANT +role:bookingItem:TENANT -.-> role:bookingItem.debitorRel:TENANT +role:parentServer.bookingItem.debitorRel:AGENT -.-> role:parentServer.bookingItem:OWNER +role:parentServer.bookingItem:OWNER -.-> role:parentServer.bookingItem:ADMIN +role:parentServer.bookingItem.debitorRel:AGENT -.-> role:parentServer.bookingItem:ADMIN +role:parentServer.bookingItem:ADMIN -.-> role:parentServer.bookingItem:AGENT +role:parentServer.bookingItem:AGENT -.-> role:parentServer.bookingItem:TENANT +role:parentServer.bookingItem:TENANT -.-> role:parentServer.bookingItem.debitorRel: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 + +``` diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql similarity index 56% rename from src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.sql rename to src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql index 01919118..bc6939db 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql @@ -3,165 +3,173 @@ -- ============================================================================ ---changeset hs-hosting-server-rbac-OBJECT:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-OBJECT:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRelatedRbacObject('hs_hosting_server'); +call generateRelatedRbacObject('hs_hosting_asset'); --// -- ============================================================================ ---changeset hs-hosting-server-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRbacRoleDescriptors('hsHostingServer', 'hs_hosting_server'); +call generateRbacRoleDescriptors('hsHostingAsset', 'hs_hosting_asset'); --// -- ============================================================================ ---changeset hs-hosting-server-rbac-insert-trigger:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-insert-trigger:1 endDelimiter:--// -- ---------------------------------------------------------------------------- /* Creates the roles, grants and permission for the AFTER INSERT TRIGGER. */ -create or replace procedure buildRbacSystemForHsHostingServer( - NEW hs_hosting_server +create or replace procedure buildRbacSystemForHsHostingAsset( + NEW hs_hosting_asset ) language plpgsql as $$ declare + newParentServer hs_hosting_asset; newBookingItem hs_booking_item; begin call enterTriggerForObjectUuid(NEW.uuid); + SELECT * FROM hs_hosting_asset WHERE uuid = NEW.parentAssetUuid INTO newParentServer; + SELECT * FROM hs_booking_item WHERE uuid = NEW.bookingItemUuid INTO newBookingItem; assert newBookingItem.uuid is not null, format('newBookingItem must not be null for NEW.bookingItemUuid = %s', NEW.bookingItemUuid); perform createRoleWithGrants( - hsHostingServerOWNER(NEW), + hsHostingAssetOWNER(NEW), permissions => array['DELETE'], incomingSuperRoles => array[hsBookingItemADMIN(newBookingItem)] ); perform createRoleWithGrants( - hsHostingServerADMIN(NEW), + hsHostingAssetADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[hsHostingServerOWNER(NEW)] + incomingSuperRoles => array[hsHostingAssetOWNER(NEW)] ); perform createRoleWithGrants( - hsHostingServerTENANT(NEW), + hsHostingAssetTENANT(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[hsHostingServerADMIN(NEW)], + incomingSuperRoles => array[hsHostingAssetADMIN(NEW)], outgoingSubRoles => array[hsBookingItemTENANT(newBookingItem)] ); + IF NEW.type = 'CLOUD_SERVER' THEN + ELSIF NEW.type = 'MANAGED_SERVER' THEN + ELSIF NEW.type = 'MANAGED_WEBSPACE' THEN + END IF; + call leaveTriggerForObjectUuid(NEW.uuid); end; $$; /* - AFTER INSERT TRIGGER to create the role+grant structure for a new hs_hosting_server row. + AFTER INSERT TRIGGER to create the role+grant structure for a new hs_hosting_asset row. */ -create or replace function insertTriggerForHsHostingServer_tf() +create or replace function insertTriggerForHsHostingAsset_tf() returns trigger language plpgsql strict as $$ begin - call buildRbacSystemForHsHostingServer(NEW); + call buildRbacSystemForHsHostingAsset(NEW); return NEW; end; $$; -create trigger insertTriggerForHsHostingServer_tg - after insert on hs_hosting_server +create trigger insertTriggerForHsHostingAsset_tg + after insert on hs_hosting_asset for each row -execute procedure insertTriggerForHsHostingServer_tf(); +execute procedure insertTriggerForHsHostingAsset_tf(); --// -- ============================================================================ ---changeset hs-hosting-server-rbac-INSERT:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-INSERT:1 endDelimiter:--// -- ---------------------------------------------------------------------------- /* - Creates INSERT INTO hs_hosting_server permissions for the related hs_booking_item rows. + Creates INSERT INTO hs_hosting_asset permissions for the related hs_booking_item rows. */ do language plpgsql $$ declare row hs_booking_item; begin - call defineContext('create INSERT INTO hs_hosting_server permissions for the related hs_booking_item rows'); + call defineContext('create INSERT INTO hs_hosting_asset permissions for the related hs_booking_item rows'); FOR row IN SELECT * FROM hs_booking_item LOOP call grantPermissionToRole( - createPermission(row.uuid, 'INSERT', 'hs_hosting_server'), + createPermission(row.uuid, 'INSERT', 'hs_hosting_asset'), hsBookingItemAGENT(row)); END LOOP; END; $$; /** - Adds hs_hosting_server INSERT permission to specified role of new hs_booking_item rows. + Adds hs_hosting_asset INSERT permission to specified role of new hs_booking_item rows. */ -create or replace function hs_hosting_server_hs_booking_item_insert_tf() +create or replace function hs_hosting_asset_hs_booking_item_insert_tf() returns trigger language plpgsql strict as $$ begin call grantPermissionToRole( - createPermission(NEW.uuid, 'INSERT', 'hs_hosting_server'), + createPermission(NEW.uuid, 'INSERT', 'hs_hosting_asset'), hsBookingItemAGENT(NEW)); return NEW; end; $$; -- z_... is to put it at the end of after insert triggers, to make sure the roles exist -create trigger z_hs_hosting_server_hs_booking_item_insert_tg +create trigger z_hs_hosting_asset_hs_booking_item_insert_tg after insert on hs_booking_item for each row -execute procedure hs_hosting_server_hs_booking_item_insert_tf(); +execute procedure hs_hosting_asset_hs_booking_item_insert_tf(); /** - Checks if the user or assumed roles are allowed to insert a row to hs_hosting_server, + Checks if the user or assumed roles are allowed to insert a row to hs_hosting_asset, where the check is performed by a direct role. A direct role is a role depending on a foreign key directly available in the NEW row. */ -create or replace function hs_hosting_server_insert_permission_missing_tf() +create or replace function hs_hosting_asset_insert_permission_missing_tf() returns trigger language plpgsql as $$ begin - raise exception '[403] insert into hs_hosting_server not allowed for current subjects % (%)', + raise exception '[403] insert into hs_hosting_asset not allowed for current subjects % (%)', currentSubjects(), currentSubjectsUuids(); end; $$; -create trigger hs_hosting_server_insert_permission_check_tg - before insert on hs_hosting_server +create trigger hs_hosting_asset_insert_permission_check_tg + before insert on hs_hosting_asset for each row - when ( not hasInsertPermission(NEW.bookingItemUuid, 'INSERT', 'hs_hosting_server') ) - execute procedure hs_hosting_server_insert_permission_missing_tf(); + when ( not hasInsertPermission(NEW.bookingItemUuid, 'INSERT', 'hs_hosting_asset') ) + execute procedure hs_hosting_asset_insert_permission_missing_tf(); --// -- ============================================================================ ---changeset hs-hosting-server-rbac-IDENTITY-VIEW:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-IDENTITY-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call generateRbacIdentityViewFromQuery('hs_hosting_server', + call generateRbacIdentityViewFromQuery('hs_hosting_asset', $idName$ - SELECT server.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(server.caption) as idName - FROM hs_hosting_server server - JOIN hs_booking_item_iv bookingItemIV ON bookingItemIV.uuid = server.bookingItemUuid + SELECT asset.uuid as uuid, bookingItemIV.idName || '-' || cleanIdentifier(asset.identifier) as idName + FROM hs_hosting_asset asset + JOIN hs_booking_item_iv bookingItemIV ON bookingItemIV.uuid = asset.bookingItemUuid $idName$); --// -- ============================================================================ ---changeset hs-hosting-server-rbac-RESTRICTED-VIEW:1 endDelimiter:--// +--changeset hs-hosting-asset-rbac-RESTRICTED-VIEW:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRbacRestrictedView('hs_hosting_server', +call generateRbacRestrictedView('hs_hosting_asset', $orderBy$ - caption + identifier $orderBy$, $updates$ version = new.version, diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7018-hs-hosting-server-test-data.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql similarity index 51% rename from src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7018-hs-hosting-server-test-data.sql rename to src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql index bf1ac243..1e840acd 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7018-hs-hosting-server-test-data.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql @@ -2,15 +2,16 @@ -- ============================================================================ ---changeset hs-hosting-server-TEST-DATA-GENERATOR:1 endDelimiter:--// +--changeset hs-hosting-asset-TEST-DATA-GENERATOR:1 endDelimiter:--// -- ---------------------------------------------------------------------------- /* - Creates a single hs_hosting_server test record. + Creates a single hs_hosting_asset test record. */ -create or replace procedure createHsHostingServerTestData( +create or replace procedure createHsHostingAssetTestData( givenPartnerNumber numeric, - givenDebitorSuffix char(2) + givenDebitorSuffix char(2), + givenWebspacePrefix char(3) ) language plpgsql as $$ declare @@ -18,7 +19,7 @@ declare relatedDebitor hs_office_debitor; relatedBookingItem hs_booking_item; begin - currentTask := 'creating hosting-server test-data ' || givenPartnerNumber::text || givenDebitorSuffix; + currentTask := 'creating hosting-asset 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); @@ -33,25 +34,25 @@ begin where item.debitoruuid = relatedDebitor.uuid and item.caption = 'some PrivateCloud'; - raise notice 'creating test hosting-server: %', givenPartnerNumber::text || givenDebitorSuffix::text; + raise notice 'creating test hosting-asset: %', givenPartnerNumber::text || givenDebitorSuffix::text; raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; insert - into hs_hosting_server (uuid, bookingitemuuid, caption, config) - values (uuid_generate_v4(), relatedBookingItem.uuid, 'some ManagedServer', '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedBookingItem.uuid, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedBookingItem.uuid, 'some Whatever', '{ "CPU": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb); + into hs_hosting_asset (uuid, bookingitemuuid, type, identifier, caption, config) + values (uuid_generate_v4(), relatedBookingItem.uuid, 'MANAGED_SERVER'::HsHostingAssetType, 'vm10' || givenDebitorSuffix, 'some ManagedServer', '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), + (uuid_generate_v4(), relatedBookingItem.uuid, 'CLOUD_SERVER'::HsHostingAssetType, 'vm20' || givenDebitorSuffix, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), + (uuid_generate_v4(), relatedBookingItem.uuid, 'MANAGED_WEBSPACE'::HsHostingAssetType, givenWebspacePrefix || '01', 'some Webspace', '{ "RAM": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb); end; $$; --// -- ============================================================================ ---changeset hs-hosting-server-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--// +--changeset hs-hosting-asset-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--// -- ---------------------------------------------------------------------------- do language plpgsql $$ begin - call createHsHostingServerTestData(10001, '11'); - call createHsHostingServerTestData(10002, '12'); - call createHsHostingServerTestData(10003, '13'); + call createHsHostingAssetTestData(10001, '11', 'aaa'); + call createHsHostingAssetTestData(10002, '12', 'bbb'); + call createHsHostingAssetTestData(10003, '13', 'ccc'); end; $$; diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7010-hs-hosting-server.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7010-hs-hosting-server.sql deleted file mode 100644 index 64250c95..00000000 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7010-hs-hosting-server.sql +++ /dev/null @@ -1,23 +0,0 @@ ---liquibase formatted sql - --- ============================================================================ ---changeset hosting-server-MAIN-TABLE:1 endDelimiter:--// --- ---------------------------------------------------------------------------- - -create table if not exists hs_hosting_server -( - uuid uuid unique references RbacObject (uuid), - version int not null default 0, - bookingItemUuid uuid not null references hs_booking_item(uuid), - caption varchar(80) not null, - config jsonb not null -); ---// - - --- ============================================================================ ---changeset hs-hosting-server-MAIN-TABLE-JOURNAL:1 endDelimiter:--// --- ---------------------------------------------------------------------------- - -call create_journal('hs_hosting_server'); ---// diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.md deleted file mode 100644 index ce381bb8..00000000 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.md +++ /dev/null @@ -1,305 +0,0 @@ -### rbac server - -This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. - -```mermaid -%%{init:{'flowchart':{'htmlLabels':false}}}%% -flowchart TB - -subgraph server["`**server**`"] - direction TB - style server fill:#dd4901,stroke:#274d6e,stroke-width:8px - - subgraph server:roles[ ] - style server:roles fill:#dd4901,stroke:white - - role:server:OWNER[[server:OWNER]] - role:server:ADMIN[[server:ADMIN]] - role:server:TENANT[[server:TENANT]] - end - - subgraph server:permissions[ ] - style server:permissions fill:#dd4901,stroke:white - - perm:server:INSERT{{server:INSERT}} - perm:server:DELETE{{server:DELETE}} - perm:server:UPDATE{{server:UPDATE}} - perm:server:SELECT{{server:SELECT}} - end -end - -subgraph bookingItem.debitor.debitorRel.anchorPerson["`**bookingItem.debitor.debitorRel.anchorPerson**`"] - direction TB - style bookingItem.debitor.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.debitorRel.anchorPerson:roles[ ] - style bookingItem.debitor.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.debitorRel.anchorPerson:OWNER[[bookingItem.debitor.debitorRel.anchorPerson:OWNER]] - role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN[[bookingItem.debitor.debitorRel.anchorPerson:ADMIN]] - role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER[[bookingItem.debitor.debitorRel.anchorPerson:REFERRER]] - end -end - -subgraph bookingItem.debitor.partnerRel.contact["`**bookingItem.debitor.partnerRel.contact**`"] - direction TB - style bookingItem.debitor.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.partnerRel.contact:roles[ ] - style bookingItem.debitor.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.partnerRel.contact:OWNER[[bookingItem.debitor.partnerRel.contact:OWNER]] - role:bookingItem.debitor.partnerRel.contact:ADMIN[[bookingItem.debitor.partnerRel.contact:ADMIN]] - role:bookingItem.debitor.partnerRel.contact:REFERRER[[bookingItem.debitor.partnerRel.contact:REFERRER]] - 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 bookingItem.debitor.partnerRel["`**bookingItem.debitor.partnerRel**`"] - direction TB - style bookingItem.debitor.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.partnerRel:roles[ ] - style bookingItem.debitor.partnerRel:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.partnerRel:OWNER[[bookingItem.debitor.partnerRel:OWNER]] - role:bookingItem.debitor.partnerRel:ADMIN[[bookingItem.debitor.partnerRel:ADMIN]] - role:bookingItem.debitor.partnerRel:AGENT[[bookingItem.debitor.partnerRel:AGENT]] - role:bookingItem.debitor.partnerRel:TENANT[[bookingItem.debitor.partnerRel:TENANT]] - end -end - -subgraph bookingItem.debitor.partnerRel.anchorPerson["`**bookingItem.debitor.partnerRel.anchorPerson**`"] - direction TB - style bookingItem.debitor.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.partnerRel.anchorPerson:roles[ ] - style bookingItem.debitor.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.partnerRel.anchorPerson:OWNER[[bookingItem.debitor.partnerRel.anchorPerson:OWNER]] - role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN[[bookingItem.debitor.partnerRel.anchorPerson:ADMIN]] - role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER[[bookingItem.debitor.partnerRel.anchorPerson:REFERRER]] - end -end - -subgraph bookingItem.debitorRel["`**bookingItem.debitorRel**`"] - direction TB - style bookingItem.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitorRel:roles[ ] - style bookingItem.debitorRel:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitorRel:OWNER[[bookingItem.debitorRel:OWNER]] - role:bookingItem.debitorRel:ADMIN[[bookingItem.debitorRel:ADMIN]] - role:bookingItem.debitorRel:AGENT[[bookingItem.debitorRel:AGENT]] - role:bookingItem.debitorRel:TENANT[[bookingItem.debitorRel:TENANT]] - end -end - -subgraph bookingItem.debitorRel.anchorPerson["`**bookingItem.debitorRel.anchorPerson**`"] - direction TB - style bookingItem.debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitorRel.anchorPerson:roles[ ] - style bookingItem.debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitorRel.anchorPerson:OWNER[[bookingItem.debitorRel.anchorPerson:OWNER]] - role:bookingItem.debitorRel.anchorPerson:ADMIN[[bookingItem.debitorRel.anchorPerson:ADMIN]] - role:bookingItem.debitorRel.anchorPerson:REFERRER[[bookingItem.debitorRel.anchorPerson:REFERRER]] - end -end - -subgraph bookingItem.debitor.partnerRel.holderPerson["`**bookingItem.debitor.partnerRel.holderPerson**`"] - direction TB - style bookingItem.debitor.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.partnerRel.holderPerson:roles[ ] - style bookingItem.debitor.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.partnerRel.holderPerson:OWNER[[bookingItem.debitor.partnerRel.holderPerson:OWNER]] - role:bookingItem.debitor.partnerRel.holderPerson:ADMIN[[bookingItem.debitor.partnerRel.holderPerson:ADMIN]] - role:bookingItem.debitor.partnerRel.holderPerson:REFERRER[[bookingItem.debitor.partnerRel.holderPerson:REFERRER]] - end -end - -subgraph bookingItem.debitorRel.contact["`**bookingItem.debitorRel.contact**`"] - direction TB - style bookingItem.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitorRel.contact:roles[ ] - style bookingItem.debitorRel.contact:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitorRel.contact:OWNER[[bookingItem.debitorRel.contact:OWNER]] - role:bookingItem.debitorRel.contact:ADMIN[[bookingItem.debitorRel.contact:ADMIN]] - role:bookingItem.debitorRel.contact:REFERRER[[bookingItem.debitorRel.contact:REFERRER]] - end -end - -subgraph bookingItem.debitorRel.holderPerson["`**bookingItem.debitorRel.holderPerson**`"] - direction TB - style bookingItem.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitorRel.holderPerson:roles[ ] - style bookingItem.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitorRel.holderPerson:OWNER[[bookingItem.debitorRel.holderPerson:OWNER]] - role:bookingItem.debitorRel.holderPerson:ADMIN[[bookingItem.debitorRel.holderPerson:ADMIN]] - role:bookingItem.debitorRel.holderPerson:REFERRER[[bookingItem.debitorRel.holderPerson:REFERRER]] - end -end - -subgraph bookingItem.debitor.refundBankAccount["`**bookingItem.debitor.refundBankAccount**`"] - direction TB - style bookingItem.debitor.refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.refundBankAccount:roles[ ] - style bookingItem.debitor.refundBankAccount:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.refundBankAccount:OWNER[[bookingItem.debitor.refundBankAccount:OWNER]] - role:bookingItem.debitor.refundBankAccount:ADMIN[[bookingItem.debitor.refundBankAccount:ADMIN]] - role:bookingItem.debitor.refundBankAccount:REFERRER[[bookingItem.debitor.refundBankAccount:REFERRER]] - end -end - -subgraph bookingItem.debitor.debitorRel.contact["`**bookingItem.debitor.debitorRel.contact**`"] - direction TB - style bookingItem.debitor.debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.debitorRel.contact:roles[ ] - style bookingItem.debitor.debitorRel.contact:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.debitorRel.contact:OWNER[[bookingItem.debitor.debitorRel.contact:OWNER]] - role:bookingItem.debitor.debitorRel.contact:ADMIN[[bookingItem.debitor.debitorRel.contact:ADMIN]] - role:bookingItem.debitor.debitorRel.contact:REFERRER[[bookingItem.debitor.debitorRel.contact:REFERRER]] - end -end - -subgraph bookingItem.debitor["`**bookingItem.debitor**`"] - direction TB - style bookingItem.debitor fill:#99bcdb,stroke:#274d6e,stroke-width:8px -end - -subgraph bookingItem.debitor.debitorRel.holderPerson["`**bookingItem.debitor.debitorRel.holderPerson**`"] - direction TB - style bookingItem.debitor.debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.debitorRel.holderPerson:roles[ ] - style bookingItem.debitor.debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.debitorRel.holderPerson:OWNER[[bookingItem.debitor.debitorRel.holderPerson:OWNER]] - role:bookingItem.debitor.debitorRel.holderPerson:ADMIN[[bookingItem.debitor.debitorRel.holderPerson:ADMIN]] - role:bookingItem.debitor.debitorRel.holderPerson:REFERRER[[bookingItem.debitor.debitorRel.holderPerson:REFERRER]] - end -end - -subgraph bookingItem.debitor.debitorRel["`**bookingItem.debitor.debitorRel**`"] - direction TB - style bookingItem.debitor.debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph bookingItem.debitor.debitorRel:roles[ ] - style bookingItem.debitor.debitorRel:roles fill:#99bcdb,stroke:white - - role:bookingItem.debitor.debitorRel:OWNER[[bookingItem.debitor.debitorRel:OWNER]] - role:bookingItem.debitor.debitorRel:ADMIN[[bookingItem.debitor.debitorRel:ADMIN]] - role:bookingItem.debitor.debitorRel:AGENT[[bookingItem.debitor.debitorRel:AGENT]] - role:bookingItem.debitor.debitorRel:TENANT[[bookingItem.debitor.debitorRel:TENANT]] - end -end - -%% granting roles to roles -role:global:ADMIN -.-> role:bookingItem.debitor.debitorRel.anchorPerson:OWNER -role:bookingItem.debitor.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN -role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.debitorRel.holderPerson:OWNER -role:bookingItem.debitor.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitor.debitorRel.holderPerson:ADMIN -role:bookingItem.debitor.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitor.debitorRel.holderPerson:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.debitorRel.contact:OWNER -role:bookingItem.debitor.debitorRel.contact:OWNER -.-> role:bookingItem.debitor.debitorRel.contact:ADMIN -role:bookingItem.debitor.debitorRel.contact:ADMIN -.-> role:bookingItem.debitor.debitorRel.contact:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.debitorRel:OWNER -role:bookingItem.debitor.debitorRel:OWNER -.-> role:bookingItem.debitor.debitorRel:ADMIN -role:bookingItem.debitor.debitorRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT -role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.debitorRel:TENANT -role:bookingItem.debitor.debitorRel.contact:ADMIN -.-> role:bookingItem.debitor.debitorRel:TENANT -role:bookingItem.debitor.debitorRel:TENANT -.-> role:bookingItem.debitor.debitorRel.anchorPerson:REFERRER -role:bookingItem.debitor.debitorRel:TENANT -.-> role:bookingItem.debitor.debitorRel.holderPerson:REFERRER -role:bookingItem.debitor.debitorRel:TENANT -.-> role:bookingItem.debitor.debitorRel.contact:REFERRER -role:bookingItem.debitor.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitor.debitorRel:OWNER -role:bookingItem.debitor.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT -role:global:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:OWNER -role:bookingItem.debitor.refundBankAccount:OWNER -.-> role:bookingItem.debitor.refundBankAccount:ADMIN -role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.refundBankAccount:REFERRER -role:bookingItem.debitor.refundBankAccount:ADMIN -.-> role:bookingItem.debitor.debitorRel:AGENT -role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.refundBankAccount:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel.anchorPerson:OWNER -role:bookingItem.debitor.partnerRel.anchorPerson:OWNER -.-> role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN -role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN -.-> role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel.holderPerson:OWNER -role:bookingItem.debitor.partnerRel.holderPerson:OWNER -.-> role:bookingItem.debitor.partnerRel.holderPerson:ADMIN -role:bookingItem.debitor.partnerRel.holderPerson:ADMIN -.-> role:bookingItem.debitor.partnerRel.holderPerson:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel.contact:OWNER -role:bookingItem.debitor.partnerRel.contact:OWNER -.-> role:bookingItem.debitor.partnerRel.contact:ADMIN -role:bookingItem.debitor.partnerRel.contact:ADMIN -.-> role:bookingItem.debitor.partnerRel.contact:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER -role:bookingItem.debitor.partnerRel:OWNER -.-> role:bookingItem.debitor.partnerRel:ADMIN -role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT -role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT -role:bookingItem.debitor.partnerRel.contact:ADMIN -.-> role:bookingItem.debitor.partnerRel:TENANT -role:bookingItem.debitor.partnerRel:TENANT -.-> role:bookingItem.debitor.partnerRel.anchorPerson:REFERRER -role:bookingItem.debitor.partnerRel:TENANT -.-> role:bookingItem.debitor.partnerRel.holderPerson:REFERRER -role:bookingItem.debitor.partnerRel:TENANT -.-> role:bookingItem.debitor.partnerRel.contact:REFERRER -role:bookingItem.debitor.partnerRel.anchorPerson:ADMIN -.-> role:bookingItem.debitor.partnerRel:OWNER -role:bookingItem.debitor.partnerRel.holderPerson:ADMIN -.-> role:bookingItem.debitor.partnerRel:AGENT -role:bookingItem.debitor.partnerRel:ADMIN -.-> role:bookingItem.debitor.debitorRel:ADMIN -role:bookingItem.debitor.partnerRel:AGENT -.-> role:bookingItem.debitor.debitorRel:AGENT -role:bookingItem.debitor.debitorRel:AGENT -.-> role:bookingItem.debitor.partnerRel:TENANT -role:global:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:OWNER -role:bookingItem.debitorRel.anchorPerson:OWNER -.-> role:bookingItem.debitorRel.anchorPerson:ADMIN -role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:OWNER -role:bookingItem.debitorRel.holderPerson:OWNER -.-> role:bookingItem.debitorRel.holderPerson:ADMIN -role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel.holderPerson:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitorRel.contact:OWNER -role:bookingItem.debitorRel.contact:OWNER -.-> role:bookingItem.debitorRel.contact:ADMIN -role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel.contact:REFERRER -role:global:ADMIN -.-> role:bookingItem.debitorRel:OWNER -role:bookingItem.debitorRel:OWNER -.-> role:bookingItem.debitorRel:ADMIN -role:bookingItem.debitorRel:ADMIN -.-> role:bookingItem.debitorRel:AGENT -role:bookingItem.debitorRel:AGENT -.-> role:bookingItem.debitorRel:TENANT -role:bookingItem.debitorRel.contact:ADMIN -.-> role:bookingItem.debitorRel:TENANT -role:bookingItem.debitorRel:TENANT -.-> role:bookingItem.debitorRel.anchorPerson:REFERRER -role:bookingItem.debitorRel:TENANT -.-> role:bookingItem.debitorRel.holderPerson:REFERRER -role:bookingItem.debitorRel:TENANT -.-> role:bookingItem.debitorRel.contact:REFERRER -role:bookingItem.debitorRel.anchorPerson:ADMIN -.-> role:bookingItem.debitorRel:OWNER -role:bookingItem.debitorRel.holderPerson:ADMIN -.-> role:bookingItem.debitorRel:AGENT -role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:OWNER -role:bookingItem:OWNER -.-> role:bookingItem:ADMIN -role:bookingItem.debitorRel:AGENT -.-> role:bookingItem:ADMIN -role:bookingItem:ADMIN -.-> role:bookingItem:AGENT -role:bookingItem:AGENT -.-> role:bookingItem:TENANT -role:bookingItem:TENANT -.-> role:bookingItem.debitorRel:TENANT -role:bookingItem:ADMIN ==> role:server:OWNER -role:server:OWNER ==> role:server:ADMIN -role:server:ADMIN ==> role:server:TENANT -role:server:TENANT ==> role:bookingItem:TENANT - -%% granting permissions to roles -role:bookingItem:AGENT ==> perm:server:INSERT -role:server:OWNER ==> perm:server:DELETE -role:server:ADMIN ==> perm:server:UPDATE -role:server:TENANT ==> perm:server:SELECT - -``` diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 3fd94518..7be8f944 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -134,8 +134,8 @@ databaseChangeLog: - include: file: db/changelog/6-hs-booking/601-booking-item/6018-hs-booking-item-test-data.sql - include: - file: db/changelog/7-hs-hosting/701-hosting-server/7010-hs-hosting-server.sql + file: db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql - include: - file: db/changelog/7-hs-hosting/701-hosting-server/7013-hs-hosting-server-rbac.sql + file: db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql - include: - file: db/changelog/7-hs-hosting/701-hosting-server/7018-hs-hosting-server-test-data.sql + file: db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql diff --git a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java index 643bad2b..15f9c152 100644 --- a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java +++ b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java @@ -51,7 +51,7 @@ public class ArchitectureTest { "..hs.office.relation", "..hs.office.sepamandate", "..hs.booking.item", - "..hs.hosting.server", + "..hs.hosting.asset", "..errors", "..mapper", "..ping", diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java similarity index 72% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerControllerAcceptanceTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java index 04ab39fb..d2c73b7c 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java @@ -1,4 +1,4 @@ -package net.hostsharing.hsadminng.hs.hosting.server; +package net.hostsharing.hsadminng.hs.hosting.asset; import io.restassured.RestAssured; import io.restassured.http.ContentType; @@ -28,13 +28,13 @@ import static org.hamcrest.Matchers.matchesRegex; classes = { HsadminNgApplication.class, JpaAttempt.class } ) @Transactional -class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanup { +class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup { @LocalServerPort private Integer port; @Autowired - HsHostingServerRepository serverRepo; + HsHostingAssetRepository assetRepo; @Autowired HsBookingItemRepository bookingItemRepo; @@ -46,10 +46,10 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu JpaAttempt jpaAttempt; @Nested - class ListServers { + class ListAssets { @Test - void globalAdmin_canViewAllServersOfArbitraryDebitor() { + void globalAdmin_canViewAllAssetsOfArbitraryDebitor() { // given context("superuser-alex@hostsharing.net"); @@ -60,13 +60,26 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu .header("current-user", "superuser-alex@hostsharing.net") .port(port) .when() - .get("http://localhost/api/hs/hosting/servers?debitorUuid=" + givenDebitor.getUuid()) + .get("http://localhost/api/hs/hosting/assets?debitorUuid=" + givenDebitor.getUuid()) .then().log().all().assertThat() .statusCode(200) .contentType("application/json") .body("", lenientlyEquals(""" [ { + "type": "MANAGED_WEBSPACE", + "identifier": "aaa01", + "caption": "some Webspace", + "config": { + "HDD": 2048, + "RAM": 1, + "SDD": 512, + "extra": 42 + } + }, + { + "type": "MANAGED_SERVER", + "identifier": "vm1011", "caption": "some ManagedServer", "config": { "CPU": 2, @@ -75,21 +88,14 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu } }, { + "type": "CLOUD_SERVER", + "identifier": "vm2011", "caption": "another CloudServer", "config": { "CPU": 2, "HDD": 1024, "extra": 42 } - }, - { - "caption": "some Whatever", - "config": { - "CPU": 1, - "HDD": 2048, - "SDD": 512, - "extra": 42 - } } ] """)); @@ -101,7 +107,7 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu class AddServer { @Test - void globalAdmin_canAddServer() { + void globalAdmin_canAddAsset() { context.define("superuser-alex@hostsharing.net"); final var givenBookingItem = givenBookingItem("First", "some PrivateCloud"); @@ -113,26 +119,30 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu .body(""" { "bookingItemUuid": "%s", + "type": "MANAGED_SERVER", + "identifier": "vm1400", "caption": "some new CloudServer", "config": { "CPU": 3, "extra": 42 } } """.formatted(givenBookingItem.getUuid())) .port(port) .when() - .post("http://localhost/api/hs/hosting/servers") + .post("http://localhost/api/hs/hosting/assets") .then().log().all().assertThat() .statusCode(201) .contentType(ContentType.JSON) .body("", lenientlyEquals(""" { + "type": "MANAGED_SERVER", + "identifier": "vm1400", "caption": "some new CloudServer", "config": { "CPU": 3, "extra": 42 } } """)) - .header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/servers/[^/]*")) + .header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*")) .extract().header("Location"); // @formatter:on - // finally, the new server can be accessed under the generated UUID + // finally, the new asset can be accessed under the generated UUID final var newUserUuid = UUID.fromString( location.substring(location.lastIndexOf('/') + 1)); assertThat(newUserUuid).isNotNull(); @@ -140,12 +150,12 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu } @Nested - class GetServer { + class GetASset { @Test - void globalAdmin_canGetArbitraryServer() { + void globalAdmin_canGetArbitraryAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenServerUuid = serverRepo.findAll().stream() + final var givenAssetUuid = assetRepo.findAll().stream() .filter(bi -> bi.getBookingItem().getDebitor().getDebitorNumber() == 1000111) .filter(item -> item.getCaption().equals("some ManagedServer")) .findAny().orElseThrow().getUuid(); @@ -155,7 +165,7 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu .header("current-user", "superuser-alex@hostsharing.net") .port(port) .when() - .get("http://localhost/api/hs/hosting/servers/" + givenServerUuid) + .get("http://localhost/api/hs/hosting/assets/" + givenAssetUuid) .then().log().all().assertThat() .statusCode(200) .contentType("application/json") @@ -172,11 +182,11 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu } @Test - void normalUser_canNotGetUnrelatedServer() { + void normalUser_canNotGetUnrelatedAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenServerUuid = serverRepo.findAll().stream() + final var givenAssetUuid = assetRepo.findAll().stream() .filter(bi -> bi.getBookingItem().getDebitor().getDebitorNumber() == 1000212) - .map(HsHostingServerEntity::getUuid) + .map(HsHostingAssetEntity::getUuid) .findAny().orElseThrow(); RestAssured // @formatter:off @@ -184,15 +194,15 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu .header("current-user", "selfregistered-user-drew@hostsharing.org") .port(port) .when() - .get("http://localhost/api/hs/hosting/servers/" + givenServerUuid) + .get("http://localhost/api/hs/hosting/assets/" + givenAssetUuid) .then().log().body().assertThat() .statusCode(404); // @formatter:on } @Test - void debitorAgentUser_canGetRelatedServer() { + void debitorAgentUser_canGetRelatedAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenServerUuid = serverRepo.findAll().stream() + final var givenAssetUuid = assetRepo.findAll().stream() .filter(bi -> bi.getBookingItem().getDebitor().getDebitorNumber() == 1000313) .filter(bi -> bi.getCaption().equals("some ManagedServer")) .findAny().orElseThrow().getUuid(); @@ -202,12 +212,13 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu .header("current-user", "person-TuckerJack@example.com") .port(port) .when() - .get("http://localhost/api/hs/hosting/servers/" + givenServerUuid) + .get("http://localhost/api/hs/hosting/assets/" + givenAssetUuid) .then().log().all().assertThat() .statusCode(200) .contentType("application/json") .body("", lenientlyEquals(""" { + "identifier": "vm1013", "caption": "some ManagedServer", "config": { "CPU": 2, @@ -220,12 +231,12 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu } @Nested - class PatchServer { + class PatchAsset { @Test - void globalAdmin_canPatchAllUpdatablePropertiesOfServer() { + void globalAdmin_canPatchAllUpdatablePropertiesOfAsset() { - final var givenServer = givenSomeTemporaryServerForDebitorNumber(1000111, entry("something", 1)); + final var givenAsset = givenSomeTemporaryAssetForDebitorNumber("2001", entry("something", 1)); RestAssured // @formatter:off .given() @@ -242,13 +253,15 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu """) .port(port) .when() - .patch("http://localhost/api/hs/hosting/servers/" + givenServer.getUuid()) + .patch("http://localhost/api/hs/hosting/assets/" + givenAsset.getUuid()) .then().log().all().assertThat() .statusCode(200) .contentType(ContentType.JSON) .body("", lenientlyEquals(""" { - "caption": "some test-server", + "type": "CLOUD_SERVER", + "identifier": "vm2001", + "caption": "some test-asset", "config": { "CPU": "4", "SSD": "4096", @@ -257,53 +270,53 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu } """)); // @formatter:on - // finally, the server is actually updated + // finally, the asset is actually updated context.define("superuser-alex@hostsharing.net"); - assertThat(serverRepo.findByUuid(givenServer.getUuid())).isPresent().get() - .matches(server -> { - assertThat(server.toString()).isEqualTo("HsHostingServerEntity(D-1000111:some CloudServer, some test-server, { CPU: 4, SSD: 4096, something: 1 })"); + assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent().get() + .matches(asset -> { + assertThat(asset.toString()).isEqualTo("HsHostingAssetEntity(D-1000111:some CloudServer, CLOUD_SERVER, vm2001, some test-asset, { CPU: 4, SSD: 4096, something: 1 })"); return true; }); } } @Nested - class DeleteServer { + class DeleteAsset { @Test - void globalAdmin_canDeleteArbitraryServer() { + void globalAdmin_canDeleteArbitraryAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenServer = givenSomeTemporaryServerForDebitorNumber(1000111, entry("something", 1)); + final var givenAsset = givenSomeTemporaryAssetForDebitorNumber("2002", entry("something", 1)); RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") .port(port) .when() - .delete("http://localhost/api/hs/hosting/servers/" + givenServer.getUuid()) + .delete("http://localhost/api/hs/hosting/assets/" + givenAsset.getUuid()) .then().log().body().assertThat() .statusCode(204); // @formatter:on - // then the given server is gone - assertThat(serverRepo.findByUuid(givenServer.getUuid())).isEmpty(); + // then the given assets is gone + assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isEmpty(); } @Test - void normalUser_canNotDeleteUnrelatedServer() { + void normalUser_canNotDeleteUnrelatedAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenServer = givenSomeTemporaryServerForDebitorNumber(1000111, entry("something", 1)); + final var givenAsset = givenSomeTemporaryAssetForDebitorNumber("2003", entry("something", 1)); RestAssured // @formatter:off .given() .header("current-user", "selfregistered-user-drew@hostsharing.org") .port(port) .when() - .delete("http://localhost/api/hs/hosting/servers/" + givenServer.getUuid()) + .delete("http://localhost/api/hs/hosting/assets/" + givenAsset.getUuid()) .then().log().body().assertThat() .statusCode(404); // @formatter:on - // then the given server is still there - assertThat(serverRepo.findByUuid(givenServer.getUuid())).isNotEmpty(); + // then the given asset is still there + assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isNotEmpty(); } } @@ -314,18 +327,20 @@ class HsHostingServerControllerAcceptanceTest extends ContextBasedTestWithCleanu .findAny().orElseThrow(); } - private HsHostingServerEntity givenSomeTemporaryServerForDebitorNumber(final int debitorNumber, + private HsHostingAssetEntity givenSomeTemporaryAssetForDebitorNumber(final String identifierSuffix, final Map.Entry resources) { return jpaAttempt.transacted(() -> { context.define("superuser-alex@hostsharing.net"); - final var newServer = HsHostingServerEntity.builder() + final var newAsset = HsHostingAssetEntity.builder() .uuid(UUID.randomUUID()) .bookingItem(givenBookingItem("First", "some CloudServer")) - .caption("some test-server") + .type(HsHostingAssetType.CLOUD_SERVER) + .identifier("vm" + identifierSuffix) + .caption("some test-asset") .config(Map.ofEntries(resources)) .build(); - return serverRepo.save(newServer); + return assetRepo.save(newAsset); }).assertSuccessful().returnedValue(); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java similarity index 73% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityPatcherUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java index d186946b..d726c9b4 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityPatcherUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java @@ -1,6 +1,6 @@ -package net.hostsharing.hsadminng.hs.hosting.server; +package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsServerPatchResource; +import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetPatchResource; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.mapper.KeyValueMap; import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase; @@ -25,9 +25,9 @@ import static org.mockito.Mockito.lenient; @TestInstance(PER_CLASS) @ExtendWith(MockitoExtension.class) -class HsHostingServerEntityPatcherUnitTest extends PatchUnitTestBase< - HsServerPatchResource, - HsHostingServerEntity +class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase< + HsHostingAssetPatchResource, + HsHostingAssetEntity > { private static final UUID INITIAL_BOOKING_ITEM_UUID = UUID.randomUUID(); @@ -58,13 +58,13 @@ class HsHostingServerEntityPatcherUnitTest extends PatchUnitTestBase< void initMocks() { lenient().when(em.getReference(eq(HsOfficeDebitorEntity.class), any())).thenAnswer(invocation -> HsOfficeDebitorEntity.builder().uuid(invocation.getArgument(1)).build()); - lenient().when(em.getReference(eq(HsHostingServerEntity.class), any())).thenAnswer(invocation -> - HsHostingServerEntity.builder().uuid(invocation.getArgument(1)).build()); + lenient().when(em.getReference(eq(HsHostingAssetEntity.class), any())).thenAnswer(invocation -> + HsHostingAssetEntity.builder().uuid(invocation.getArgument(1)).build()); } @Override - protected HsHostingServerEntity newInitialEntity() { - final var entity = new HsHostingServerEntity(); + protected HsHostingAssetEntity newInitialEntity() { + final var entity = new HsHostingAssetEntity(); entity.setUuid(INITIAL_BOOKING_ITEM_UUID); entity.setBookingItem(TEST_BOOKING_ITEM); entity.getConfig().putAll(KeyValueMap.from(INITIAL_CONFIG)); @@ -73,13 +73,13 @@ class HsHostingServerEntityPatcherUnitTest extends PatchUnitTestBase< } @Override - protected HsServerPatchResource newPatchResource() { - return new HsServerPatchResource(); + protected HsHostingAssetPatchResource newPatchResource() { + return new HsHostingAssetPatchResource(); } @Override - protected HsHostingServerEntityPatcher createPatcher(final HsHostingServerEntity server) { - return new HsHostingServerEntityPatcher(server); + protected HsHostingAssetEntityPatcher createPatcher(final HsHostingAssetEntity server) { + return new HsHostingAssetEntityPatcher(server); } @Override @@ -87,14 +87,14 @@ class HsHostingServerEntityPatcherUnitTest extends PatchUnitTestBase< return Stream.of( new JsonNullableProperty<>( "caption", - HsServerPatchResource::setCaption, + HsHostingAssetPatchResource::setCaption, PATCHED_CAPTION, - HsHostingServerEntity::setCaption), + HsHostingAssetEntity::setCaption), new SimpleProperty<>( "config", - HsServerPatchResource::setConfig, + HsHostingAssetPatchResource::setConfig, PATCH_CONFIG, - HsHostingServerEntity::putConfig, + HsHostingAssetEntity::putConfig, PATCHED_CONFIG) .notNullable() ); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java new file mode 100644 index 00000000..4a878bf7 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java @@ -0,0 +1,49 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_BOOKING_ITEM; +import static org.assertj.core.api.Assertions.assertThat; + +class HsHostingAssetEntityUnitTest { + + final HsHostingAssetEntity givenParentAsset = HsHostingAssetEntity.builder() + .bookingItem(TEST_BOOKING_ITEM) + .type(HsHostingAssetType.MANAGED_SERVER) + .identifier("vm1234") + .caption("some managed asset") + .config(Map.ofEntries( + entry("CPUs", 2), + entry("SSD-storage", 512), + entry("HDD-storage", 2048))) + .build(); + final HsHostingAssetEntity givenServer = HsHostingAssetEntity.builder() + .bookingItem(TEST_BOOKING_ITEM) + .type(HsHostingAssetType.MANAGED_WEBSPACE) + .parentAsset(givenParentAsset) + .identifier("xyz00") + .caption("some managed webspace") + .config(Map.ofEntries( + entry("CPUs", 2), + entry("SSD-storage", 512), + entry("HDD-storage", 2048))) + .build(); + + @Test + void toStringContainsAllPropertiesAndResourcesSortedByKey() { + final var result = givenServer.toString(); + + assertThat(result).isEqualTo( + "HsHostingAssetEntity(D-1000100:test booking item, MANAGED_WEBSPACE, D-1000100:test booking item:vm1234, xyz00, some managed webspace, { CPUs: 2, HDD-storage: 2048, SSD-storage: 512 })"); + } + + @Test + void toShortStringContainsOnlyMemberNumberAndCaption() { + final var result = givenServer.toShortString(); + + assertThat(result).isEqualTo("D-1000100:test booking item:xyz00"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java similarity index 56% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepositoryIntegrationTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java index b2ca1b5e..3124ac39 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java @@ -1,4 +1,4 @@ -package net.hostsharing.hsadminng.hs.hosting.server; +package net.hostsharing.hsadminng.hs.hosting.asset; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.distinctGrantDisplaysOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.distinctRoleNamesOf; import static net.hostsharing.hsadminng.rbac.test.Array.fromFormatted; @@ -33,10 +34,10 @@ import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest @Import({ Context.class, JpaAttempt.class }) -class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithCleanup { +class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanup { @Autowired - HsHostingServerRepository serverRepo; + HsHostingAssetRepository assetRepo; @Autowired HsBookingItemRepository bookingItemRepo; @@ -60,30 +61,31 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean HttpServletRequest request; @Nested - class CreateServer { + class CreateAsset { @Test - public void testHostsharingAdmin_withoutAssumedRole_canCreateNewServer() { + public void testHostsharingAdmin_withoutAssumedRole_canCreateNewAsset() { // given context("superuser-alex@hostsharing.net"); - final var count = serverRepo.count(); + final var count = assetRepo.count(); final var givenBookingItem = givenBookingItem("First", "some CloudServer"); - // when final var result = attempt(em, () -> { - final var newServer = HsHostingServerEntity.builder() + final var newAsset = HsHostingAssetEntity.builder() .bookingItem(givenBookingItem) - .caption("some new booking server") + .caption("some new managed webspace") + .type(HsHostingAssetType.MANAGED_WEBSPACE) + .identifier("xyz90") .build(); - return toCleanup(serverRepo.save(newServer)); + return toCleanup(assetRepo.save(newAsset)); }); // then result.assertSuccessful(); - assertThat(result.returnedValue()).isNotNull().extracting(HsHostingServerEntity::getUuid).isNotNull(); - assertThatServerIsPersisted(result.returnedValue()); - assertThat(serverRepo.count()).isEqualTo(count + 1); + assertThat(result.returnedValue()).isNotNull().extracting(HsHostingAssetEntity::getUuid).isNotNull(); + assertThatAssetIsPersisted(result.returnedValue()); + assertThat(assetRepo.count()).isEqualTo(count + 1); } @Test @@ -97,46 +99,49 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenBookingItem = givenBookingItem("First", "some CloudServer"); // when - attempt(em, () -> { - final var newServer = HsHostingServerEntity.builder() + final var result = attempt(em, () -> { + final var newAsset = HsHostingAssetEntity.builder() .bookingItem(givenBookingItem) - .caption("some new booking server") + .type(HsHostingAssetType.MANAGED_WEBSPACE) + .identifier("xyz91") + .caption("some new managed webspace") .build(); - return toCleanup(serverRepo.save(newServer)); + return toCleanup(assetRepo.save(newAsset)); }); // then + result.assertSuccessful(); final var all = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:ADMIN", - "hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:OWNER", - "hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:TENANT")); + "hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN", + "hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER", + "hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(fromFormatted( initialGrantNames, // global-admin - "{ grant perm:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:DELETE to role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:OWNER by system and assume }", // owner - "{ grant perm:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:UPDATE to role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:ADMIN by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-someCloudServer-xyz91:DELETE to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER by system and assume }", // admin - "{ grant role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:ADMIN to role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:OWNER by system and assume }", - "{ grant role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:OWNER to role:hs_booking_item#D-1000111-someCloudServer:ADMIN by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-someCloudServer-xyz91:UPDATE to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN by system and assume }", + "{ grant role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER by system and assume }", + "{ grant role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:OWNER to role:hs_booking_item#D-1000111-someCloudServer:ADMIN by system and assume }", // tenant - "{ grant role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:TENANT to role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:ADMIN by system and assume }", - "{ grant perm:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:SELECT to role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:TENANT by system and assume }", - "{ grant role:hs_booking_item#D-1000111-someCloudServer:TENANT to role:hs_hosting_server#D-1000111-someCloudServer-somenewbookingserver:TENANT by system and assume }", + "{ grant perm:hs_hosting_asset#D-1000111-someCloudServer-xyz91:SELECT to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT by system and assume }", + "{ grant role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:ADMIN by system and assume }", + "{ grant role:hs_booking_item#D-1000111-someCloudServer:TENANT to role:hs_hosting_asset#D-1000111-someCloudServer-xyz91:TENANT by system and assume }", null)); } - private void assertThatServerIsPersisted(final HsHostingServerEntity saved) { - final var found = serverRepo.findByUuid(saved.getUuid()); - assertThat(found).isNotEmpty().map(HsHostingServerEntity::toString).get().isEqualTo(saved.toString()); + private void assertThatAssetIsPersisted(final HsHostingAssetEntity saved) { + final var found = assetRepo.findByUuid(saved.getUuid()); + assertThat(found).isNotEmpty().map(HsHostingAssetEntity::toString).get().isEqualTo(saved.toString()); } } @@ -144,69 +149,69 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean class FindByDebitorUuid { @Test - public void globalAdmin_withoutAssumedRole_canViewAllServersOfArbitraryDebitor() { + public void globalAdmin_withoutAssumedRole_canViewAllAssetsOfArbitraryDebitor() { // given context("superuser-alex@hostsharing.net"); final var debitorUuid = debitorRepo.findDebitorByDebitorNumber(1000212).stream() .findAny().orElseThrow().getUuid(); // when - final var result = serverRepo.findAllByDebitorUuid(debitorUuid); + final var result = assetRepo.findAllByDebitorUuid(debitorUuid); // then allTheseServersAreReturned( result, - "HsHostingServerEntity(D-1000212:some PrivateCloud, another CloudServer, { CPU: 2, HDD: 1024, extra: 42 })", - "HsHostingServerEntity(D-1000212:some PrivateCloud, some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", - "HsHostingServerEntity(D-1000212:some PrivateCloud, some Whatever, { CPU: 1, HDD: 2048, SDD: 512, extra: 42 })"); + "HsHostingAssetEntity(D-1000212:some PrivateCloud, MANAGED_WEBSPACE, bbb01, some Webspace, { HDD: 2048, RAM: 1, SDD: 512, extra: 42 })", + "HsHostingAssetEntity(D-1000212:some PrivateCloud, MANAGED_SERVER, vm1012, some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", + "HsHostingAssetEntity(D-1000212:some PrivateCloud, CLOUD_SERVER, vm2012, another CloudServer, { CPU: 2, HDD: 1024, extra: 42 })"); } @Test - public void normalUser_canViewOnlyRelatedServers() { + public void normalUser_canViewOnlyRelatedAsset() { // given: context("person-FirbySusan@example.com"); final var debitorUuid = debitorRepo.findDebitorByDebitorNumber(1000111).stream().findAny().orElseThrow().getUuid(); // when: - final var result = serverRepo.findAllByDebitorUuid(debitorUuid); + final var result = assetRepo.findAllByDebitorUuid(debitorUuid); // then: - exactlyTheseServersAreReturned( + exactlyTheseAssetsAreReturned( result, - "HsHostingServerEntity(D-1000111:some PrivateCloud, another CloudServer, { CPU: 2, HDD: 1024, extra: 42 })", - "HsHostingServerEntity(D-1000111:some PrivateCloud, some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", - "HsHostingServerEntity(D-1000111:some PrivateCloud, some Whatever, { CPU: 1, HDD: 2048, SDD: 512, extra: 42 })"); + "HsHostingAssetEntity(D-1000111:some PrivateCloud, MANAGED_WEBSPACE, aaa01, some Webspace, { HDD: 2048, RAM: 1, SDD: 512, extra: 42 })", + "HsHostingAssetEntity(D-1000111:some PrivateCloud, MANAGED_SERVER, vm1011, some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", + "HsHostingAssetEntity(D-1000111:some PrivateCloud, CLOUD_SERVER, vm2011, another CloudServer, { CPU: 2, HDD: 1024, extra: 42 })"); } } @Nested - class UpdateServer { + class UpdateAsset { @Test public void hostsharingAdmin_canUpdateArbitraryServer() { // given - final var givenServerUuid = givenSomeTemporaryServer("First").getUuid(); + final var givenAssetUuid = givenSomeTemporaryAsset("First", "vm1000").getUuid(); // when final var result = jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); - final var foundServer = em.find(HsHostingServerEntity.class, givenServerUuid); - foundServer.getConfig().put("CPUs", 2); - foundServer.getConfig().remove("SSD-storage"); - foundServer.getConfig().put("HSD-storage", 2048); - return toCleanup(serverRepo.save(foundServer)); + final var foundAsset = em.find(HsHostingAssetEntity.class, givenAssetUuid); + foundAsset.getConfig().put("CPUs", 2); + foundAsset.getConfig().remove("SSD-storage"); + foundAsset.getConfig().put("HSD-storage", 2048); + return toCleanup(assetRepo.save(foundAsset)); }); // then result.assertSuccessful(); jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); - assertThatServerActuallyInDatabase(result.returnedValue()); + assertThatAssetActuallyInDatabase(result.returnedValue()); }).assertSuccessful(); } - private void assertThatServerActuallyInDatabase(final HsHostingServerEntity saved) { - final var found = serverRepo.findByUuid(saved.getUuid()); + private void assertThatAssetActuallyInDatabase(final HsHostingAssetEntity saved) { + final var found = assetRepo.findByUuid(saved.getUuid()); assertThat(found).isNotEmpty().get().isNotSameAs(saved) .extracting(Object::toString).isEqualTo(saved.toString()); } @@ -216,83 +221,83 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean class DeleteByUuid { @Test - public void globalAdmin_withoutAssumedRole_canDeleteAnyServer() { + public void globalAdmin_withoutAssumedRole_canDeleteAnyAsset() { // given context("superuser-alex@hostsharing.net", null); - final var givenServer = givenSomeTemporaryServer("First"); + final var givenAsset = givenSomeTemporaryAsset("First", "vm1000"); // when final var result = jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); - serverRepo.deleteByUuid(givenServer.getUuid()); + assetRepo.deleteByUuid(givenAsset.getUuid()); }); // then result.assertSuccessful(); assertThat(jpaAttempt.transacted(() -> { context("superuser-fran@hostsharing.net", null); - return serverRepo.findByUuid(givenServer.getUuid()); + return assetRepo.findByUuid(givenAsset.getUuid()); }).assertSuccessful().returnedValue()).isEmpty(); } @Test - public void relatedOwner_canDeleteTheirRelatedServer() { + public void relatedOwner_canDeleteTheirRelatedAsset() { // given context("superuser-alex@hostsharing.net", null); - final var givenServer = givenSomeTemporaryServer("First"); + final var givenAsset = givenSomeTemporaryAsset("First", "vm1000"); // when final var result = jpaAttempt.transacted(() -> { context("person-FirbySusan@example.com"); - assertThat(serverRepo.findByUuid(givenServer.getUuid())).isPresent(); + assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent(); - serverRepo.deleteByUuid(givenServer.getUuid()); + assetRepo.deleteByUuid(givenAsset.getUuid()); }); // then result.assertSuccessful(); assertThat(jpaAttempt.transacted(() -> { context("superuser-fran@hostsharing.net", null); - return serverRepo.findByUuid(givenServer.getUuid()); + return assetRepo.findByUuid(givenAsset.getUuid()); }).assertSuccessful().returnedValue()).isEmpty(); } @Test - public void relatedAdmin_canNotDeleteTheirRelatedServer() { + public void relatedAdmin_canNotDeleteTheirRelatedAsset() { // given context("superuser-alex@hostsharing.net", null); - final var givenServer = givenSomeTemporaryServer("First"); + final var givenAsset = givenSomeTemporaryAsset("First", "vm1000"); // when final var result = jpaAttempt.transacted(() -> { - context("person-FirbySusan@example.com", "hs_hosting_server#D-1000111-someCloudServer-sometempbookingserver:ADMIN"); - assertThat(serverRepo.findByUuid(givenServer.getUuid())).isPresent(); + context("person-FirbySusan@example.com", "hs_hosting_asset#D-1000111-someCloudServer-vm1000:ADMIN"); + assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent(); - serverRepo.deleteByUuid(givenServer.getUuid()); + assetRepo.deleteByUuid(givenAsset.getUuid()); }); // then result.assertExceptionWithRootCauseMessage( JpaSystemException.class, - "[403] Subject ", " is not allowed to delete hs_hosting_server"); + "[403] Subject ", " is not allowed to delete hs_hosting_asset"); assertThat(jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); - return serverRepo.findByUuid(givenServer.getUuid()); + return assetRepo.findByUuid(givenAsset.getUuid()); }).assertSuccessful().returnedValue()).isPresent(); // still there } @Test - public void deletingAServerAlsoDeletesRelatedRolesAndGrants() { + public void deletingAnAssetAlsoDeletesRelatedRolesAndGrants() { // given context("superuser-alex@hostsharing.net"); final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll())); final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll())); - final var givenServer = givenSomeTemporaryServer("First"); + final var givenAsset = givenSomeTemporaryAsset("First", "vm1000"); // when final var result = jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); - return serverRepo.deleteByUuid(givenServer.getUuid()); + return assetRepo.deleteByUuid(givenAsset.getUuid()); }); // then @@ -309,7 +314,7 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean final var query = em.createNativeQuery(""" select currentTask, targetTable, targetOp from tx_journal_v - where targettable = 'hs_hosting_server'; + where targettable = 'hs_hosting_asset'; """); // when @@ -317,24 +322,26 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating hosting-server test-data 1000111, hs_hosting_server, INSERT]", - "[creating hosting-server test-data 1000212, hs_hosting_server, INSERT]", - "[creating hosting-server test-data 1000313, hs_hosting_server, INSERT]"); + "[creating hosting-asset test-data 1000111, hs_hosting_asset, INSERT]", + "[creating hosting-asset test-data 1000212, hs_hosting_asset, INSERT]", + "[creating hosting-asset test-data 1000313, hs_hosting_asset, INSERT]"); } - private HsHostingServerEntity givenSomeTemporaryServer(final String debitorName) { + private HsHostingAssetEntity givenSomeTemporaryAsset(final String debitorName, final String identifier) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); final var givenBookingItem = givenBookingItem(debitorName, "some CloudServer"); - final var newServer = HsHostingServerEntity.builder() + final var newAsset = HsHostingAssetEntity.builder() .bookingItem(givenBookingItem) - .caption("some temp booking server") + .type(CLOUD_SERVER) + .identifier(identifier) + .caption("some temp cloud asset") .config(Map.ofEntries( entry("CPUs", 1), entry("SSD-storage", 256))) .build(); - return toCleanup(serverRepo.save(newServer)); + return toCleanup(assetRepo.save(newAsset)); }).assertSuccessful().returnedValue(); } @@ -345,17 +352,17 @@ class HsHostingServerRepositoryIntegrationTest extends ContextBasedTestWithClean .findAny().orElseThrow(); } - void exactlyTheseServersAreReturned( - final List actualResult, + void exactlyTheseAssetsAreReturned( + final List actualResult, final String... serverNames) { assertThat(actualResult) - .extracting(serverEntity -> serverEntity.toString()) + .extracting(HsHostingAssetEntity::toString) .containsExactlyInAnyOrder(serverNames); } - void allTheseServersAreReturned(final List actualResult, final String... serverNames) { + void allTheseServersAreReturned(final List actualResult, final String... serverNames) { assertThat(actualResult) - .extracting(serverEntity -> serverEntity.toString()) + .extracting(HsHostingAssetEntity::toString) .contains(serverNames); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityUnitTest.java deleted file mode 100644 index 3cae06e2..00000000 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/server/HsHostingServerEntityUnitTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.hostsharing.hsadminng.hs.hosting.server; - -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static java.util.Map.entry; -import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_BOOKING_ITEM; -import static org.assertj.core.api.Assertions.assertThat; - -class HsHostingServerEntityUnitTest { - - final HsHostingServerEntity givenServer = HsHostingServerEntity.builder() - .bookingItem(TEST_BOOKING_ITEM) - .caption("some caption") - .config(Map.ofEntries( - entry("CPUs", 2), - entry("SSD-storage", 512), - entry("HDD-storage", 2048))) - .build(); - - @Test - void toStringContainsAllPropertiesAndResourcesSortedByKey() { - final var result = givenServer.toString(); - - assertThat(result).isEqualTo( - "HsHostingServerEntity(D-1000100:test booking item, some caption, { CPUs: 2, HDD-storage: 2048, SSD-storage: 512 })"); - } - - @Test - void toShortStringContainsOnlyMemberNumberAndCaption() { - final var result = givenServer.toShortString(); - - assertThat(result).isEqualTo("D-1000100:test booking item:some caption"); - } -} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index eda9bea7..3bc64cd1 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -620,7 +620,7 @@ public class ImportOfficeData extends ContextBasedTest { private void deleteTestDataFromHsOfficeTables() { jpaAttempt.transacted(() -> { context(rbacSuperuser); - em.createNativeQuery("delete from hs_hosting_server where true").executeUpdate(); + em.createNativeQuery("delete from hs_hosting_asset where true").executeUpdate(); em.createNativeQuery("delete from hs_booking_item where true").executeUpdate(); em.createNativeQuery("delete from hs_office_coopassetstransaction where true").executeUpdate(); em.createNativeQuery("delete from hs_office_coopassetstransaction_legacy_id where true").executeUpdate();