Compare commits
No commits in common. "7e6a02717f13fa6f5439e06f03a227784bfb174f" and "2e9e5d6ef03fbe3ad38934393db096a5f0bf2416" have entirely different histories.
7e6a02717f
...
2e9e5d6ef0
@ -16,7 +16,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||||
|
|
||||||
import jakarta.persistence.EntityNotFoundException;
|
|
||||||
import jakarta.validation.ValidationException;
|
import jakarta.validation.ValidationException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -131,12 +130,8 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
|
|||||||
return entityToSave;
|
return entityToSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
final BiConsumer<HsHostingAssetInsertResource, HsHostingAssetEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
final BiConsumer<HsHostingAssetInsertResource, HsHostingAssetEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||||
entity.putConfig(KeyValueMap.from(resource.getConfig()));
|
entity.putConfig(KeyValueMap.from(resource.getConfig()));
|
||||||
if (resource.getParentAssetUuid() != null) {
|
|
||||||
entity.setParentAsset(assetRepo.findByUuid(resource.getParentAssetUuid())
|
|
||||||
.orElseThrow(() -> new EntityNotFoundException("ERROR: [400] parentAssetUuid %s not found".formatted(
|
|
||||||
resource.getParentAssetUuid()))));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inOtherCas
|
|||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
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.usingCase;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase;
|
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.Nullable.NULLABLE;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.DELETE;
|
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.INSERT;
|
||||||
@ -136,7 +137,7 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
.importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(),
|
.importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(),
|
||||||
dependsOnColumn("bookingItemUuid"),
|
dependsOnColumn("bookingItemUuid"),
|
||||||
directlyFetchedByDependsOnColumn(),
|
directlyFetchedByDependsOnColumn(),
|
||||||
NULLABLE)
|
NOT_NULL)
|
||||||
|
|
||||||
.switchOnColumn("type",
|
.switchOnColumn("type",
|
||||||
inCaseOf(CLOUD_SERVER.name(),
|
inCaseOf(CLOUD_SERVER.name(),
|
||||||
|
@ -8,7 +8,6 @@ import jakarta.persistence.EntityManager;
|
|||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -26,7 +25,6 @@ public class RbacGrantsDiagramService {
|
|||||||
|
|
||||||
public static void writeToFile(final String title, final String graph, final String fileName) {
|
public static void writeToFile(final String title, final String graph, final String fileName) {
|
||||||
|
|
||||||
new File("doc/temp").mkdirs();
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
|
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
|
||||||
writer.write("""
|
writer.write("""
|
||||||
### all grants to %s
|
### all grants to %s
|
||||||
@ -194,9 +192,8 @@ public class RbacGrantsDiagramService {
|
|||||||
return "[" + roleType + "\nref:" + uuid + "]";
|
return "[" + roleType + "\nref:" + uuid + "]";
|
||||||
}
|
}
|
||||||
if (refType.equals("perm")) {
|
if (refType.equals("perm")) {
|
||||||
final var parts = idName.split(":");
|
final var roleType = idName.split(":")[1];
|
||||||
final var permType = parts[2];
|
return "{{" + roleType + "\nref:" + uuid + "}}";
|
||||||
return "{{" + permType + "\nref:" + uuid + "}}";
|
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -208,7 +205,7 @@ public class RbacGrantsDiagramService {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static String cleanId(final String idName) {
|
private static String cleanId(final String idName) {
|
||||||
return idName.replaceAll("@.*", "")
|
return idName.replaceAll("@.*", "")
|
||||||
.replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", "").replace(">", ":");
|
.replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,11 +53,7 @@ components:
|
|||||||
bookingItemUuid:
|
bookingItemUuid:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
nullable: false
|
||||||
parentAssetUuid:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
nullable: true
|
|
||||||
type:
|
type:
|
||||||
$ref: '#/components/schemas/HsHostingAssetType'
|
$ref: '#/components/schemas/HsHostingAssetType'
|
||||||
identifier:
|
identifier:
|
||||||
@ -76,6 +72,7 @@ components:
|
|||||||
- type
|
- type
|
||||||
- identifier
|
- identifier
|
||||||
- caption
|
- caption
|
||||||
|
- debitorUuid
|
||||||
- config
|
- config
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
|
@ -24,17 +24,13 @@ create table if not exists hs_hosting_asset
|
|||||||
(
|
(
|
||||||
uuid uuid unique references RbacObject (uuid),
|
uuid uuid unique references RbacObject (uuid),
|
||||||
version int not null default 0,
|
version int not null default 0,
|
||||||
bookingItemUuid uuid null references hs_booking_item(uuid),
|
bookingItemUuid uuid not null references hs_booking_item(uuid),
|
||||||
type HsHostingAssetType not null,
|
type HsHostingAssetType not null,
|
||||||
parentAssetUuid uuid null references hs_hosting_asset(uuid),
|
parentAssetUuid uuid null references hs_hosting_asset(uuid),
|
||||||
identifier varchar(80) not null,
|
identifier varchar(80) not null,
|
||||||
caption varchar(80) not null,
|
caption varchar(80) not null,
|
||||||
config jsonb not null,
|
config jsonb not null
|
||||||
|
|
||||||
constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset check (bookingItemUuid is not null or parentAssetUuid is not null)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ begin
|
|||||||
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.parentAssetUuid INTO newParentServer;
|
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.parentAssetUuid INTO newParentServer;
|
||||||
|
|
||||||
SELECT * FROM hs_booking_item WHERE uuid = NEW.bookingItemUuid INTO newBookingItem;
|
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(
|
perform createRoleWithGrants(
|
||||||
hsHostingAssetOWNER(NEW),
|
hsHostingAssetOWNER(NEW),
|
||||||
|
@ -19,7 +19,6 @@ import java.util.Map;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static java.util.Map.entry;
|
import static java.util.Map.entry;
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
|
|
||||||
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
|
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hamcrest.Matchers.matchesRegex;
|
import static org.hamcrest.Matchers.matchesRegex;
|
||||||
@ -114,7 +113,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/hosting/assets?type=" + MANAGED_SERVER)
|
.get("http://localhost/api/hs/hosting/assets?type=" + HsHostingAssetType.MANAGED_SERVER)
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
@ -160,7 +159,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
class AddServer {
|
class AddServer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_canAddBookedAsset() {
|
void globalAdmin_canAddAsset() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenBookingItem = givenBookingItem("First", "some PrivateCloud");
|
final var givenBookingItem = givenBookingItem("First", "some PrivateCloud");
|
||||||
@ -174,7 +173,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"bookingItemUuid": "%s",
|
"bookingItemUuid": "%s",
|
||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"identifier": "vm1400",
|
"identifier": "vm1400",
|
||||||
"caption": "some new ManagedServer",
|
"caption": "some new CloudServer",
|
||||||
"config": { "CPUs": 2, "RAM": 100, "SSD": 300, "Traffic": 250 }
|
"config": { "CPUs": 2, "RAM": 100, "SSD": 300, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
""".formatted(givenBookingItem.getUuid()))
|
""".formatted(givenBookingItem.getUuid()))
|
||||||
@ -188,7 +187,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
{
|
{
|
||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"identifier": "vm1400",
|
"identifier": "vm1400",
|
||||||
"caption": "some new ManagedServer",
|
"caption": "some new CloudServer",
|
||||||
"config": { "CPUs": 2, "RAM": 100, "SSD": 300, "Traffic": 250 }
|
"config": { "CPUs": 2, "RAM": 100, "SSD": 300, "Traffic": 250 }
|
||||||
}
|
}
|
||||||
"""))
|
"""))
|
||||||
@ -201,48 +200,6 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
assertThat(newUserUuid).isNotNull();
|
assertThat(newUserUuid).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void parentAssetAgent_canAddSubAsset() {
|
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
|
||||||
final var givenParentAsset = givenParentAsset("First", MANAGED_SERVER);
|
|
||||||
|
|
||||||
final var location = RestAssured // @formatter:off
|
|
||||||
.given()
|
|
||||||
.header("current-user", "person-FirbySusan@example.com")
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.body("""
|
|
||||||
{
|
|
||||||
"parentAssetUuid": "%s",
|
|
||||||
"type": "MANAGED_WEBSPACE",
|
|
||||||
"identifier": "xyz00",
|
|
||||||
"caption": "some new ManagedWebspace in client's ManagedServer",
|
|
||||||
"config": { "SSD": 100, "Traffic": 250 }
|
|
||||||
}
|
|
||||||
""".formatted(givenParentAsset.getUuid()))
|
|
||||||
.port(port)
|
|
||||||
.when()
|
|
||||||
.post("http://localhost/api/hs/hosting/assets")
|
|
||||||
.then().log().all().assertThat()
|
|
||||||
.statusCode(201)
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.body("", lenientlyEquals("""
|
|
||||||
{
|
|
||||||
"type": "MANAGED_WEBSPACE",
|
|
||||||
"identifier": "xyz00",
|
|
||||||
"caption": "some new ManagedWebspace in client's ManagedServer",
|
|
||||||
"config": { "SSD": 100, "Traffic": 250 }
|
|
||||||
}
|
|
||||||
"""))
|
|
||||||
.header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*"))
|
|
||||||
.extract().header("Location"); // @formatter:on
|
|
||||||
|
|
||||||
// finally, the new asset can be accessed under the generated UUID
|
|
||||||
final var newUserUuid = UUID.fromString(
|
|
||||||
location.substring(location.lastIndexOf('/') + 1));
|
|
||||||
assertThat(newUserUuid).isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void additionalValidationsArePerformend_whenAddingAsset() {
|
void additionalValidationsArePerformend_whenAddingAsset() {
|
||||||
|
|
||||||
@ -258,7 +215,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"bookingItemUuid": "%s",
|
"bookingItemUuid": "%s",
|
||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"identifier": "vm1400",
|
"identifier": "vm1400",
|
||||||
"caption": "some new ManagedServer",
|
"caption": "some new CloudServer",
|
||||||
"config": { "CPUs": 0, "extra": 42 }
|
"config": { "CPUs": 0, "extra": 42 }
|
||||||
}
|
}
|
||||||
""".formatted(givenBookingItem.getUuid()))
|
""".formatted(givenBookingItem.getUuid()))
|
||||||
@ -278,7 +235,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class GetAsset {
|
class GetASset {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_canGetArbitraryAsset() {
|
void globalAdmin_canGetArbitraryAsset() {
|
||||||
@ -455,12 +412,6 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.findAny().orElseThrow();
|
.findAny().orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
HsHostingAssetEntity givenParentAsset(final String debitorName, final HsHostingAssetType assetType) {
|
|
||||||
final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike(debitorName).stream().findAny().orElseThrow();
|
|
||||||
final var givenAsset = assetRepo.findAllByCriteria(givenDebitor.getUuid(), null, assetType).stream().findAny().orElseThrow();
|
|
||||||
return givenAsset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HsHostingAssetEntity givenSomeTemporaryAssetForDebitorNumber(final String identifierSuffix,
|
private HsHostingAssetEntity givenSomeTemporaryAssetForDebitorNumber(final String identifierSuffix,
|
||||||
final Map.Entry<String, Integer> resources) {
|
final Map.Entry<String, Integer> resources) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
|
Loading…
Reference in New Issue
Block a user