From 1adc2d09f7af2920119dd327df71f1e7c1cb3950 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Jun 2026 10:54:28 +0000
Subject: [PATCH 1/3] Initial plan
From 4b3791b8d11a3e861541a8521295c1a7feccc6e2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Jun 2026 11:27:45 +0000
Subject: [PATCH 2/3] feat: add tenant isolation for multi-tenant SCL data
service
- Add Flyway migration V1_8 to add tenant column to scl_file table
- Add GLOBAL_TENANT constant ("global") for no-auth mode
- Add TenantService to resolve tenant from JWT issuer or fall back to "global"
- Update CompasSclDataRepository interface: all methods take tenant as first param
- Update PostgreSQL repository SQL to filter/insert by tenant
- Update SoftDeleteCompasSclDataPostgreSQLRepository with tenant in DELETE SQL
- Update CompasSclDataService: all public methods take tenant as first param
- Update REST resource (CompasSclDataResource) to inject TenantService
- Update WebSocket event models and endpoints with tenant field
- Update CompasPluginsResourceService and CompasPluginsResource with tenant
- Add TenantServiceTest with 6 unit tests covering all scenarios
- Update all existing tests to use tenant parameter
---
.../compas/scl/data/rest/TenantService.java | 56 ++++++++
.../data/rest/v1/CompasPluginsResource.java | 13 +-
.../data/rest/v1/CompasSclDataResource.java | 33 +++--
.../service/CompasPluginsResourceService.java | 27 ++--
.../event/CompasSclDataEventHandler.java | 8 +-
.../event/model/CreateEventRequest.java | 8 +-
.../event/model/GetEventRequest.java | 8 +-
.../event/model/GetVersionEventRequest.java | 8 +-
.../event/model/UpdateEventRequest.java | 8 +-
.../v1/CompasSclCreateServerEndpoint.java | 8 +-
.../v1/CompasSclGetServerEndpoint.java | 7 +-
.../v1/CompasSclGetVersionServerEndpoint.java | 7 +-
.../v1/CompasSclUpdateServerEndpoint.java | 8 +-
.../scl/data/rest/TenantServiceTest.java | 69 ++++++++++
.../v1/CompasPluginsResourceGetDataTest.java | 20 ++-
.../rest/v1/CompasPluginsResourceTest.java | 9 +-
.../v1/CompasSclDataResourceAsEditorTest.java | 54 +++++---
.../v1/CompasSclDataResourceAsReaderTest.java | 29 +++--
.../CompasPluginsResourceServiceTest.java | 33 ++---
.../event/CompasSclDataEventHandlerTest.java | 74 +++++------
.../event/model/CreateEventRequestTest.java | 3 +-
.../event/model/GetEventRequestTest.java | 3 +-
.../model/GetVersionEventRequestTest.java | 3 +-
.../event/model/UpdateEventRequestTest.java | 3 +-
...asSclCreateServerEndpointAsEditorTest.java | 10 +-
.../v1/CompasSclCreateServerEndpointTest.java | 2 +-
...ompasSclGetServerEndpointAsEditorTest.java | 10 +-
...ompasSclGetServerEndpointAsReaderTest.java | 10 +-
...lGetVersionServerEndpointAsEditorTest.java | 10 +-
...lGetVersionServerEndpointAsReaderTest.java | 10 +-
...asSclUpdateServerEndpointAsEditorTest.java | 10 +-
.../v1/CompasSclUpdateServerEndpointTest.java | 2 +-
.../CompasSclDataPostgreSQLRepository.java | 83 +++++++-----
...leteCompasSclDataPostgreSQLRepository.java | 10 +-
.../V1_8__add_tenant_to_scl_file.sql | 16 +++
.../scl/data/SclDataServiceConstants.java | 5 +
.../repository/CompasSclDataRepository.java | 51 +++++---
.../AbstractCompasSclDataRepositoryTest.java | 25 ++--
.../data/service/CompasSclDataService.java | 64 +++++----
.../service/CompasSclDataServiceTest.java | 121 +++++++++---------
40 files changed, 626 insertions(+), 312 deletions(-)
create mode 100644 app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java
create mode 100644 app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java
create mode 100644 repository-postgresql/src/main/resources/org/lfenergy/compas/scl/data/repository/postgresql/db/migration/V1_8__add_tenant_to_scl_file.sql
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java
new file mode 100644
index 00000000..cb4e1c3b
--- /dev/null
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: 2026 Alliander N.V.
+//
+// SPDX-License-Identifier: Apache-2.0
+package org.lfenergy.compas.scl.data.rest;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import static org.lfenergy.compas.scl.data.SclDataServiceConstants.GLOBAL_TENANT;
+
+/**
+ * Service responsible for resolving the tenant name for the current request.
+ *
+ * Tenant resolution rules:
+ *
+ * - When authentication is disabled (no JWT issuer), the hardcoded
+ * tenant {@code "global"} is used.
+ * - When OIDC authentication is enabled, the tenant name is derived
+ * from the realm segment of the JWT issuer URL
+ * (e.g. {@code http://host/auth/realms/compas} → tenant {@code "compas"}).
+ *
+ */
+@ApplicationScoped
+public class TenantService {
+
+ private final JsonWebToken jsonWebToken;
+
+ @Inject
+ public TenantService(JsonWebToken jsonWebToken) {
+ this.jsonWebToken = jsonWebToken;
+ }
+
+ /**
+ * Resolve the tenant name for the active request.
+ *
+ * @return The resolved tenant name; never {@code null}.
+ */
+ public String resolveTenant() {
+ try {
+ String issuer = jsonWebToken.getIssuer();
+ if (issuer == null || issuer.isBlank()) {
+ return GLOBAL_TENANT;
+ }
+ // Issuer URL format (Keycloak): http:///auth/realms/
+ // Extract the last path segment as the realm / tenant name.
+ int lastSlash = issuer.lastIndexOf('/');
+ if (lastSlash >= 0 && lastSlash < issuer.length() - 1) {
+ return issuer.substring(lastSlash + 1);
+ }
+ } catch (Exception e) {
+ // No token available – fall back to global tenant.
+ }
+ return GLOBAL_TENANT;
+ }
+}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResource.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResource.java
index 377f367b..cb529e60 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResource.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResource.java
@@ -11,6 +11,7 @@
import org.lfenergy.compas.scl.data.exception.CompasInvalidInputException;
import org.lfenergy.compas.scl.data.model.PluginsCustomResource;
import org.lfenergy.compas.scl.data.rest.PluginsCustomResourcesApi;
+import org.lfenergy.compas.scl.data.rest.TenantService;
import org.lfenergy.compas.scl.data.rest.dto.DataEntry;
import org.lfenergy.compas.scl.data.rest.dto.DataEntryWithContent;
import org.lfenergy.compas.scl.data.rest.dto.PagedDataEntryResponse;
@@ -32,10 +33,12 @@ public class CompasPluginsResource implements PluginsCustomResourcesApi {
private static final Logger LOGGER = LogManager.getLogger(CompasPluginsResource.class);
private final CompasPluginsResourceService service;
+ private final TenantService tenantService;
@Inject
- public CompasPluginsResource(CompasPluginsResourceService service) {
+ public CompasPluginsResource(CompasPluginsResourceService service, TenantService tenantService) {
this.service = service;
+ this.tenantService = tenantService;
}
@Override
@@ -46,9 +49,10 @@ public PagedDataEntryResponse getAllData(String type,
Integer page,
Integer size) {
LOGGER.info("Listing plugins custom resources for type '{}'", type);
+ String tenant = tenantService.resolveTenant();
- var entities = service.list(type, uploadedAfter, uploadedBefore, name, page, size);
- long totalElements = service.count(type, uploadedAfter, uploadedBefore, name);
+ var entities = service.list(tenant, type, uploadedAfter, uploadedBefore, name, page, size);
+ long totalElements = service.count(tenant, type, uploadedAfter, uploadedBefore, name);
var entries = entities.stream()
.map(this::toDataEntry)
@@ -89,7 +93,8 @@ public UploadDataResponse uploadData(String type,
throw new CompasInvalidInputException("Failed to read content from upload");
}
- var entity = service.upload(new UploadCustomPluginsResourceData(type, name, contentType, contentText,
+ String tenant = tenantService.resolveTenant();
+ var entity = service.upload(tenant, new UploadCustomPluginsResourceData(type, name, contentType, contentText,
dataCompatibilityVersion, description, version, nextVersionType));
var response = new UploadDataResponse();
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResource.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResource.java
index fba0497c..13c1e007 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResource.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResource.java
@@ -10,6 +10,7 @@
import org.apache.logging.log4j.Logger;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.lfenergy.compas.scl.data.model.Version;
+import org.lfenergy.compas.scl.data.rest.TenantService;
import org.lfenergy.compas.scl.data.rest.UserInfoProperties;
import org.lfenergy.compas.scl.data.rest.v1.model.*;
import org.lfenergy.compas.scl.data.service.CompasSclDataService;
@@ -38,6 +39,9 @@ public class CompasSclDataResource {
@Inject
UserInfoProperties userInfoProperties;
+ @Inject
+ TenantService tenantService;
+
@Inject
public CompasSclDataResource(CompasSclDataService compasSclDataService) {
this.compasSclDataService = compasSclDataService;
@@ -52,9 +56,11 @@ public Uni create(@PathParam(TYPE_PATH_PARAM) SclFileType type,
LOGGER.info("Adding new SCL File for type {} to storage.", type);
String who = jsonWebToken.getClaim(userInfoProperties.who());
LOGGER.trace("Username used for Who {}", who);
+ String tenant = tenantService.resolveTenant();
+ LOGGER.trace("Tenant resolved as {}", tenant);
var response = new CreateResponse();
- response.setSclData(compasSclDataService.create(type, request.getName(), who, request.getComment(),
+ response.setSclData(compasSclDataService.create(tenant, type, request.getName(), who, request.getComment(),
request.getSclData()));
return Uni.createFrom().item(response);
}
@@ -64,8 +70,9 @@ public Uni create(@PathParam(TYPE_PATH_PARAM) SclFileType type,
@Produces(MediaType.APPLICATION_XML)
public Uni list(@PathParam(TYPE_PATH_PARAM) SclFileType type) {
LOGGER.info("Listing SCL Files for type {} from storage.", type);
+ String tenant = tenantService.resolveTenant();
var response = new ListResponse();
- response.setItems(compasSclDataService.list(type));
+ response.setItems(compasSclDataService.list(tenant, type));
return Uni.createFrom().item(response);
}
@@ -75,8 +82,9 @@ public Uni list(@PathParam(TYPE_PATH_PARAM) SclFileType type) {
public Uni listVersionsByUUID(@PathParam(TYPE_PATH_PARAM) SclFileType type,
@PathParam(ID_PATH_PARAM) UUID id) {
LOGGER.info("Listing versions of SCL File {} for type {} from storage.", id, type);
+ String tenant = tenantService.resolveTenant();
var response = new VersionsResponse();
- response.setItems(compasSclDataService.listVersionsByUUID(type, id));
+ response.setItems(compasSclDataService.listVersionsByUUID(tenant, type, id));
return Uni.createFrom().item(response);
}
@@ -86,8 +94,9 @@ public Uni listVersionsByUUID(@PathParam(TYPE_PATH_PARAM) SclF
public Uni findByUUID(@PathParam(TYPE_PATH_PARAM) SclFileType type,
@PathParam(ID_PATH_PARAM) UUID id) {
LOGGER.info("Retrieving latest version of SCL File {} for type {} from storage.", id, type);
+ String tenant = tenantService.resolveTenant();
var response = new GetResponse();
- response.setSclData(compasSclDataService.findByUUID(type, id));
+ response.setSclData(compasSclDataService.findByUUID(tenant, type, id));
return Uni.createFrom().item(response);
}
@@ -98,8 +107,9 @@ public Uni findByUUIDAndVersion(@PathParam(TYPE_PATH_PARAM) SclFile
@PathParam(ID_PATH_PARAM) UUID id,
@PathParam(VERSION_PATH_PARAM) Version version) {
LOGGER.info("Retrieving version {} of SCL File {} for type {} from storage.", version, id, type);
+ String tenant = tenantService.resolveTenant();
var response = new GetResponse();
- response.setSclData(compasSclDataService.findByUUID(type, id, version));
+ response.setSclData(compasSclDataService.findByUUID(tenant, type, id, version));
return Uni.createFrom().item(response);
}
@@ -114,9 +124,11 @@ public Uni update(@PathParam(TYPE_PATH_PARAM) SclFileType type,
LOGGER.info("Updating SCL File {} for type {} to storage.", id, type);
String who = jsonWebToken.getClaim(userInfoProperties.who());
LOGGER.trace("Username used for Who {}", who);
+ String tenant = tenantService.resolveTenant();
+ LOGGER.trace("Tenant resolved as {}", tenant);
var response = new UpdateResponse();
- response.setSclData(compasSclDataService.update(type, id, request.getChangeSetType(), who, request.getComment(),
+ response.setSclData(compasSclDataService.update(tenant, type, id, request.getChangeSetType(), who, request.getComment(),
request.getSclData()));
return Uni.createFrom().item(response);
}
@@ -128,7 +140,8 @@ public Uni update(@PathParam(TYPE_PATH_PARAM) SclFileType type,
public Uni deleteAll(@PathParam(TYPE_PATH_PARAM) SclFileType type,
@PathParam(ID_PATH_PARAM) UUID id) {
LOGGER.info("Removing all versions of SCL File {} for type {} from storage.", id, type);
- compasSclDataService.delete(type, id);
+ String tenant = tenantService.resolveTenant();
+ compasSclDataService.delete(tenant, type, id);
return Uni.createFrom().nullItem();
}
@@ -140,7 +153,8 @@ public Uni deleteVersion(@PathParam(TYPE_PATH_PARAM) SclFileType type,
@PathParam(ID_PATH_PARAM) UUID id,
@PathParam(VERSION_PATH_PARAM) Version version) {
LOGGER.info("Removing version {} of SCL File {} for type {} from storage.", version, id, type);
- compasSclDataService.delete(type, id, version);
+ String tenant = tenantService.resolveTenant();
+ compasSclDataService.delete(tenant, type, id, version);
return Uni.createFrom().nullItem();
}
@@ -151,9 +165,10 @@ public Uni deleteVersion(@PathParam(TYPE_PATH_PARAM) SclFileType type,
public Uni checkDuplicateName(@PathParam(TYPE_PATH_PARAM) SclFileType type,
@Valid DuplicateNameCheckRequest request) {
LOGGER.info("Checking for duplicate SCL File name.");
+ String tenant = tenantService.resolveTenant();
var response = new DuplicateNameCheckResponse();
- response.setDuplicate(compasSclDataService.hasDuplicateSclName(type, request.getName()));
+ response.setDuplicate(compasSclDataService.hasDuplicateSclName(tenant, type, request.getName()));
return Uni.createFrom().item(response);
}
}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceService.java b/app/src/main/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceService.java
index 23a478aa..3604eafd 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceService.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceService.java
@@ -28,7 +28,6 @@
public class CompasPluginsResourceService {
private static final Logger LOGGER = LogManager.getLogger(CompasPluginsResourceService.class);
- private static final String DEFAULT_TENANT = "default";
private static final List ALLOWED_CONTENT_TYPES = List.of(
@@ -44,11 +43,12 @@ public CompasPluginsResourceService(EntityManager entityManager) {
}
@Transactional(SUPPORTS)
- public List list(String type, Date uploadedAfter, Date uploadedBefore,
+ public List list(String tenant, String type, Date uploadedAfter, Date uploadedBefore,
String name, int page, int size) {
- var queryBuilder = new StringBuilder("SELECT e FROM PluginsCustomResource e WHERE e.type = :type");
+ var queryBuilder = new StringBuilder("SELECT e FROM PluginsCustomResource e WHERE e.type = :type AND e.tenant = :tenant");
var params = new HashMap();
params.put("type", type);
+ params.put("tenant", tenant);
appendFilters(queryBuilder, params, uploadedAfter, uploadedBefore, name);
queryBuilder.append(" ORDER BY e.uploadedAt DESC");
@@ -61,10 +61,11 @@ public List list(String type, Date uploadedAfter, Date up
}
@Transactional(SUPPORTS)
- public long count(String type, Date uploadedAfter, Date uploadedBefore, String name) {
- var queryBuilder = new StringBuilder("SELECT COUNT(e) FROM PluginsCustomResource e WHERE e.type = :type");
+ public long count(String tenant, String type, Date uploadedAfter, Date uploadedBefore, String name) {
+ var queryBuilder = new StringBuilder("SELECT COUNT(e) FROM PluginsCustomResource e WHERE e.type = :type AND e.tenant = :tenant");
var params = new HashMap();
params.put("type", type);
+ params.put("tenant", tenant);
appendFilters(queryBuilder, params, uploadedAfter, uploadedBefore, name);
@@ -84,20 +85,20 @@ public PluginsCustomResource findById(UUID id) {
}
@Transactional(REQUIRED)
- public PluginsCustomResource upload(UploadCustomPluginsResourceData request) {
+ public PluginsCustomResource upload(String tenant, UploadCustomPluginsResourceData request) {
LOGGER.info("Uploading plugins custom resource type='{}', name='{}'", request.type(), request.name());
validateContentType(request.contentType());
validateSemver(request.dataCompatibilityVersion(), "data-compatibility-version");
- String resolvedVersion = resolveVersion(request.type(), request.name(), request.version(), request.nextVersionType());
+ String resolvedVersion = resolveVersion(tenant, request.type(), request.name(), request.version(), request.nextVersionType());
Long duplicateCount = entityManager.createQuery(
"SELECT COUNT(e) FROM PluginsCustomResource e " +
"WHERE e.type = :type AND e.tenant = :tenant AND e.name = :name AND e.version = :version",
Long.class)
.setParameter("type", request.type())
- .setParameter("tenant", DEFAULT_TENANT)
+ .setParameter("tenant", tenant)
.setParameter("name", request.name())
.setParameter("version", resolvedVersion)
.getSingleResult();
@@ -110,7 +111,7 @@ public PluginsCustomResource upload(UploadCustomPluginsResourceData request) {
var entity = new PluginsCustomResource();
entity.type = request.type();
- entity.tenant = DEFAULT_TENANT;
+ entity.tenant = tenant;
entity.name = request.name();
entity.description = request.description();
entity.contentType = request.contentType();
@@ -123,7 +124,7 @@ public PluginsCustomResource upload(UploadCustomPluginsResourceData request) {
return entity;
}
- private String resolveVersion(String type, String name,
+ private String resolveVersion(String tenant, String type, String name,
String explicitVersion, String nextVersionType) {
if (explicitVersion != null && !explicitVersion.isBlank()) {
validateSemver(explicitVersion, "version");
@@ -137,20 +138,20 @@ private String resolveVersion(String type, String name,
throw new CompasInvalidInputException(
"Invalid nextVersionType: must be 'major', 'minor', or 'patch'");
}
- return findLatestVersionAndIncrement(type, name, changeSetType);
+ return findLatestVersionAndIncrement(tenant, type, name, changeSetType);
}
throw new CompasInvalidInputException(
"Either 'version' or 'nextVersionType' must be provided");
}
- private String findLatestVersionAndIncrement(String type, String name,
+ private String findLatestVersionAndIncrement(String tenant, String type, String name,
ChangeSetType changeSetType) {
List existing = entityManager.createQuery(
"SELECT e FROM PluginsCustomResource e " +
"WHERE e.type = :type AND e.tenant = :tenant AND e.name = :name",
PluginsCustomResource.class)
.setParameter("type", type)
- .setParameter("tenant", DEFAULT_TENANT)
+ .setParameter("tenant", tenant)
.setParameter("name", name)
.getResultList();
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandler.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandler.java
index b4e46cd8..16ff4fd1 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandler.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandler.java
@@ -33,7 +33,7 @@ public CompasSclDataEventHandler(CompasSclDataService compasSclDataService) {
public void createWebsocketsEvent(CreateEventRequest request) {
new WebsocketHandler().execute(request.getSession(), () -> {
var response = new CreateWsResponse();
- response.setSclData(compasSclDataService.create(request.getType(), request.getName(), request.getWho(),
+ response.setSclData(compasSclDataService.create(request.getTenant(), request.getType(), request.getName(), request.getWho(),
request.getComment(), request.getSclData()));
return response;
});
@@ -43,7 +43,7 @@ public void createWebsocketsEvent(CreateEventRequest request) {
public void getWebsocketsEvent(GetEventRequest request) {
new WebsocketHandler().execute(request.getSession(), () -> {
var response = new GetWsResponse();
- response.setSclData(compasSclDataService.findByUUID(request.getType(), request.getId()));
+ response.setSclData(compasSclDataService.findByUUID(request.getTenant(), request.getType(), request.getId()));
return response;
});
}
@@ -52,7 +52,7 @@ public void getWebsocketsEvent(GetEventRequest request) {
public void getVersionWebsocketsEvent(GetVersionEventRequest request) {
new WebsocketHandler().execute(request.getSession(), () -> {
var response = new GetWsResponse();
- response.setSclData(compasSclDataService.findByUUID(request.getType(), request.getId(), request.getVersion()));
+ response.setSclData(compasSclDataService.findByUUID(request.getTenant(), request.getType(), request.getId(), request.getVersion()));
return response;
});
}
@@ -61,7 +61,7 @@ public void getVersionWebsocketsEvent(GetVersionEventRequest request) {
public void updateWebsocketsEvent(UpdateEventRequest request) {
new WebsocketHandler().execute(request.getSession(), () -> {
var response = new UpdateWsResponse();
- response.setSclData(compasSclDataService.update(request.getType(), request.getId(), request.getChangeSetType(),
+ response.setSclData(compasSclDataService.update(request.getTenant(), request.getType(), request.getId(), request.getChangeSetType(),
request.getWho(), request.getComment(), request.getSclData()));
return response;
});
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequest.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequest.java
index 3665ba5e..95d5d990 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequest.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequest.java
@@ -14,14 +14,16 @@ public class CreateEventRequest {
private final String who;
private final String comment;
private final String sclData;
+ private final String tenant;
- public CreateEventRequest(Session session, SclFileType type, String name, String who, String comment, String sclData) {
+ public CreateEventRequest(Session session, SclFileType type, String name, String who, String comment, String sclData, String tenant) {
this.session = session;
this.type = type;
this.name = name;
this.who = who;
this.comment = comment;
this.sclData = sclData;
+ this.tenant = tenant;
}
public Session getSession() {
@@ -47,4 +49,8 @@ public String getComment() {
public String getSclData() {
return sclData;
}
+
+ public String getTenant() {
+ return tenant;
+ }
}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequest.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequest.java
index 089a4778..2a4eb339 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequest.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequest.java
@@ -12,11 +12,13 @@ public class GetEventRequest {
private final Session session;
private final SclFileType type;
private final UUID id;
+ private final String tenant;
- public GetEventRequest(Session session, SclFileType type, UUID id) {
+ public GetEventRequest(Session session, SclFileType type, UUID id, String tenant) {
this.session = session;
this.type = type;
this.id = id;
+ this.tenant = tenant;
}
public Session getSession() {
@@ -30,4 +32,8 @@ public SclFileType getType() {
public UUID getId() {
return id;
}
+
+ public String getTenant() {
+ return tenant;
+ }
}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequest.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequest.java
index ec3f96e6..d749535c 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequest.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequest.java
@@ -14,12 +14,14 @@ public class GetVersionEventRequest {
private final SclFileType type;
private final UUID id;
private final Version version;
+ private final String tenant;
- public GetVersionEventRequest(Session session, SclFileType type, UUID id, Version version) {
+ public GetVersionEventRequest(Session session, SclFileType type, UUID id, Version version, String tenant) {
this.session = session;
this.type = type;
this.id = id;
this.version = version;
+ this.tenant = tenant;
}
public Session getSession() {
@@ -37,4 +39,8 @@ public UUID getId() {
public Version getVersion() {
return version;
}
+
+ public String getTenant() {
+ return tenant;
+ }
}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequest.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequest.java
index 5b81d808..54cf7260 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequest.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequest.java
@@ -17,8 +17,9 @@ public class UpdateEventRequest {
private final String who;
private final String comment;
private final String sclData;
+ private final String tenant;
- public UpdateEventRequest(Session session, SclFileType type, UUID id, ChangeSetType changeSetType, String who, String comment, String sclData) {
+ public UpdateEventRequest(Session session, SclFileType type, UUID id, ChangeSetType changeSetType, String who, String comment, String sclData, String tenant) {
this.session = session;
this.type = type;
this.id = id;
@@ -26,6 +27,7 @@ public UpdateEventRequest(Session session, SclFileType type, UUID id, ChangeSetT
this.who = who;
this.comment = comment;
this.sclData = sclData;
+ this.tenant = tenant;
}
public Session getSession() {
@@ -55,4 +57,8 @@ public String getComment() {
public String getSclData() {
return sclData;
}
+
+ public String getTenant() {
+ return tenant;
+ }
}
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpoint.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpoint.java
index 1015f0e0..6dbad21e 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpoint.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpoint.java
@@ -9,6 +9,7 @@
import org.apache.logging.log4j.Logger;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.lfenergy.compas.core.websocket.ErrorResponseEncoder;
+import org.lfenergy.compas.scl.data.rest.TenantService;
import org.lfenergy.compas.scl.data.rest.UserInfoProperties;
import org.lfenergy.compas.scl.data.websocket.event.model.CreateEventRequest;
import org.lfenergy.compas.scl.data.websocket.v1.decoder.CreateWsRequestDecoder;
@@ -39,14 +40,17 @@ public class CompasSclCreateServerEndpoint {
private final EventBus eventBus;
private final JsonWebToken jsonWebToken;
private final UserInfoProperties userInfoProperties;
+ private final TenantService tenantService;
@Inject
public CompasSclCreateServerEndpoint(EventBus eventBus,
JsonWebToken jsonWebToken,
- UserInfoProperties userInfoProperties) {
+ UserInfoProperties userInfoProperties,
+ TenantService tenantService) {
this.eventBus = eventBus;
this.jsonWebToken = jsonWebToken;
this.userInfoProperties = userInfoProperties;
+ this.tenantService = tenantService;
}
@OnOpen
@@ -74,7 +78,7 @@ public void onCreateMessage(Session session,
LOGGER.trace("Username used for Who {}", who);
eventBus.send("create-ws", new CreateEventRequest(
- session, SclFileType.valueOf(type), request.getName(), who, request.getComment(), request.getSclData()));
+ session, SclFileType.valueOf(type), request.getName(), who, request.getComment(), request.getSclData(), tenantService.resolveTenant()));
}
@OnError
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpoint.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpoint.java
index 68bf896f..02a5389a 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpoint.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpoint.java
@@ -20,6 +20,7 @@
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
+import org.lfenergy.compas.scl.data.rest.TenantService;
import static org.lfenergy.compas.core.websocket.WebsocketSupport.handleException;
import static org.lfenergy.compas.scl.data.rest.Constants.TYPE_PATH_PARAM;
@@ -33,10 +34,12 @@ public class CompasSclGetServerEndpoint {
private static final Logger LOGGER = LogManager.getLogger(CompasSclGetServerEndpoint.class);
private final EventBus eventBus;
+ private final TenantService tenantService;
@Inject
- public CompasSclGetServerEndpoint(EventBus eventBus) {
+ public CompasSclGetServerEndpoint(EventBus eventBus, TenantService tenantService) {
this.eventBus = eventBus;
+ this.tenantService = tenantService;
}
@OnOpen
@@ -50,7 +53,7 @@ public void onGetMessage(Session session,
@PathParam(TYPE_PATH_PARAM) String type) {
LOGGER.info("Message (get) from session {} for type {}.", session.getId(), type);
- eventBus.send("get-ws", new GetEventRequest(session, SclFileType.valueOf(type), request.getId()));
+ eventBus.send("get-ws", new GetEventRequest(session, SclFileType.valueOf(type), request.getId(), tenantService.resolveTenant()));
}
@OnError
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpoint.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpoint.java
index ecafcdec..1d31a66e 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpoint.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpoint.java
@@ -21,6 +21,7 @@
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
+import org.lfenergy.compas.scl.data.rest.TenantService;
import static org.lfenergy.compas.core.websocket.WebsocketSupport.handleException;
import static org.lfenergy.compas.scl.data.rest.Constants.TYPE_PATH_PARAM;
@@ -34,10 +35,12 @@ public class CompasSclGetVersionServerEndpoint {
private static final Logger LOGGER = LogManager.getLogger(CompasSclGetVersionServerEndpoint.class);
private final EventBus eventBus;
+ private final TenantService tenantService;
@Inject
- public CompasSclGetVersionServerEndpoint(EventBus eventBus) {
+ public CompasSclGetVersionServerEndpoint(EventBus eventBus, TenantService tenantService) {
this.eventBus = eventBus;
+ this.tenantService = tenantService;
}
@OnOpen
@@ -52,7 +55,7 @@ public void onGetVersionMessage(Session session,
LOGGER.info("Message from session {} for type {}.", session.getId(), type);
eventBus.send("get-version-ws", new GetVersionEventRequest(session, SclFileType.valueOf(type),
- request.getId(), new Version(request.getVersion())));
+ request.getId(), new Version(request.getVersion()), tenantService.resolveTenant()));
}
@OnError
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpoint.java b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpoint.java
index 9cf7ddf2..924c880a 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpoint.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpoint.java
@@ -9,6 +9,7 @@
import org.apache.logging.log4j.Logger;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.lfenergy.compas.core.websocket.ErrorResponseEncoder;
+import org.lfenergy.compas.scl.data.rest.TenantService;
import org.lfenergy.compas.scl.data.rest.UserInfoProperties;
import org.lfenergy.compas.scl.data.websocket.event.model.UpdateEventRequest;
import org.lfenergy.compas.scl.data.websocket.v1.decoder.UpdateWsRequestDecoder;
@@ -39,14 +40,17 @@ public class CompasSclUpdateServerEndpoint {
private final EventBus eventBus;
private final JsonWebToken jsonWebToken;
private final UserInfoProperties userInfoProperties;
+ private final TenantService tenantService;
@Inject
public CompasSclUpdateServerEndpoint(EventBus eventBus,
JsonWebToken jsonWebToken,
- UserInfoProperties userInfoProperties) {
+ UserInfoProperties userInfoProperties,
+ TenantService tenantService) {
this.eventBus = eventBus;
this.jsonWebToken = jsonWebToken;
this.userInfoProperties = userInfoProperties;
+ this.tenantService = tenantService;
}
@OnOpen
@@ -75,7 +79,7 @@ public void onUpdateMessage(Session session,
eventBus.send("update-ws", new UpdateEventRequest(
session, SclFileType.valueOf(type), request.getId(), request.getChangeSetType(),
- who, request.getComment(), request.getSclData()));
+ who, request.getComment(), request.getSclData(), tenantService.resolveTenant()));
}
@OnError
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java
new file mode 100644
index 00000000..d71f14e9
--- /dev/null
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: 2026 Alliander N.V.
+//
+// SPDX-License-Identifier: Apache-2.0
+package org.lfenergy.compas.scl.data.rest;
+
+import org.eclipse.microprofile.jwt.JsonWebToken;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.lfenergy.compas.scl.data.SclDataServiceConstants.GLOBAL_TENANT;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class TenantServiceTest {
+
+ @Mock
+ private JsonWebToken jsonWebToken;
+
+ @InjectMocks
+ private TenantService tenantService;
+
+ @Test
+ void resolveTenant_WhenIssuerIsNull_ThenReturnsGlobalTenant() {
+ when(jsonWebToken.getIssuer()).thenReturn(null);
+
+ assertEquals(GLOBAL_TENANT, tenantService.resolveTenant());
+ }
+
+ @Test
+ void resolveTenant_WhenIssuerIsBlank_ThenReturnsGlobalTenant() {
+ when(jsonWebToken.getIssuer()).thenReturn(" ");
+
+ assertEquals(GLOBAL_TENANT, tenantService.resolveTenant());
+ }
+
+ @Test
+ void resolveTenant_WhenIssuerHasRealmPath_ThenReturnsRealmAssTenant() {
+ when(jsonWebToken.getIssuer()).thenReturn("http://host/auth/realms/compas");
+
+ assertEquals("compas", tenantService.resolveTenant());
+ }
+
+ @Test
+ void resolveTenant_WhenIssuerHasDifferentRealm_ThenReturnsCorrectTenant() {
+ when(jsonWebToken.getIssuer()).thenReturn("http://keycloak.example.com/realms/my-company");
+
+ assertEquals("my-company", tenantService.resolveTenant());
+ }
+
+ @Test
+ void resolveTenant_WhenIssuerHasNoPath_ThenReturnsGlobalTenant() {
+ when(jsonWebToken.getIssuer()).thenReturn("http://host");
+
+ // "http://host" has a last slash at position 6 (before "host"),
+ // so host is extracted as tenant
+ assertEquals("host", tenantService.resolveTenant());
+ }
+
+ @Test
+ void resolveTenant_WhenGetIssuerThrowsException_ThenReturnsGlobalTenant() {
+ when(jsonWebToken.getIssuer()).thenThrow(new RuntimeException("No token"));
+
+ assertEquals(GLOBAL_TENANT, tenantService.resolveTenant());
+ }
+}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceGetDataTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceGetDataTest.java
index 845c9a45..8636f616 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceGetDataTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceGetDataTest.java
@@ -30,11 +30,14 @@
@TestSecurity(user = "test-user")
@TestHTTPEndpoint(CompasPluginsResource.class)
class CompasPluginsResourceGetDataTest {
-
+ private static final String TENANT = "test-tenant";
@InjectMock
private CompasPluginsResourceService compasPluginsResourceService;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@Test
void getDataById_WhenCalledWithValidUUID_ThenReturnsResource() {
@@ -82,9 +85,10 @@ void getAllData_WhenCalledWithValidTypeAndNoFilters_ThenReturnsListOfResources()
var resource2 = createTestResource();
resource2.name = "another-resource";
- when(compasPluginsResourceService.list(eq(type), any(), any(), any(), eq(page), eq(size)))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasPluginsResourceService.list(eq(TENANT), eq(type), any(), any(), any(), eq(page), eq(size)))
.thenReturn(List.of(resource1, resource2));
- when(compasPluginsResourceService.count(eq(type), any(), any(), any()))
+ when(compasPluginsResourceService.count(eq(TENANT), eq(type), any(), any(), any()))
.thenReturn(2L);
given()
@@ -112,9 +116,10 @@ void getAllData_WhenCalledWithPaginationParameters_ThenReturnsPagedResponse() {
var resource = createTestResource();
- when(compasPluginsResourceService.list(eq(type), any(), any(), any(), eq(page), eq(size)))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasPluginsResourceService.list(eq(TENANT), eq(type), any(), any(), any(), eq(page), eq(size)))
.thenReturn(List.of(resource));
- when(compasPluginsResourceService.count(eq(type), any(), any(), any()))
+ when(compasPluginsResourceService.count(eq(TENANT), eq(type), any(), any(), any()))
.thenReturn(6L); // e.g. 6 total entries -> 2 pages of 5
given()
@@ -138,9 +143,10 @@ void getAllData_WhenCalledWithNonMatchingFilters_ThenReturnsEmptyContent() {
int page = 0;
int size = 20;
- when(compasPluginsResourceService.list(eq(type), any(), any(), any(), eq(page), eq(size)))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasPluginsResourceService.list(eq(TENANT), eq(type), any(), any(), any(), eq(page), eq(size)))
.thenReturn(List.of());
- when(compasPluginsResourceService.count(eq(type), any(), any(), any()))
+ when(compasPluginsResourceService.count(eq(TENANT), eq(type), any(), any(), any()))
.thenReturn(0L);
given()
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceTest.java
index 3138bfb6..8ef1c738 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasPluginsResourceTest.java
@@ -23,18 +23,23 @@
@ExtendWith(MockitoExtension.class)
class CompasPluginsResourceTest {
+ private static final String TENANT = "test-tenant";
@Mock
CompasPluginsResourceService service;
+ @Mock
+ org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@InjectMocks
CompasPluginsResource resource;
@Test
void getAllData_WhenSizeIsZero_ThenTotalPagesIsZero() {
- when(service.list(eq("xml"), isNull(), isNull(), isNull(), eq(0), eq(0)))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.list(eq(TENANT), eq("xml"), isNull(), isNull(), isNull(), eq(0), eq(0)))
.thenReturn(List.of());
- when(service.count(eq("xml"), isNull(), isNull(), isNull()))
+ when(service.count(eq(TENANT), eq("xml"), isNull(), isNull(), isNull()))
.thenReturn(5L);
var response = resource.getAllData("xml", null, null, null, 0, 0);
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsEditorTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsEditorTest.java
index f918e7bd..2fd6c73e 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsEditorTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsEditorTest.java
@@ -40,10 +40,14 @@
})
class CompasSclDataResourceAsEditorTest {
public static final String USERNAME = "Test Editor";
+ private static final String TENANT = "test-tenant";
@InjectMock
private CompasSclDataService compasSclDataService;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@Test
void list_WhenCalled_ThenItemResponseRetrieved() {
var type = SclFileType.SCD;
@@ -52,7 +56,8 @@ void list_WhenCalled_ThenItemResponseRetrieved() {
var version = "1.0.0";
var labels = List.of("Label1");
- when(compasSclDataService.list(type))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.list(TENANT, type))
.thenReturn(Collections.singletonList(new Item(uuid.toString(), name, version, labels)));
var response = given()
@@ -68,7 +73,7 @@ void list_WhenCalled_ThenItemResponseRetrieved() {
assertEquals(name, xmlPath.get("ListResponse.Item[0].Name"));
assertEquals(version, xmlPath.get("ListResponse.Item[0].Version"));
assertEquals(labels.get(0), xmlPath.get("ListResponse.Item[0].Label"));
- verify(compasSclDataService).list(type);
+ verify(compasSclDataService).list(TENANT, type);
}
@Test
@@ -78,7 +83,8 @@ void listVersionsByUUID_WhenCalled_ThenItemResponseRetrieved() {
var name = "Name";
var version = "1.0.0";
- when(compasSclDataService.listVersionsByUUID(type, uuid))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.listVersionsByUUID(TENANT, type, uuid))
.thenReturn(Collections.singletonList(new HistoryItem(uuid.toString(), name, version, null, null, null)));
var response = given()
@@ -94,7 +100,7 @@ void listVersionsByUUID_WhenCalled_ThenItemResponseRetrieved() {
assertEquals(uuid.toString(), xmlPath.get("VersionsResponse.HistoryItem[0].Id"));
assertEquals(name, xmlPath.get("VersionsResponse.HistoryItem[0].Name"));
assertEquals(version, xmlPath.get("VersionsResponse.HistoryItem[0].Version"));
- verify(compasSclDataService).listVersionsByUUID(type, uuid);
+ verify(compasSclDataService).listVersionsByUUID(TENANT, type, uuid);
}
@Test
@@ -103,7 +109,8 @@ void findByUUID_WhenCalled_ThenSCLResponseRetrieved() throws IOException {
var uuid = UUID.randomUUID();
var scl = readSCL();
- when(compasSclDataService.findByUUID(type, uuid)).thenReturn(scl);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.findByUUID(TENANT, type, uuid)).thenReturn(scl);
var response = given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -115,7 +122,7 @@ void findByUUID_WhenCalled_ThenSCLResponseRetrieved() throws IOException {
.response();
assertEquals(scl, response.xmlPath().getString("GetResponse.SclData"));
- verify(compasSclDataService).findByUUID(type, uuid);
+ verify(compasSclDataService).findByUUID(TENANT, type, uuid);
}
@Test
@@ -125,7 +132,8 @@ void findByUUIDAndVersion_WhenCalled_ThenSCLResponseRetrieved() throws IOExcepti
var scl = readSCL();
var version = new Version(1, 2, 3);
- when(compasSclDataService.findByUUID(type, uuid, version)).thenReturn(scl);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.findByUUID(TENANT, type, uuid, version)).thenReturn(scl);
var response = given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -138,7 +146,7 @@ void findByUUIDAndVersion_WhenCalled_ThenSCLResponseRetrieved() throws IOExcepti
.response();
assertEquals(scl, response.xmlPath().getString("GetResponse.SclData"));
- verify(compasSclDataService).findByUUID(type, uuid, version);
+ verify(compasSclDataService).findByUUID(TENANT, type, uuid, version);
}
@Test
@@ -153,7 +161,8 @@ void create_WhenCalled_ThenServiceCalledAndUUIDRetrieved() throws IOException {
request.setComment(comment);
request.setSclData(scl);
- when(compasSclDataService.create(type, name, USERNAME, comment, scl)).thenReturn(scl);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.create(TENANT, type, name, USERNAME, comment, scl)).thenReturn(scl);
var response = given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -166,7 +175,7 @@ void create_WhenCalled_ThenServiceCalledAndUUIDRetrieved() throws IOException {
.response();
assertEquals(scl, response.xmlPath().getString("CreateResponse.SclData"));
- verify(compasSclDataService).create(type, name, USERNAME, comment, scl);
+ verify(compasSclDataService).create(TENANT, type, name, USERNAME, comment, scl);
}
@Test
@@ -209,7 +218,8 @@ void update_WhenCalled_ThenServiceCalledAndNewUUIDRetrieved() throws IOException
request.setComment(comment);
request.setSclData(scl);
- when(compasSclDataService.update(type, uuid, changeSetType, USERNAME, comment, scl)).thenReturn(scl);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.update(TENANT, type, uuid, changeSetType, USERNAME, comment, scl)).thenReturn(scl);
var response = given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -223,7 +233,7 @@ void update_WhenCalled_ThenServiceCalledAndNewUUIDRetrieved() throws IOException
.response();
assertEquals(scl, response.xmlPath().getString("UpdateResponse.SclData"));
- verify(compasSclDataService).update(type, uuid, changeSetType, USERNAME, comment, scl);
+ verify(compasSclDataService).update(TENANT, type, uuid, changeSetType, USERNAME, comment, scl);
}
@Test
@@ -231,7 +241,8 @@ void deleteAll_WhenCalled_ThenServiceCalled() {
var uuid = UUID.randomUUID();
var type = SclFileType.SCD;
- doNothing().when(compasSclDataService).delete(type, uuid);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ doNothing().when(compasSclDataService).delete(TENANT, type, uuid);
given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -240,7 +251,7 @@ void deleteAll_WhenCalled_ThenServiceCalled() {
.then()
.statusCode(204);
- verify(compasSclDataService).delete(type, uuid);
+ verify(compasSclDataService).delete(TENANT, type, uuid);
}
@Test
@@ -249,7 +260,8 @@ void deleteVersion_WhenCalled_ThenServiceCalled() {
var type = SclFileType.SCD;
var version = new Version(1, 2, 3);
- doNothing().when(compasSclDataService).delete(type, uuid, version);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ doNothing().when(compasSclDataService).delete(TENANT, type, uuid, version);
given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -259,7 +271,7 @@ void deleteVersion_WhenCalled_ThenServiceCalled() {
.then()
.statusCode(204);
- verify(compasSclDataService).delete(type, uuid, version);
+ verify(compasSclDataService).delete(TENANT, type, uuid, version);
}
@Test
@@ -267,7 +279,8 @@ void checkNameForDuplication_WhenCalled_WithDuplicateName_ThenServiceCalled() {
var type = SclFileType.SCD;
var name = "STATION-0012312";
- when(compasSclDataService.hasDuplicateSclName(type, name)).thenReturn(true);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.hasDuplicateSclName(TENANT, type, name)).thenReturn(true);
var request = new DuplicateNameCheckRequest();
request.setName(name);
@@ -282,7 +295,7 @@ void checkNameForDuplication_WhenCalled_WithDuplicateName_ThenServiceCalled() {
.extract()
.response();
- verify(compasSclDataService).hasDuplicateSclName(type, name);
+ verify(compasSclDataService).hasDuplicateSclName(TENANT, type, name);
assertTrue(response.xmlPath().getBoolean("DuplicateNameCheckResponse.Duplicate"));
}
@@ -291,7 +304,8 @@ void checkNameForDuplication_WhenCalled_WithUniqueName_ThenServiceCalled() {
var type = SclFileType.SCD;
var name = "STATION-0012312";
- when(compasSclDataService.hasDuplicateSclName(type, name)).thenReturn(false);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.hasDuplicateSclName(TENANT, type, name)).thenReturn(false);
var request = new DuplicateNameCheckRequest();
request.setName(name);
@@ -306,7 +320,7 @@ void checkNameForDuplication_WhenCalled_WithUniqueName_ThenServiceCalled() {
.extract()
.response();
- verify(compasSclDataService).hasDuplicateSclName(type, name);
+ verify(compasSclDataService).hasDuplicateSclName(TENANT, type, name);
assertFalse(response.xmlPath().getBoolean("DuplicateNameCheckResponse.Duplicate"));
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsReaderTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsReaderTest.java
index 3094631a..69f25177 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsReaderTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/rest/v1/CompasSclDataResourceAsReaderTest.java
@@ -27,15 +27,20 @@
import static org.lfenergy.compas.scl.data.rest.Constants.*;
import static org.mockito.Mockito.*;
import io.quarkus.test.InjectMock;
+import org.lfenergy.compas.scl.data.rest.TenantService;
@QuarkusTest
@TestHTTPEndpoint(CompasSclDataResource.class)
@TestSecurity(user = "test-reader", roles = {"SCD_" + READ_ROLE})
class CompasSclDataResourceAsReaderTest {
+ private static final String TENANT = "test-tenant";
@InjectMock
private CompasSclDataService compasSclDataService;
+ @InjectMock
+ private TenantService tenantService;
+
@Test
void list_WhenCalled_ThenItemResponseRetrieved() {
var type = SclFileType.SCD;
@@ -44,7 +49,8 @@ void list_WhenCalled_ThenItemResponseRetrieved() {
var version = "1.0.0";
var labels = List.of("Label1");
- when(compasSclDataService.list(type))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.list(TENANT, type))
.thenReturn(Collections.singletonList(new Item(uuid.toString(), name, version, labels)));
var response = given()
@@ -60,7 +66,7 @@ void list_WhenCalled_ThenItemResponseRetrieved() {
assertEquals(name, xmlPath.get("ListResponse.Item[0].Name"));
assertEquals(version, xmlPath.get("ListResponse.Item[0].Version"));
assertEquals(labels.get(0), xmlPath.get("ListResponse.Item[0].Label"));
- verify(compasSclDataService).list(type);
+ verify(compasSclDataService).list(TENANT, type);
}
@Test
@@ -70,7 +76,8 @@ void listVersionsByUUID_WhenCalled_ThenItemResponseRetrieved() {
var name = "Name";
var version = "1.0.0";
- when(compasSclDataService.listVersionsByUUID(type, uuid))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.listVersionsByUUID(TENANT, type, uuid))
.thenReturn(Collections.singletonList(new HistoryItem(uuid.toString(), name, version, null, null, null)));
var response = given()
@@ -86,7 +93,7 @@ void listVersionsByUUID_WhenCalled_ThenItemResponseRetrieved() {
assertEquals(uuid.toString(), xmlPath.get("VersionsResponse.HistoryItem[0].Id"));
assertEquals(name, xmlPath.get("VersionsResponse.HistoryItem[0].Name"));
assertEquals(version, xmlPath.get("VersionsResponse.HistoryItem[0].Version"));
- verify(compasSclDataService).listVersionsByUUID(type, uuid);
+ verify(compasSclDataService).listVersionsByUUID(TENANT, type, uuid);
}
@Test
@@ -95,7 +102,8 @@ void findByUUID_WhenCalled_ThenSCLResponseRetrieved() throws IOException {
var uuid = UUID.randomUUID();
var scl = readSCL();
- when(compasSclDataService.findByUUID(type, uuid)).thenReturn(scl);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.findByUUID(TENANT, type, uuid)).thenReturn(scl);
var response = given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -107,7 +115,7 @@ void findByUUID_WhenCalled_ThenSCLResponseRetrieved() throws IOException {
.response();
assertEquals(scl, response.xmlPath().getString("GetResponse.SclData"));
- verify(compasSclDataService).findByUUID(type, uuid);
+ verify(compasSclDataService).findByUUID(TENANT, type, uuid);
}
@Test
@@ -117,7 +125,8 @@ void findByUUIDAndVersion_WhenCalled_ThenSCLResponseRetrieved() throws IOExcepti
var scl = readSCL();
var version = new Version(1, 2, 3);
- when(compasSclDataService.findByUUID(type, uuid, version)).thenReturn(scl);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(compasSclDataService.findByUUID(TENANT, type, uuid, version)).thenReturn(scl);
var response = given()
.pathParam(TYPE_PATH_PARAM, type)
@@ -130,7 +139,7 @@ void findByUUIDAndVersion_WhenCalled_ThenSCLResponseRetrieved() throws IOExcepti
.response();
assertEquals(scl, response.xmlPath().getString("GetResponse.SclData"));
- verify(compasSclDataService).findByUUID(type, uuid, version);
+ verify(compasSclDataService).findByUUID(TENANT, type, uuid, version);
}
@Test
@@ -186,8 +195,6 @@ void deleteAll_WhenCalled_ThenServiceCalled() {
var uuid = UUID.randomUUID();
var type = SclFileType.SCD;
- doNothing().when(compasSclDataService).delete(type, uuid);
-
given()
.pathParam(TYPE_PATH_PARAM, type)
.pathParam(ID_PATH_PARAM, uuid)
@@ -204,8 +211,6 @@ void deleteVersion_WhenCalled_ThenServiceCalled() {
var type = SclFileType.SCD;
var version = new Version(1, 2, 3);
- doNothing().when(compasSclDataService).delete(type, uuid, version);
-
given()
.pathParam(TYPE_PATH_PARAM, type)
.pathParam(ID_PATH_PARAM, uuid)
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceServiceTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceServiceTest.java
index 3cecebe2..79d4634a 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceServiceTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/service/CompasPluginsResourceServiceTest.java
@@ -28,6 +28,7 @@
@ExtendWith(MockitoExtension.class)
class CompasPluginsResourceServiceTest {
+ private static final String TENANT = "test-tenant";
@Mock
EntityManager entityManager;
@@ -43,7 +44,7 @@ void list_WhenCalledWithTypeOnly_ThenReturnsResults() {
var resource = createResource();
when(query.getResultList()).thenReturn(List.of(resource));
- var result = service.list("xml", null, null, null, 0, 20);
+ var result = service.list(TENANT, "xml", null, null, null, 0, 20);
assertEquals(1, result.size());
assertEquals(resource, result.get(0));
@@ -56,7 +57,7 @@ void list_WhenCalledWithAllFilters_ThenAppliesAllFilters() {
var query = mockTypedQuery(PluginsCustomResource.class);
when(query.getResultList()).thenReturn(List.of());
- service.list("xml", new Date(), new Date(), "test", 1, 10);
+ service.list(TENANT, "xml", new Date(), new Date(), "test", 1, 10);
var jpqlCaptor = ArgumentCaptor.forClass(String.class);
verify(entityManager).createQuery(jpqlCaptor.capture(), eq(PluginsCustomResource.class));
@@ -76,7 +77,7 @@ void count_WhenCalledWithTypeOnly_ThenReturnsCount() {
var query = mockTypedQuery(Long.class);
when(query.getSingleResult()).thenReturn(5L);
- var result = service.count("xml", null, null, null);
+ var result = service.count(TENANT, "xml", null, null, null);
assertEquals(5L, result);
}
@@ -86,7 +87,7 @@ void count_WhenCalledWithFilters_ThenAppliesFilters() {
var query = mockTypedQuery(Long.class);
when(query.getSingleResult()).thenReturn(3L);
- var result = service.count("xml", new Date(), new Date(), "search");
+ var result = service.count(TENANT, "xml", new Date(), new Date(), "search");
assertEquals(3L, result);
var jpqlCaptor = ArgumentCaptor.forClass(String.class);
@@ -126,7 +127,7 @@ void upload_WhenCalledWithExplicitVersion_ThenPersistsEntity() {
var duplicateQuery = mockTypedQuery(Long.class);
when(duplicateQuery.getSingleResult()).thenReturn(0L);
- var result = service.upload(new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
+ var result = service.upload(TENANT, new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"1.0.0", "desc", "2.0.0", null));
verify(entityManager).persist(any(PluginsCustomResource.class));
@@ -137,7 +138,7 @@ void upload_WhenCalledWithExplicitVersion_ThenPersistsEntity() {
assertEquals("2.0.0", result.version);
assertEquals("1.0.0", result.dataCompatibilityVersion);
assertEquals("desc", result.description);
- assertEquals("default", result.tenant);
+ assertEquals(TENANT, result.tenant);
}
@Test
@@ -147,7 +148,7 @@ void upload_WhenDuplicateVersionExists_ThenThrowsCompasDuplicateVersionException
var request = new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"1.0.0", "desc", "2.0.0", null);
- assertThrows(CompasDuplicateVersionException.class, () -> service.upload(request));
+ assertThrows(CompasDuplicateVersionException.class, () -> service.upload(TENANT, request));
}
@ParameterizedTest
@@ -161,7 +162,7 @@ void upload_WhenNextVersionType_ThenIncrementsVersion(String nextVersionType, St
existing.version = "1.2.3";
when(existingQuery.getResultList()).thenReturn(List.of(existing));
- var result = service.upload(new UploadCustomPluginsResourceData("xml", "name", "application/json", "{}",
+ var result = service.upload(TENANT, new UploadCustomPluginsResourceData("xml", "name", "application/json", "{}",
"1.0.0", "desc", null, nextVersionType));
assertEquals(expectedVersion, result.version);
@@ -175,7 +176,7 @@ void upload_WhenNextVersionTypeWithNoExistingVersions_ThenReturns100() {
var existingQuery = mockTypedQuery(PluginsCustomResource.class);
when(existingQuery.getResultList()).thenReturn(List.of());
- var result = service.upload(new UploadCustomPluginsResourceData("xml", "name", "application/json", "{}",
+ var result = service.upload(TENANT, new UploadCustomPluginsResourceData("xml", "name", "application/json", "{}",
"1.0.0", "desc", null, "MAJOR"));
assertEquals("1.0.0", result.version);
@@ -185,21 +186,21 @@ void upload_WhenNextVersionTypeWithNoExistingVersions_ThenReturns100() {
void upload_WhenInvalidNextVersionType_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"1.0.0", "desc", null, "INVALID");
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
@Test
void upload_WhenNoVersionAndNoNextVersionType_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"1.0.0", "desc", null, null);
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
@Test
void upload_WhenBlankVersionAndBlankNextVersionType_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"1.0.0", "desc", " ", " ");
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
// --- validation ---
@@ -208,28 +209,28 @@ void upload_WhenBlankVersionAndBlankNextVersionType_ThenThrowsCompasInvalidInput
void upload_WhenInvalidContentType_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", "text/plain", "",
"1.0.0", "desc", "1.0.0", null);
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
@Test
void upload_WhenNullContentType_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", null, "",
"1.0.0", "desc", "1.0.0", null);
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
@Test
void upload_WhenInvalidSemverForDataCompatibilityVersion_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"not-a-version", "desc", "1.0.0", null);
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
@Test
void upload_WhenInvalidSemverForExplicitVersion_ThenThrowsCompasInvalidInputException() {
var request = new UploadCustomPluginsResourceData("xml", "name", "application/xml", "",
"1.0.0", "desc", "bad", null);
- assertThrows(CompasInvalidInputException.class, () -> service.upload(request));
+ assertThrows(CompasInvalidInputException.class, () -> service.upload(TENANT, request));
}
// --- helpers ---
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandlerTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandlerTest.java
index d937f833..bd829878 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandlerTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/CompasSclDataEventHandlerTest.java
@@ -36,6 +36,8 @@
@ExtendWith(MockitoExtension.class)
class CompasSclDataEventHandlerTest {
+ private static final String TENANT = "test-tenant";
+
@Mock
private CompasSclDataService service;
@@ -51,14 +53,14 @@ void createWebsocketsEvent_WhenCalled_ThenCreateResponseReturned() {
var sclData = "Some SCL Data";
var session = mockSession();
- var request = new CreateEventRequest(session, type, name, who, comment, sclData);
- when(service.create(type, name, who, comment, sclData)).thenReturn(sclData);
+ var request = new CreateEventRequest(session, type, name, who, comment, sclData, TENANT);
+ when(service.create(TENANT, type, name, who, comment, sclData)).thenReturn(sclData);
eventHandler.createWebsocketsEvent(request);
var response = verifyResponse(session, CreateWsResponse.class);
assertEquals(sclData, response.getSclData());
- verify(service).create(type, name, who, comment, sclData);
+ verify(service).create(TENANT, type, name, who, comment, sclData);
}
@Test
@@ -71,14 +73,14 @@ void createWebsocketsEvent_WhenCalledAndCompasExceptionThrownByService_ThenError
var errorMessage = "Some Error";
var session = mockSession();
- var request = new CreateEventRequest(session, type, name, who, comment, sclData);
- when(service.create(type, name, who, comment, sclData))
+ var request = new CreateEventRequest(session, type, name, who, comment, sclData, TENANT);
+ when(service.create(TENANT, type, name, who, comment, sclData))
.thenThrow(new CompasException(DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage));
eventHandler.createWebsocketsEvent(request);
verifyErrorResponse(session, DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage);
- verify(service).create(type, name, who, comment, sclData);
+ verify(service).create(TENANT, type, name, who, comment, sclData);
}
@Test
@@ -91,13 +93,13 @@ void createWebsocketsEvent_WhenCalledAndRuntimeExceptionThrownByService_ThenErro
var errorMessage = "Some Error";
var session = mockSession();
- var request = new CreateEventRequest(session, type, name, who, comment, sclData);
- when(service.create(type, name, who, comment, sclData)).thenThrow(new RuntimeException(errorMessage));
+ var request = new CreateEventRequest(session, type, name, who, comment, sclData, TENANT);
+ when(service.create(TENANT, type, name, who, comment, sclData)).thenThrow(new RuntimeException(errorMessage));
eventHandler.createWebsocketsEvent(request);
verifyErrorResponse(session, WEBSOCKET_GENERAL_ERROR_CODE, errorMessage);
- verify(service).create(type, name, who, comment, sclData);
+ verify(service).create(TENANT, type, name, who, comment, sclData);
}
@Test
@@ -107,14 +109,14 @@ void getWebsocketsEvent_WhenCalled_ThenGetResponseReturned() {
var sclData = "Some SCL Data";
var session = mockSession();
- var request = new GetEventRequest(session, type, id);
- when(service.findByUUID(type, id)).thenReturn(sclData);
+ var request = new GetEventRequest(session, type, id, TENANT);
+ when(service.findByUUID(TENANT, type, id)).thenReturn(sclData);
eventHandler.getWebsocketsEvent(request);
var response = verifyResponse(session, GetWsResponse.class);
assertEquals(sclData, response.getSclData());
- verify(service).findByUUID(type, id);
+ verify(service).findByUUID(TENANT, type, id);
}
@Test
@@ -124,14 +126,14 @@ void getWebsocketsEvent_WhenCalledAndCompasExceptionThrownByService_ThenErrorRes
var errorMessage = "Some Error";
var session = mockSession();
- var request = new GetEventRequest(session, type, id);
- when(service.findByUUID(type, id))
+ var request = new GetEventRequest(session, type, id, TENANT);
+ when(service.findByUUID(TENANT, type, id))
.thenThrow(new CompasException(DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage));
eventHandler.getWebsocketsEvent(request);
verifyErrorResponse(session, DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage);
- verify(service).findByUUID(type, id);
+ verify(service).findByUUID(TENANT, type, id);
}
@Test
@@ -141,13 +143,13 @@ void getWebsocketsEvent_WhenCalledAndRuntimeExceptionThrownByService_ThenErrorRe
var errorMessage = "Some Error";
var session = mockSession();
- var request = new GetEventRequest(session, type, id);
- when(service.findByUUID(type, id)).thenThrow(new RuntimeException(errorMessage));
+ var request = new GetEventRequest(session, type, id, TENANT);
+ when(service.findByUUID(TENANT, type, id)).thenThrow(new RuntimeException(errorMessage));
eventHandler.getWebsocketsEvent(request);
verifyErrorResponse(session, WEBSOCKET_GENERAL_ERROR_CODE, errorMessage);
- verify(service).findByUUID(type, id);
+ verify(service).findByUUID(TENANT, type, id);
}
@Test
@@ -158,14 +160,14 @@ void getVersionWebsocketsEvent_WhenCalled_ThenGetResponseReturned() {
var version = new Version("1.2.3");
var session = mockSession();
- var request = new GetVersionEventRequest(session, type, id, version);
- when(service.findByUUID(type, id, version)).thenReturn(sclData);
+ var request = new GetVersionEventRequest(session, type, id, version, TENANT);
+ when(service.findByUUID(TENANT, type, id, version)).thenReturn(sclData);
eventHandler.getVersionWebsocketsEvent(request);
var response = verifyResponse(session, GetWsResponse.class);
assertEquals(sclData, response.getSclData());
- verify(service).findByUUID(type, id, version);
+ verify(service).findByUUID(TENANT, type, id, version);
}
@Test
@@ -176,14 +178,14 @@ void getVersionWebsocketsEvent_WhenCalledAndCompasExceptionThrownByService_ThenE
var errorMessage = "Some Error";
var session = mockSession();
- var request = new GetVersionEventRequest(session, type, id, version);
- when(service.findByUUID(type, id, version))
+ var request = new GetVersionEventRequest(session, type, id, version, TENANT);
+ when(service.findByUUID(TENANT, type, id, version))
.thenThrow(new CompasException(DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage));
eventHandler.getVersionWebsocketsEvent(request);
verifyErrorResponse(session, DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage);
- verify(service).findByUUID(type, id, version);
+ verify(service).findByUUID(TENANT, type, id, version);
}
@Test
@@ -194,13 +196,13 @@ void getVersionWebsocketsEvent_WhenCalledAndRuntimeExceptionThrownByService_Then
var errorMessage = "Some Error";
var session = mockSession();
- var request = new GetVersionEventRequest(session, type, id, version);
- when(service.findByUUID(type, id, version)).thenThrow(new RuntimeException(errorMessage));
+ var request = new GetVersionEventRequest(session, type, id, version, TENANT);
+ when(service.findByUUID(TENANT, type, id, version)).thenThrow(new RuntimeException(errorMessage));
eventHandler.getVersionWebsocketsEvent(request);
verifyErrorResponse(session, WEBSOCKET_GENERAL_ERROR_CODE, errorMessage);
- verify(service).findByUUID(type, id, version);
+ verify(service).findByUUID(TENANT, type, id, version);
}
@Test
@@ -213,14 +215,14 @@ void updateWebsocketsEvent_WhenCalled_ThenUpdateResponseReturned() {
var sclData = "Some SCL Data";
var session = mockSession();
- var request = new UpdateEventRequest(session, type, id, cst, who, comment, sclData);
- when(service.update(type, id, cst, who, comment, sclData)).thenReturn(sclData);
+ var request = new UpdateEventRequest(session, type, id, cst, who, comment, sclData, TENANT);
+ when(service.update(TENANT, type, id, cst, who, comment, sclData)).thenReturn(sclData);
eventHandler.updateWebsocketsEvent(request);
var response = verifyResponse(session, UpdateWsResponse.class);
assertEquals(sclData, response.getSclData());
- verify(service).update(type, id, cst, who, comment, sclData);
+ verify(service).update(TENANT, type, id, cst, who, comment, sclData);
}
@Test
@@ -234,14 +236,14 @@ void updateWebsocketsEvent_WhenCalledAndCompasExceptionThrownByService_ThenError
var errorMessage = "Some Error";
var session = mockSession();
- var request = new UpdateEventRequest(session, type, id, cst, who, comment, sclData);
- when(service.update(type, id, cst, who, comment, sclData))
+ var request = new UpdateEventRequest(session, type, id, cst, who, comment, sclData, TENANT);
+ when(service.update(TENANT, type, id, cst, who, comment, sclData))
.thenThrow(new CompasException(DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage));
eventHandler.updateWebsocketsEvent(request);
verifyErrorResponse(session, DUPLICATE_SCL_NAME_ERROR_CODE, errorMessage);
- verify(service).update(type, id, cst, who, comment, sclData);
+ verify(service).update(TENANT, type, id, cst, who, comment, sclData);
}
@Test
@@ -255,13 +257,13 @@ void updateWebsocketsEvent_WhenCalledAndRuntimeExceptionThrownByService_ThenErro
var errorMessage = "Some Error";
var session = mockSession();
- var request = new UpdateEventRequest(session, type, id, cst, who, comment, sclData);
- when(service.update(type, id, cst, who, comment, sclData)).thenThrow(new RuntimeException(errorMessage));
+ var request = new UpdateEventRequest(session, type, id, cst, who, comment, sclData, TENANT);
+ when(service.update(TENANT, type, id, cst, who, comment, sclData)).thenThrow(new RuntimeException(errorMessage));
eventHandler.updateWebsocketsEvent(request);
verifyErrorResponse(session, WEBSOCKET_GENERAL_ERROR_CODE, errorMessage);
- verify(service).update(type, id, cst, who, comment, sclData);
+ verify(service).update(TENANT, type, id, cst, who, comment, sclData);
}
private Session mockSession() {
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequestTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequestTest.java
index 60300868..32ef843c 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequestTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/CreateEventRequestTest.java
@@ -25,7 +25,7 @@ void constructor_WhenCalledWith3Arguments_ThenValuesSet() {
var comment = "Some comment";
var sclData = "Some SCL Data";
- var result = new CreateEventRequest(session, type, name, who, comment, sclData);
+ var result = new CreateEventRequest(session, type, name, who, comment, sclData, "test-tenant");
assertEquals(session, result.getSession());
assertEquals(type, result.getType());
@@ -33,6 +33,7 @@ void constructor_WhenCalledWith3Arguments_ThenValuesSet() {
assertEquals(who, result.getWho());
assertEquals(comment, result.getComment());
assertEquals(sclData, result.getSclData());
+ assertEquals("test-tenant", result.getTenant());
}
@Test
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequestTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequestTest.java
index 461d72ce..153e378e 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequestTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetEventRequestTest.java
@@ -23,11 +23,12 @@ void constructor_WhenCalledWith3Arguments_ThenValuesSet() {
var type = SclFileType.CID;
var id = UUID.randomUUID();
- var result = new GetEventRequest(session, type, id);
+ var result = new GetEventRequest(session, type, id, "test-tenant");
assertEquals(session, result.getSession());
assertEquals(type, result.getType());
assertEquals(id, result.getId());
+ assertEquals("test-tenant", result.getTenant());
}
@Test
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequestTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequestTest.java
index 0ca96c0a..1b238ce2 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequestTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/GetVersionEventRequestTest.java
@@ -25,12 +25,13 @@ void constructor_WhenCalledWith3Arguments_ThenValuesSet() {
var id = UUID.randomUUID();
var version = new Version("1.2.3");
- var result = new GetVersionEventRequest(session, type, id, version);
+ var result = new GetVersionEventRequest(session, type, id, version, "test-tenant");
assertEquals(session, result.getSession());
assertEquals(type, result.getType());
assertEquals(id, result.getId());
assertEquals(version, result.getVersion());
+ assertEquals("test-tenant", result.getTenant());
}
@Test
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequestTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequestTest.java
index 9c5fa4f4..ddaa64ea 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequestTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/event/model/UpdateEventRequestTest.java
@@ -28,7 +28,7 @@ void constructor_WhenCalledWith3Arguments_ThenValuesSet() {
var comment = "Some comment";
var sclData = "Some SCL Data";
- var result = new UpdateEventRequest(session, type, id, changeSetType, who, comment, sclData);
+ var result = new UpdateEventRequest(session, type, id, changeSetType, who, comment, sclData, "test-tenant");
assertEquals(session, result.getSession());
assertEquals(type, result.getType());
@@ -37,6 +37,7 @@ void constructor_WhenCalledWith3Arguments_ThenValuesSet() {
assertEquals(who, result.getWho());
assertEquals(comment, result.getComment());
assertEquals(sclData, result.getSclData());
+ assertEquals("test-tenant", result.getTenant());
}
@Test
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointAsEditorTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointAsEditorTest.java
index bf43e0b0..0b1d1117 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointAsEditorTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointAsEditorTest.java
@@ -25,9 +25,14 @@
@QuarkusTest
class CompasSclCreateServerEndpointAsEditorTest extends AbstractServerEndpointAsEditorTestSupport {
+ private static final String TENANT = "test-tenant";
+
@InjectMock
private CompasSclDataService service;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@TestHTTPResource("/scl-ws/v1/SCD/create")
private URI uri;
@@ -44,14 +49,15 @@ void createSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws Exception {
request.setComment(comment);
request.setSclData(sclData);
- when(service.create(sclFileTye, name, USERNAME, comment, sclData))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.create(TENANT, sclFileTye, name, USERNAME, comment, sclData))
.thenReturn(sclData);
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
session.getAsyncRemote().sendText(encoder.encode(request));
assertSclData(sclData);
- verify(service).create(sclFileTye, name, USERNAME, comment, sclData);
+ verify(service).create(TENANT, sclFileTye, name, USERNAME, comment, sclData);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointTest.java
index b44f5e67..5fb8de0a 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclCreateServerEndpointTest.java
@@ -18,7 +18,7 @@ class CompasSclCreateServerEndpointTest extends AbstractServerEndpointOnOpenTest
@Test
void onOpen_WhenSessionCloseThrowsIOException_ThenExceptionIsHandledGracefully() throws IOException {
- var endpoint = new CompasSclCreateServerEndpoint(null, jsonWebToken, null);
+ var endpoint = new CompasSclCreateServerEndpoint(null, jsonWebToken, null, null);
testOnOpenWhenSessionCloseThrowsIOException(jsonWebToken, endpoint::onOpen);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsEditorTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsEditorTest.java
index 8d1e1bc1..9f4fba27 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsEditorTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsEditorTest.java
@@ -26,9 +26,14 @@
@QuarkusTest
class CompasSclGetServerEndpointAsEditorTest extends AbstractServerEndpointAsEditorTestSupport {
+ private static final String TENANT = "test-tenant";
+
@InjectMock
private CompasSclDataService service;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@TestHTTPResource("/scl-ws/v1/SCD/get")
private URI uri;
@@ -42,13 +47,14 @@ void getSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws Exception {
var request = new GetWsRequest();
request.setId(id);
- when(service.findByUUID(sclFileTye, id)).thenReturn(sclData);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.findByUUID(TENANT, sclFileTye, id)).thenReturn(sclData);
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
session.getAsyncRemote().sendText(encoder.encode(request));
assertSclData(sclData);
- verify(service).findByUUID(sclFileTye, id);
+ verify(service).findByUUID(TENANT, sclFileTye, id);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsReaderTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsReaderTest.java
index 038d453b..c1932491 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsReaderTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetServerEndpointAsReaderTest.java
@@ -26,9 +26,14 @@
@QuarkusTest
class CompasSclGetServerEndpointAsReaderTest extends AbstractServerEndpointAsReaderTestSupport {
+ private static final String TENANT = "test-tenant";
+
@InjectMock
private CompasSclDataService service;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@TestHTTPResource("/scl-ws/v1/SCD/get")
private URI uri;
@@ -42,13 +47,14 @@ void getSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws Exception {
var request = new GetWsRequest();
request.setId(id);
- when(service.findByUUID(sclFileTye, id)).thenReturn(sclData);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.findByUUID(TENANT, sclFileTye, id)).thenReturn(sclData);
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
session.getAsyncRemote().sendText(encoder.encode(request));
assertSclData(sclData);
- verify(service).findByUUID(sclFileTye, id);
+ verify(service).findByUUID(TENANT, sclFileTye, id);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsEditorTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsEditorTest.java
index 834dd22d..aaee0987 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsEditorTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsEditorTest.java
@@ -27,9 +27,14 @@
@QuarkusTest
class CompasSclGetVersionServerEndpointAsEditorTest extends AbstractServerEndpointAsEditorTestSupport {
+ private static final String TENANT = "test-tenant";
+
@InjectMock
private CompasSclDataService service;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@TestHTTPResource("/scl-ws/v1/SCD/get-version")
private URI uri;
@@ -45,13 +50,14 @@ void getVersionSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws Exception
request.setId(id);
request.setVersion(version.toString());
- when(service.findByUUID(sclFileTye, id, version)).thenReturn(sclData);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.findByUUID(TENANT, sclFileTye, id, version)).thenReturn(sclData);
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
session.getAsyncRemote().sendText(encoder.encode(request));
assertSclData(sclData);
- verify(service).findByUUID(sclFileTye, id, version);
+ verify(service).findByUUID(TENANT, sclFileTye, id, version);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsReaderTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsReaderTest.java
index 903047e7..1cba6af8 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsReaderTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclGetVersionServerEndpointAsReaderTest.java
@@ -27,9 +27,14 @@
@QuarkusTest
class CompasSclGetVersionServerEndpointAsReaderTest extends AbstractServerEndpointAsReaderTestSupport {
+ private static final String TENANT = "test-tenant";
+
@InjectMock
private CompasSclDataService service;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@TestHTTPResource("/scl-ws/v1/SCD/get-version")
private URI uri;
@@ -45,13 +50,14 @@ void getVersionSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws Exception
request.setId(id);
request.setVersion(version.toString());
- when(service.findByUUID(sclFileTye, id, version)).thenReturn(sclData);
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.findByUUID(TENANT, sclFileTye, id, version)).thenReturn(sclData);
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
session.getAsyncRemote().sendText(encoder.encode(request));
assertSclData(sclData);
- verify(service).findByUUID(sclFileTye, id, version);
+ verify(service).findByUUID(TENANT, sclFileTye, id, version);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointAsEditorTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointAsEditorTest.java
index 795688b5..203b5a45 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointAsEditorTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointAsEditorTest.java
@@ -27,9 +27,14 @@
@QuarkusTest
class CompasSclUpdateServerEndpointAsEditorTest extends AbstractServerEndpointAsEditorTestSupport {
+ private static final String TENANT = "test-tenant";
+
@InjectMock
private CompasSclDataService service;
+ @InjectMock
+ private org.lfenergy.compas.scl.data.rest.TenantService tenantService;
+
@TestHTTPResource("/scl-ws/v1/SCD/update")
private URI uri;
@@ -48,14 +53,15 @@ void updateSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws Exception {
request.setComment(comment);
request.setSclData(sclData);
- when(service.update(sclFileTye, id, cst, USERNAME, comment, sclData))
+ when(tenantService.resolveTenant()).thenReturn(TENANT);
+ when(service.update(TENANT, sclFileTye, id, cst, USERNAME, comment, sclData))
.thenReturn(sclData);
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
session.getAsyncRemote().sendText(encoder.encode(request));
assertSclData(sclData);
- verify(service).update(sclFileTye, id, cst, USERNAME, comment, sclData);
+ verify(service).update(TENANT, sclFileTye, id, cst, USERNAME, comment, sclData);
}
}
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointTest.java
index 3fa7f928..815e543f 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/websocket/v1/CompasSclUpdateServerEndpointTest.java
@@ -18,7 +18,7 @@ class CompasSclUpdateServerEndpointTest extends AbstractServerEndpointOnOpenTest
@Test
void onOpen_WhenSessionCloseThrowsIOException_ThenExceptionIsHandledGracefully() throws IOException {
- var endpoint = new CompasSclUpdateServerEndpoint(null, jsonWebToken, null);
+ var endpoint = new CompasSclUpdateServerEndpoint(null, jsonWebToken, null, null);
testOnOpenWhenSessionCloseThrowsIOException(jsonWebToken, endpoint::onOpen);
}
}
diff --git a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java
index c2081a85..7d89d7c6 100644
--- a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java
+++ b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/CompasSclDataPostgreSQLRepository.java
@@ -40,14 +40,16 @@ public class CompasSclDataPostgreSQLRepository implements CompasSclDataRepositor
protected static String DELETE_SCL_FILE_SQL = """
delete from scl_file
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
""";
protected static String DELETE_SCL_FILE_SQL_BY_VERSION = """
delete from scl_file
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
@@ -59,14 +61,15 @@ public CompasSclDataPostgreSQLRepository(DataSource dataSource) {
@Override
@Transactional(SUPPORTS)
- public List list(SclFileType type) {
+ public List list(String tenant, SclFileType type) {
var sql = """
select scl_file.id, scl_file.name,
scl_file.major_version, scl_file.minor_version, scl_file.patch_version,
scl_labels.label_values as labels
from (select distinct on (scl_file.id) *
from scl_file
- where scl_file.type = ?
+ where scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.is_deleted = false
order by scl_file.id
, scl_file.major_version desc
@@ -89,6 +92,7 @@ left outer join (
try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(sql)) {
stmt.setString(1, type.name());
+ stmt.setString(2, tenant);
try (var resultSet = stmt.executeQuery()) {
while (resultSet.next()) {
@@ -106,7 +110,7 @@ left outer join (
@Override
@Transactional(SUPPORTS)
- public List listVersionsByUUID(SclFileType type, UUID id) {
+ public List listVersionsByUUID(String tenant, SclFileType type, UUID id) {
var sql = """
select scl_file.id, scl_file.name
, scl_file.major_version, scl_file.minor_version, scl_file.patch_version
@@ -125,8 +129,9 @@ left outer join (
and scl_data.major_version = scl_file.major_version
and scl_data.minor_version = scl_file.minor_version
and scl_data.patch_version = scl_file.patch_version
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.is_deleted = false
order by scl_file.major_version
, scl_file.minor_version
@@ -138,6 +143,7 @@ left outer join (
var stmt = connection.prepareStatement(sql)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
+ stmt.setString(3, tenant);
try (var resultSet = stmt.executeQuery()) {
while (resultSet.next()) {
@@ -157,21 +163,22 @@ left outer join (
@Override
@Transactional(SUPPORTS)
- public String findByUUID(SclFileType type, UUID id) {
+ public String findByUUID(String tenant, SclFileType type, UUID id) {
// Use the find meta info to retrieve info about the latest version.
- var metaInfo = findMetaInfoByUUID(type, id);
+ var metaInfo = findMetaInfoByUUID(tenant, type, id);
// Next return the data using the meta info.
- return findByUUID(type, id, new Version(metaInfo.getVersion()));
+ return findByUUID(tenant, type, id, new Version(metaInfo.getVersion()));
}
@Override
@Transactional(SUPPORTS)
- public String findByUUID(SclFileType type, UUID id, Version version) {
+ public String findByUUID(String tenant, SclFileType type, UUID id, Version version) {
var sql = """
select scl_file.scl_data
from scl_file
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
@@ -182,9 +189,10 @@ public String findByUUID(SclFileType type, UUID id, Version version) {
var stmt = connection.prepareStatement(sql)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
- stmt.setInt(3, version.getMajorVersion());
- stmt.setInt(4, version.getMinorVersion());
- stmt.setInt(5, version.getPatchVersion());
+ stmt.setString(3, tenant);
+ stmt.setInt(4, version.getMajorVersion());
+ stmt.setInt(5, version.getMinorVersion());
+ stmt.setInt(6, version.getPatchVersion());
try (var resultSet = stmt.executeQuery()) {
if (resultSet.next()) {
@@ -200,11 +208,12 @@ public String findByUUID(SclFileType type, UUID id, Version version) {
@Override
@Transactional(SUPPORTS)
- public boolean hasDuplicateSclName(SclFileType type, String name) {
+ public boolean hasDuplicateSclName(String tenant, SclFileType type, String name) {
var sql = """
select distinct on (scl_file.id) scl_file.name
from scl_file
- where scl_file.type = ?
+ where scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.is_deleted = false
order by scl_file.id
, scl_file.major_version desc
@@ -215,6 +224,7 @@ select distinct on (scl_file.id) scl_file.name
try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(sql)) {
stmt.setString(1, type.name());
+ stmt.setString(2, tenant);
try (var resultSet = stmt.executeQuery()) {
while (resultSet.next()) {
@@ -230,12 +240,13 @@ select distinct on (scl_file.id) scl_file.name
@Override
@Transactional(SUPPORTS)
- public IAbstractItem findMetaInfoByUUID(SclFileType type, UUID id) {
+ public IAbstractItem findMetaInfoByUUID(String tenant, SclFileType type, UUID id) {
var sql = """
select scl_file.id, scl_file.name, scl_file.major_version, scl_file.minor_version, scl_file.patch_version
from scl_file
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.is_deleted = false
order by scl_file.major_version desc, scl_file.minor_version desc, scl_file.patch_version desc
""";
@@ -244,6 +255,7 @@ public IAbstractItem findMetaInfoByUUID(SclFileType type, UUID id) {
var stmt = connection.prepareStatement(sql)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
+ stmt.setString(3, tenant);
try (var resultSet = stmt.executeQuery()) {
// We need to only retrieve the first row, because that's the latest version.
@@ -262,10 +274,10 @@ public IAbstractItem findMetaInfoByUUID(SclFileType type, UUID id) {
@Override
@Transactional(REQUIRED)
- public void create(SclFileType type, UUID id, String name, String scl, Version version, String who, List labels) {
+ public void create(String tenant, SclFileType type, UUID id, String name, String scl, Version version, String who, List labels) {
var createSclSQL = """
- insert into scl_file(id, major_version, minor_version, patch_version, type, name, created_by, scl_data)
- values (?, ?, ?, ?, ?, ?, ?, ?)
+ insert into scl_file(id, major_version, minor_version, patch_version, type, tenant, name, created_by, scl_data)
+ values (?, ?, ?, ?, ?, ?, ?, ?, ?)
""";
try (var connection = dataSource.getConnection();
@@ -276,9 +288,10 @@ insert into scl_file(id, major_version, minor_version, patch_version, type, name
sclStmt.setInt(3, version.getMinorVersion());
sclStmt.setInt(4, version.getPatchVersion());
sclStmt.setString(5, type.name());
- sclStmt.setString(6, name);
- sclStmt.setString(7, who);
- sclStmt.setString(8, scl);
+ sclStmt.setString(6, tenant);
+ sclStmt.setString(7, name);
+ sclStmt.setString(8, who);
+ sclStmt.setString(9, scl);
sclStmt.executeUpdate();
// Add the label to the database, if there are any.
@@ -319,12 +332,13 @@ insert into scl_label(scl_id, major_version, minor_version, patch_version, label
@Override
@Transactional(REQUIRED)
- public void delete(SclFileType type, UUID id) {
+ public void delete(String tenant, SclFileType type, UUID id) {
try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(DELETE_SCL_FILE_SQL)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
+ stmt.setString(3, tenant);
stmt.executeUpdate();
} catch (SQLException exp) {
throw new CompasSclDataServiceException(POSTGRES_DELETE_ERROR_CODE, "Error removing SCL from database!", exp);
@@ -333,15 +347,16 @@ public void delete(SclFileType type, UUID id) {
@Override
@Transactional(REQUIRED)
- public void delete(SclFileType type, UUID id, Version version) {
+ public void delete(String tenant, SclFileType type, UUID id, Version version) {
try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(DELETE_SCL_FILE_SQL_BY_VERSION)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
- stmt.setInt(3, version.getMajorVersion());
- stmt.setInt(4, version.getMinorVersion());
- stmt.setInt(5, version.getPatchVersion());
+ stmt.setString(3, tenant);
+ stmt.setInt(4, version.getMajorVersion());
+ stmt.setInt(5, version.getMinorVersion());
+ stmt.setInt(6, version.getPatchVersion());
stmt.executeUpdate();
} catch (SQLException exp) {
throw new CompasSclDataServiceException(POSTGRES_DELETE_ERROR_CODE, "Error removing SCL (version) from database!", exp);
diff --git a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/SoftDeleteCompasSclDataPostgreSQLRepository.java b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/SoftDeleteCompasSclDataPostgreSQLRepository.java
index 172b3019..65255148 100644
--- a/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/SoftDeleteCompasSclDataPostgreSQLRepository.java
+++ b/repository-postgresql/src/main/java/org/lfenergy/compas/scl/data/repository/postgresql/SoftDeleteCompasSclDataPostgreSQLRepository.java
@@ -11,14 +11,16 @@ public class SoftDeleteCompasSclDataPostgreSQLRepository extends CompasSclDataPo
private static final String SOFT_DELETE_SCL_FILE_SQL = """
update scl_file
set is_deleted = true
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
""";
private static final String SOFT_DELETE_SCL_FILE_SQL_BY_VERSION = """
delete from scl_file
- where scl_file.id = ?
- and scl_file.type = ?
+ where scl_file.id = ?
+ and scl_file.type = ?
+ and scl_file.tenant = ?
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
diff --git a/repository-postgresql/src/main/resources/org/lfenergy/compas/scl/data/repository/postgresql/db/migration/V1_8__add_tenant_to_scl_file.sql b/repository-postgresql/src/main/resources/org/lfenergy/compas/scl/data/repository/postgresql/db/migration/V1_8__add_tenant_to_scl_file.sql
new file mode 100644
index 00000000..bdadfc94
--- /dev/null
+++ b/repository-postgresql/src/main/resources/org/lfenergy/compas/scl/data/repository/postgresql/db/migration/V1_8__add_tenant_to_scl_file.sql
@@ -0,0 +1,16 @@
+/**
+ * SPDX-FileCopyrightText: 2026 Alliander N.V.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+--
+-- Add tenant column to scl_file for multi-tenant data isolation.
+-- Existing rows default to 'global' (the no-auth default tenant).
+--
+ALTER TABLE scl_file
+ ADD COLUMN tenant varchar(255) not null default 'global';
+
+CREATE INDEX scl_file_tenant ON scl_file(tenant);
+
+COMMENT ON COLUMN scl_file.tenant IS 'Tenant identifier: ''global'' when auth is disabled, OIDC realm name when auth is enabled.';
diff --git a/repository/src/main/java/org/lfenergy/compas/scl/data/SclDataServiceConstants.java b/repository/src/main/java/org/lfenergy/compas/scl/data/SclDataServiceConstants.java
index ce1f7951..cea92a04 100644
--- a/repository/src/main/java/org/lfenergy/compas/scl/data/SclDataServiceConstants.java
+++ b/repository/src/main/java/org/lfenergy/compas/scl/data/SclDataServiceConstants.java
@@ -10,6 +10,11 @@ public class SclDataServiceConstants {
public static final String SCL_DATA_SERVICE_V1_NS_URI = "https://www.lfenergy.org/compas/SclDataService/v1";
+ /**
+ * Fallback tenant name used when authentication is disabled.
+ */
+ public static final String GLOBAL_TENANT = "global";
+
public static final String SCL_NS_URI = "http://www.iec.ch/61850/2003/SCL";
public static final String SCL_NS_PREFIX = "";
public static final String SCL_ELEMENT_NAME = "SCL";
diff --git a/repository/src/main/java/org/lfenergy/compas/scl/data/repository/CompasSclDataRepository.java b/repository/src/main/java/org/lfenergy/compas/scl/data/repository/CompasSclDataRepository.java
index 4535fdda..826ea822 100644
--- a/repository/src/main/java/org/lfenergy/compas/scl/data/repository/CompasSclDataRepository.java
+++ b/repository/src/main/java/org/lfenergy/compas/scl/data/repository/CompasSclDataRepository.java
@@ -17,56 +17,62 @@ public interface CompasSclDataRepository {
/**
* List the latest version of all SCL Entries for a type of SCL.
*
- * @param type The type of SCL to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL to search for.
* @return The list of entries found for the passed type.
*/
- List list(SclFileType type);
+ List list(String tenant, SclFileType type);
/**
* List all versions for a specific SCL Entry for a type of SCL.
*
- * @param type The type of SCL to search for the specific SCL.
- * @param id The ID of the SCL to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL to search for the specific SCL.
+ * @param id The ID of the SCL to search for.
* @return The list of versions found for that specific sCl Entry.
*/
- List listVersionsByUUID(SclFileType type, UUID id);
+ List listVersionsByUUID(String tenant, SclFileType type, UUID id);
/**
* Return the latest version of a specific SCL Entry.
*
- * @param type The type of SCL to search for the specific SCL.
- * @param id The ID of the SCL to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL to search for the specific SCL.
+ * @param id The ID of the SCL to search for.
* @return The SCL XML File Content that is search for.
*/
- String findByUUID(SclFileType type, UUID id);
+ String findByUUID(String tenant, SclFileType type, UUID id);
/**
* Return the meta info of the latest version of a specific SCL Entry.
*
- * @param type The type of SCL to search for the specific SCL.
- * @param id The ID of the SCL to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL to search for the specific SCL.
+ * @param id The ID of the SCL to search for.
* @return The Meta Info of SCL Entry that is search for.
*/
- IAbstractItem findMetaInfoByUUID(SclFileType type, UUID id);
+ IAbstractItem findMetaInfoByUUID(String tenant, SclFileType type, UUID id);
/**
* Return the specific version of a specific SCL Entry.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type of SCL to search for the specific SCL.
* @param id The ID of the SCL to search for.
* @param version The version of the ScL to search for.
* @return The SCL XML File Content that is search for.
*/
- String findByUUID(SclFileType type, UUID id, Version version);
+ String findByUUID(String tenant, SclFileType type, UUID id, Version version);
/**
- * Return the specific version of a specific SCL Entry.
+ * Check whether the name is already used by another SCL File of the same type within the tenant.
*
- * @param type The type of SCL to search for the specific SCL.
- * @param name The name of the SCL used for checking duplicates.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL used for checking duplicates.
+ * @param name The name of the SCL used for checking duplicates.
* @return True if name is already used by another SCL File of the same File type, otherwise false.
*/
- boolean hasDuplicateSclName(SclFileType type, String name);
+ boolean hasDuplicateSclName(String tenant, SclFileType type, String name);
/**
* Create a new entry for the passed UUID with the version number passed.
@@ -75,6 +81,7 @@ public interface CompasSclDataRepository {
* When a entry is updated the service layer will increase the version and always create a new entry
* in the repository.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type of SCL to store it in.
* @param id The ID of the new entry to be created.
* @param name The name of the SCL to be stored.
@@ -83,22 +90,24 @@ public interface CompasSclDataRepository {
* @param who The user that created the new entry.
* @param labels The list of Labels extracted from the SCL XML File.
*/
- void create(SclFileType type, UUID id, String name, String scl, Version version, String who, List labels);
+ void create(String tenant, SclFileType type, UUID id, String name, String scl, Version version, String who, List labels);
/**
* Delete all versions for a specific SCL File using its ID.
*
- * @param type The type of SCL where to find the SCL File
- * @param id The ID of the SCL File to delete.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL where to find the SCL File
+ * @param id The ID of the SCL File to delete.
*/
- void delete(SclFileType type, UUID id);
+ void delete(String tenant, SclFileType type, UUID id);
/**
* Delete passed versions for a specific SCL File using its ID.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type of SCL where to find the SCL File
* @param id The ID of the SCL File to delete.
* @param version The version of that SCL File to delete.
*/
- void delete(SclFileType type, UUID id, Version version);
+ void delete(String tenant, SclFileType type, UUID id, Version version);
}
diff --git a/repository/src/test/java/org/lfenergy/compas/scl/data/repository/AbstractCompasSclDataRepositoryTest.java b/repository/src/test/java/org/lfenergy/compas/scl/data/repository/AbstractCompasSclDataRepositoryTest.java
index 0f20e022..7bf900a0 100644
--- a/repository/src/test/java/org/lfenergy/compas/scl/data/repository/AbstractCompasSclDataRepositoryTest.java
+++ b/repository/src/test/java/org/lfenergy/compas/scl/data/repository/AbstractCompasSclDataRepositoryTest.java
@@ -15,6 +15,7 @@
import static org.lfenergy.compas.scl.data.exception.CompasSclDataServiceErrorCode.NO_DATA_FOUND_ERROR_CODE;
public abstract class AbstractCompasSclDataRepositoryTest {
+ protected static final String TENANT = "test-tenant";
protected static final SclFileType TYPE = SclFileType.SCD;
// Use different types, so tests don't conflict with each other.
@@ -23,7 +24,7 @@ public abstract class AbstractCompasSclDataRepositoryTest {
@Test
void list_WhenCalledOnEmptyDatabase_ThenNoRecordsReturned() {
- var items = getRepository().list(LIST1_TYPE);
+ var items = getRepository().list(TENANT, LIST1_TYPE);
assertNotNull(items);
assertEquals(0, items.size());
@@ -33,7 +34,7 @@ void list_WhenCalledOnEmptyDatabase_ThenNoRecordsReturned() {
void listVersionsByUUID_WhenCalledWithUnknownID_ThenExceptionIsThrown() {
var uuid = UUID.randomUUID();
- var items = getRepository().listVersionsByUUID(TYPE, uuid);
+ var items = getRepository().listVersionsByUUID(TENANT, TYPE, uuid);
assertNotNull(items);
assertEquals(0, items.size());
@@ -45,7 +46,7 @@ void findByUUID_WhenCalledWithUnknownUUID_ThenExceptionIsThrown() {
var repository = getRepository();
var exception = assertThrows(CompasNoDataFoundException.class,
- () -> repository.findByUUID(TYPE, uuid));
+ () -> repository.findByUUID(TENANT, TYPE, uuid));
assertEquals(NO_DATA_FOUND_ERROR_CODE, exception.getErrorCode());
}
@@ -55,7 +56,7 @@ void findMetaInfoByUUID_WhenCalledWithUnknownUUID_ThenExceptionIsThrown() {
var repository = getRepository();
var exception = assertThrows(CompasNoDataFoundException.class,
- () -> repository.findMetaInfoByUUID(TYPE, uuid));
+ () -> repository.findMetaInfoByUUID(TENANT, TYPE, uuid));
assertEquals(NO_DATA_FOUND_ERROR_CODE, exception.getErrorCode());
}
@@ -66,12 +67,12 @@ void delete_AllVersions_SoftDeleted() {
Version version2 = new Version(2, 0, 0);
var repository = getRepository();
- repository.create(TYPE, uuid, "TestName", "", version1, "tester", List.of("label"));
- repository.create(TYPE, uuid, "TestName", "", version2, "tester", List.of("label"));
+ repository.create(TENANT, TYPE, uuid, "TestName", "", version1, "tester", List.of("label"));
+ repository.create(TENANT, TYPE, uuid, "TestName", "", version2, "tester", List.of("label"));
- repository.delete(TYPE, uuid);
+ repository.delete(TENANT, TYPE, uuid);
- var items = repository.listVersionsByUUID(TYPE, uuid);
+ var items = repository.listVersionsByUUID(TENANT, TYPE, uuid);
assertEquals(0, items.size(), "All versions should be soft deleted");
}
@@ -82,12 +83,12 @@ void delete_SpecificVersion_Deleted() {
Version version2 = new Version(2, 0, 0);
var repository = getRepository();
- repository.create(TYPE, uuid, "TestName", "", version1, "tester", List.of("label"));
- repository.create(TYPE, uuid, "TestName", "", version2, "tester", List.of("label"));
+ repository.create(TENANT, TYPE, uuid, "TestName", "", version1, "tester", List.of("label"));
+ repository.create(TENANT, TYPE, uuid, "TestName", "", version2, "tester", List.of("label"));
- repository.delete(TYPE, uuid, version1);
+ repository.delete(TENANT, TYPE, uuid, version1);
- var items = repository.listVersionsByUUID(TYPE, uuid);
+ var items = repository.listVersionsByUUID(TENANT, TYPE, uuid);
assertEquals(1, items.size(), "Only one version should remain");
assertEquals(version2.toString(), items.get(0).getVersion(), "Remaining version should be version2");
}
diff --git a/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java b/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java
index dbbccd31..14f69cce 100644
--- a/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java
+++ b/service/src/main/java/org/lfenergy/compas/scl/data/service/CompasSclDataService.java
@@ -55,12 +55,13 @@ public CompasSclDataService(CompasSclDataRepository repository, ElementConverter
/**
* List the latest version of all SCL XML Files for a specific type.
*
- * @param type The type to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type to search for.
* @return The List of Items found.
*/
@Transactional(SUPPORTS)
- public List- list(SclFileType type) {
- return repository.list(type)
+ public List
- list(String tenant, SclFileType type) {
+ return repository.list(tenant, type)
.stream()
.map(e -> new Item(e.getId(), e.getName(), e.getVersion(), e.getLabels()))
.toList();
@@ -69,13 +70,14 @@ public List
- list(SclFileType type) {
/**
* Search for all versions of a specific SCL XML File (using the UUID) for a specific type.
*
- * @param type The type to search for.
- * @param id The UUID of the record to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type to search for.
+ * @param id The UUID of the record to search for.
* @return The list of versions found.
*/
@Transactional(SUPPORTS)
- public List listVersionsByUUID(SclFileType type, UUID id) {
- var items = repository.listVersionsByUUID(type, id);
+ public List listVersionsByUUID(String tenant, SclFileType type, UUID id) {
+ var items = repository.listVersionsByUUID(tenant, type, id);
if (items.isEmpty()) {
var message = String.format("No versions found for type '%s' with ID '%s'", type, id);
throw new CompasNoDataFoundException(message);
@@ -89,32 +91,35 @@ public List listVersionsByUUID(SclFileType type, UUID id) {
/**
* Get the latest version of a specific SCL XML File (using the UUID) for a specific type.
*
- * @param type The type to search for.
- * @param id The UUID of the record to search for.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type to search for.
+ * @param id The UUID of the record to search for.
* @return The latest version of the SCL XML Files.
*/
@Transactional(SUPPORTS)
- public String findByUUID(SclFileType type, UUID id) {
- return repository.findByUUID(type, id);
+ public String findByUUID(String tenant, SclFileType type, UUID id) {
+ return repository.findByUUID(tenant, type, id);
}
/**
* Get a specific version of a specific SCL XML File (using the UUID) for a specific type.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type to search for.
* @param id The UUID of the record to search for.
* @param version The version to search for.
* @return The found version of the SCL XML Files.
*/
@Transactional(SUPPORTS)
- public String findByUUID(SclFileType type, UUID id, Version version) {
- return repository.findByUUID(type, id, version);
+ public String findByUUID(String tenant, SclFileType type, UUID id, Version version) {
+ return repository.findByUUID(tenant, type, id, version);
}
/**
* Create a new record for the passed SCL XML File with the passed name for a specific type.
* A new UUID is generated to be set and also the CoMPAS Private Elements are added on SCL Level.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type to create it for.
* @param name The name that will be stored as CoMPAS Private extension.
* @param comment Some comments that will be added to the THistory entry being added.
@@ -122,13 +127,13 @@ public String findByUUID(SclFileType type, UUID id, Version version) {
* @return The ID of the new created SCL XML File in the database.
*/
@Transactional(REQUIRED)
- public String create(SclFileType type, String name, String who, String comment, String sclData) {
+ public String create(String tenant, SclFileType type, String name, String who, String comment, String sclData) {
var scl = converter.convertToElement(new BufferedInputStream(new ByteArrayInputStream(sclData.getBytes(StandardCharsets.UTF_8))), SCL_ELEMENT_NAME, SCL_NS_URI);
if (scl == null) {
throw new CompasException(NO_SCL_ELEMENT_FOUND_ERROR_CODE, "No valid SCL found in the passed SCL Data.");
}
- if (hasDuplicateSclName(type, name)) {
+ if (hasDuplicateSclName(tenant, type, name)) {
throw new CompasException(DUPLICATE_SCL_NAME_ERROR_CODE, "Given name of SCL File already used.");
}
@@ -149,12 +154,12 @@ public String create(SclFileType type, String name, String who, String comment,
var labels = validateLabels(scl);
var newSclData = converter.convertToString(scl);
- repository.create(type, id, name, newSclData, version, who, labels);
+ repository.create(tenant, type, id, name, newSclData, version, who, labels);
return newSclData;
}
- public boolean hasDuplicateSclName(SclFileType type, String name){
- return repository.hasDuplicateSclName(type, name);
+ public boolean hasDuplicateSclName(String tenant, SclFileType type, String name){
+ return repository.hasDuplicateSclName(tenant, type, name);
}
/**
@@ -163,6 +168,7 @@ public boolean hasDuplicateSclName(SclFileType type, String name){
* the CoMPAS Private elements will also be copied, the SCL Name will only be copied if it isn't available in the
* SCL XML File.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type to update it for.
* @param id The UUID of the record to update.
* @param changeSetType The type of change to determine the new version.
@@ -170,18 +176,18 @@ public boolean hasDuplicateSclName(SclFileType type, String name){
* @param sclData The SCL XML File with the updated content.
*/
@Transactional(REQUIRED)
- public String update(SclFileType type, UUID id, ChangeSetType changeSetType, String who, String comment, String sclData) {
+ public String update(String tenant, SclFileType type, UUID id, ChangeSetType changeSetType, String who, String comment, String sclData) {
var scl = converter.convertToElement(new BufferedInputStream(new ByteArrayInputStream(sclData.getBytes(StandardCharsets.UTF_8))), SCL_ELEMENT_NAME, SCL_NS_URI);
if (scl == null) {
throw new CompasException(NO_SCL_ELEMENT_FOUND_ERROR_CODE, "No valid SCL found in the passed SCL Data.");
}
- var currentSclMetaInfo = repository.findMetaInfoByUUID(type, id);
+ var currentSclMetaInfo = repository.findMetaInfoByUUID(tenant, type, id);
var newFileName = getFilenameFromXML(scl);
if (newFileName.isPresent()
&& !newFileName.get().equals(currentSclMetaInfo.getName())
- && repository.hasDuplicateSclName(type, newFileName.get())) {
+ && repository.hasDuplicateSclName(tenant, type, newFileName.get())) {
throw new CompasException(DUPLICATE_SCL_NAME_ERROR_CODE, "Given name of SCL File already used.");
}
@@ -202,7 +208,7 @@ public String update(SclFileType type, UUID id, ChangeSetType changeSetType, Str
var labels = validateLabels(scl);
var newSclData = converter.convertToString(scl);
- repository.create(type, id, newSclName, newSclData, version, who, labels);
+ repository.create(tenant, type, id, newSclName, newSclData, version, who, labels);
return newSclData;
}
@@ -210,24 +216,26 @@ public String update(SclFileType type, UUID id, ChangeSetType changeSetType, Str
/**
* Delete all versions for a specific SCL File using it's ID.
*
- * @param type The type of SCL where to find the SCL File
- * @param id The ID of the SCL File to delete.
+ * @param tenant The tenant to scope the data to.
+ * @param type The type of SCL where to find the SCL File
+ * @param id The ID of the SCL File to delete.
*/
@Transactional(REQUIRED)
- public void delete(SclFileType type, UUID id) {
- repository.delete(type, id);
+ public void delete(String tenant, SclFileType type, UUID id) {
+ repository.delete(tenant, type, id);
}
/**
* Delete passed versions for a specific SCL File using it's ID.
*
+ * @param tenant The tenant to scope the data to.
* @param type The type of SCL where to find the SCL File
* @param id The ID of the SCL File to delete.
* @param version The version of that SCL File to delete.
*/
@Transactional(REQUIRED)
- public void delete(SclFileType type, UUID id, Version version) {
- repository.delete(type, id, version);
+ public void delete(String tenant, SclFileType type, UUID id, Version version) {
+ repository.delete(tenant, type, id, version);
}
/**
diff --git a/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java b/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java
index 142674b8..f97f8540 100644
--- a/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java
+++ b/service/src/test/java/org/lfenergy/compas/scl/data/service/CompasSclDataServiceTest.java
@@ -40,6 +40,7 @@
class CompasSclDataServiceTest {
private static final Version INITIAL_VERSION = new Version("1.0.0");
private static final SclFileType SCL_TYPE = SclFileType.SCD;
+ private static final String TENANT = "test-tenant";
@Mock
private CompasSclDataRepository compasSclDataRepository;
@@ -56,12 +57,12 @@ void beforeEach() {
@Test
void list_WhenCalled_ThenRepositoryIsCalled() {
- when(compasSclDataRepository.list(SCL_TYPE)).thenReturn(emptyList());
+ when(compasSclDataRepository.list(TENANT, SCL_TYPE)).thenReturn(emptyList());
- var result = compasSclDataService.list(SCL_TYPE);
+ var result = compasSclDataService.list(TENANT, SCL_TYPE);
assertNotNull(result);
- verify(compasSclDataRepository).list(SCL_TYPE);
+ verify(compasSclDataRepository).list(TENANT, SCL_TYPE);
}
@Test
@@ -72,49 +73,49 @@ void listVersionsByUUID_WhenCalledAndRepositoryReturnItemList_ThenListIsReturned
var historyItem = mock(IHistoryItem.class);
when(historyItem.getId()).thenReturn(id);
List expectedResult = List.of(historyItem);
- when(compasSclDataRepository.listVersionsByUUID(SCL_TYPE, uuid)).thenReturn(expectedResult);
+ when(compasSclDataRepository.listVersionsByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(expectedResult);
- var result = compasSclDataService.listVersionsByUUID(SCL_TYPE, uuid);
+ var result = compasSclDataService.listVersionsByUUID(TENANT, SCL_TYPE, uuid);
assertNotNull(result);
assertEquals(expectedResult.size(), result.size());
assertEquals(historyItem.getId(), result.get(0).getId());
- verify(compasSclDataRepository).listVersionsByUUID(SCL_TYPE, uuid);
+ verify(compasSclDataRepository).listVersionsByUUID(TENANT, SCL_TYPE, uuid);
}
@Test
void listVersionsByUUID_WhenCalledAndRepositoryReturnsEmptyList_ThenExceptionIsThrown() {
var uuid = UUID.randomUUID();
- when(compasSclDataRepository.listVersionsByUUID(SCL_TYPE, uuid)).thenReturn(emptyList());
+ when(compasSclDataRepository.listVersionsByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(emptyList());
var exception = assertThrows(CompasNoDataFoundException.class, () -> {
- compasSclDataService.listVersionsByUUID(SCL_TYPE, uuid);
+ compasSclDataService.listVersionsByUUID(TENANT, SCL_TYPE, uuid);
});
assertEquals(NO_DATA_FOUND_ERROR_CODE, exception.getErrorCode());
- verify(compasSclDataRepository).listVersionsByUUID(SCL_TYPE, uuid);
+ verify(compasSclDataRepository).listVersionsByUUID(TENANT, SCL_TYPE, uuid);
}
@Test
void findByUUID_WhenCalledWithoutVersion_ThenRepositoryIsCalled() throws IOException {
var uuid = UUID.randomUUID();
- when(compasSclDataRepository.findByUUID(SCL_TYPE, uuid)).thenReturn(readSCL("scl_test_file.scd"));
+ when(compasSclDataRepository.findByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(readSCL("scl_test_file.scd"));
- var result = compasSclDataService.findByUUID(SCL_TYPE, uuid);
+ var result = compasSclDataService.findByUUID(TENANT, SCL_TYPE, uuid);
assertNotNull(result);
- verify(compasSclDataRepository).findByUUID(SCL_TYPE, uuid);
+ verify(compasSclDataRepository).findByUUID(TENANT, SCL_TYPE, uuid);
}
@Test
void findByUUID_WhenCalledWithVersion_ThenRepositoryIsCalled() throws IOException {
var uuid = UUID.randomUUID();
var version = new Version(1, 0, 0);
- when(compasSclDataRepository.findByUUID(SCL_TYPE, uuid, version)).thenReturn(readSCL("scl_test_file.scd"));
+ when(compasSclDataRepository.findByUUID(TENANT, SCL_TYPE, uuid, version)).thenReturn(readSCL("scl_test_file.scd"));
- var result = compasSclDataService.findByUUID(SCL_TYPE, uuid, version);
+ var result = compasSclDataService.findByUUID(TENANT, SCL_TYPE, uuid, version);
assertNotNull(result);
- verify(compasSclDataRepository).findByUUID(SCL_TYPE, uuid, version);
+ verify(compasSclDataRepository).findByUUID(TENANT, SCL_TYPE, uuid, version);
}
@Test
@@ -125,16 +126,16 @@ void create_WhenCalledWithOutCompasExtension_ThenSCLReturnedWithCorrectCompasExt
var scl = readSCL("scl_test_file.scd");
- when(compasSclDataRepository.hasDuplicateSclName(SCL_TYPE, name)).thenReturn(false);
- doNothing().when(compasSclDataRepository).create(eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
+ when(compasSclDataRepository.hasDuplicateSclName(TENANT, SCL_TYPE, name)).thenReturn(false);
+ doNothing().when(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
- scl = compasSclDataService.create(SCL_TYPE, name, who, comment, scl);
+ scl = compasSclDataService.create(TENANT, SCL_TYPE, name, who, comment, scl);
assertNotNull(scl);
assertCompasExtension(scl, name);
assertHistoryItem(scl, 2, INITIAL_VERSION, comment);
- verify(compasSclDataRepository).create(eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
- verify(compasSclDataRepository).hasDuplicateSclName(SCL_TYPE, name);
+ verify(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
+ verify(compasSclDataRepository).hasDuplicateSclName(TENANT, SCL_TYPE, name);
}
@Test
@@ -146,16 +147,16 @@ void create_WhenCalledWithCompasExtension_ThenSCLReturnedWithCorrectCompasExtens
var scl = readSCL("scl_test_file.scd");
scl = createCompasPrivate(scl, "JUSTANOTHERNAME");
- when(compasSclDataRepository.hasDuplicateSclName(SCL_TYPE, name)).thenReturn(false);
- doNothing().when(compasSclDataRepository).create(eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
+ when(compasSclDataRepository.hasDuplicateSclName(TENANT, SCL_TYPE, name)).thenReturn(false);
+ doNothing().when(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
- scl = compasSclDataService.create(SCL_TYPE, name, who, comment, scl);
+ scl = compasSclDataService.create(TENANT, SCL_TYPE, name, who, comment, scl);
assertNotNull(scl);
assertCompasExtension(scl, name);
assertHistoryItem(scl, 2, INITIAL_VERSION, comment);
- verify(compasSclDataRepository).create(eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
- verify(compasSclDataRepository).hasDuplicateSclName(SCL_TYPE, name);
+ verify(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), any(UUID.class), eq(name), anyString(), eq(INITIAL_VERSION), eq(who), eq(emptyList()));
+ verify(compasSclDataRepository).hasDuplicateSclName(TENANT, SCL_TYPE, name);
}
@Test
@@ -166,12 +167,12 @@ void create_WhenCalledWithDuplicateSclName_ThenCompasExceptionThrown() throws IO
var scl = readSCL("scl_test_file.scd");
- when(compasSclDataRepository.hasDuplicateSclName(SCL_TYPE, name)).thenReturn(true);
+ when(compasSclDataRepository.hasDuplicateSclName(TENANT, SCL_TYPE, name)).thenReturn(true);
var exception = assertThrows(CompasException.class, () -> {
- compasSclDataService.create(SCL_TYPE, name, who, comment, scl);
+ compasSclDataService.create(TENANT, SCL_TYPE, name, who, comment, scl);
});
assertEquals(DUPLICATE_SCL_NAME_ERROR_CODE, exception.getErrorCode());
- verify(compasSclDataRepository).hasDuplicateSclName(SCL_TYPE, name);
+ verify(compasSclDataRepository).hasDuplicateSclName(TENANT, SCL_TYPE, name);
}
@Test
@@ -183,7 +184,7 @@ void create_WhenCalledWithXMLStringWithoutSCL_ThenCompasExceptionThrown() {
var scl = "";
var exception = assertThrows(CompasException.class, () -> {
- compasSclDataService.create(SCL_TYPE, name, who, comment, scl);
+ compasSclDataService.create(TENANT, SCL_TYPE, name, who, comment, scl);
});
assertEquals(NO_SCL_ELEMENT_FOUND_ERROR_CODE, exception.getErrorCode());
}
@@ -199,17 +200,17 @@ void update_WhenCalledWithoutCompasElements_ThenSCLReturnedWithCorrectCompasExte
var scl = readSCL("scl_test_file.scd");
var sclMetaInfo = new SclMetaInfo(uuid.toString(), previousName, INITIAL_VERSION.toString());
- when(compasSclDataRepository.findMetaInfoByUUID(SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
- doNothing().when(compasSclDataRepository).create(eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
+ when(compasSclDataRepository.findMetaInfoByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
+ doNothing().when(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
- scl = compasSclDataService.update(SCL_TYPE, uuid, changeSet, who, null, scl);
+ scl = compasSclDataService.update(TENANT, SCL_TYPE, uuid, changeSet, who, null, scl);
assertNotNull(scl);
assertCompasExtension(scl, previousName);
assertHistoryItem(scl, 4, nextVersion, null);
- verify(compasSclDataRepository).create(eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
- verify(compasSclDataRepository).findMetaInfoByUUID(SCL_TYPE, uuid);
- verify(compasSclDataRepository, never()).hasDuplicateSclName(SCL_TYPE, previousName);
+ verify(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
+ verify(compasSclDataRepository).findMetaInfoByUUID(TENANT, SCL_TYPE, uuid);
+ verify(compasSclDataRepository, never()).hasDuplicateSclName(TENANT, SCL_TYPE, previousName);
}
@Test
@@ -225,18 +226,18 @@ void update_WhenCalledWithCompasElementsAndNewName_ThenSCLReturnedWithCorrectCom
scl = createCompasPrivate(scl, newName);
var sclMetaInfo = new SclMetaInfo(uuid.toString(), previousName, INITIAL_VERSION.toString());
- when(compasSclDataRepository.findMetaInfoByUUID(SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
- doNothing().when(compasSclDataRepository).create(eq(SCL_TYPE), eq(uuid), eq(newName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
- when(compasSclDataRepository.hasDuplicateSclName(SCL_TYPE, newName)).thenReturn(false);
+ when(compasSclDataRepository.findMetaInfoByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
+ doNothing().when(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), eq(uuid), eq(newName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
+ when(compasSclDataRepository.hasDuplicateSclName(TENANT, SCL_TYPE, newName)).thenReturn(false);
- scl = compasSclDataService.update(SCL_TYPE, uuid, changeSet, who, null, scl);
+ scl = compasSclDataService.update(TENANT, SCL_TYPE, uuid, changeSet, who, null, scl);
assertNotNull(scl);
assertCompasExtension(scl, newName);
assertHistoryItem(scl, 4, nextVersion, null);
- verify(compasSclDataRepository).create(eq(SCL_TYPE), eq(uuid), eq(newName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
- verify(compasSclDataRepository).findMetaInfoByUUID(SCL_TYPE, uuid);
- verify(compasSclDataRepository).hasDuplicateSclName(SCL_TYPE, newName);
+ verify(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), eq(uuid), eq(newName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
+ verify(compasSclDataRepository).findMetaInfoByUUID(TENANT, SCL_TYPE, uuid);
+ verify(compasSclDataRepository).hasDuplicateSclName(TENANT, SCL_TYPE, newName);
}
@Test
@@ -250,15 +251,15 @@ void update_WhenCalledWithCompasElementsAndDuplicateNewName_ThenCompasExceptionT
var scl = createCompasPrivate(readSCL("scl_test_file.scd"), newName);
var sclMetaInfo = new SclMetaInfo(uuid.toString(), previousName, INITIAL_VERSION.toString());
- when(compasSclDataRepository.findMetaInfoByUUID(SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
- when(compasSclDataRepository.hasDuplicateSclName(SCL_TYPE, newName)).thenReturn(true);
+ when(compasSclDataRepository.findMetaInfoByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
+ when(compasSclDataRepository.hasDuplicateSclName(TENANT, SCL_TYPE, newName)).thenReturn(true);
var exception = assertThrows(CompasException.class, () -> {
- compasSclDataService.update(SCL_TYPE, uuid, changeSet, who, null, scl);
+ compasSclDataService.update(TENANT, SCL_TYPE, uuid, changeSet, who, null, scl);
});
assertEquals(DUPLICATE_SCL_NAME_ERROR_CODE, exception.getErrorCode());
- verify(compasSclDataRepository).findMetaInfoByUUID(SCL_TYPE, uuid);
- verify(compasSclDataRepository).hasDuplicateSclName(SCL_TYPE, newName);
+ verify(compasSclDataRepository).findMetaInfoByUUID(TENANT, SCL_TYPE, uuid);
+ verify(compasSclDataRepository).hasDuplicateSclName(TENANT, SCL_TYPE, newName);
}
@Test
@@ -273,17 +274,17 @@ void update_WhenCalledWithCompasElementsAndSameName_ThenSCLReturnedWithCorrectCo
scl = createCompasPrivate(scl, previousName);
var sclMetaInfo = new SclMetaInfo(uuid.toString(), previousName, INITIAL_VERSION.toString());
- when(compasSclDataRepository.findMetaInfoByUUID(SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
- doNothing().when(compasSclDataRepository).create(eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
+ when(compasSclDataRepository.findMetaInfoByUUID(TENANT, SCL_TYPE, uuid)).thenReturn(sclMetaInfo);
+ doNothing().when(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
- scl = compasSclDataService.update(SCL_TYPE, uuid, changeSet, who, null, scl);
+ scl = compasSclDataService.update(TENANT, SCL_TYPE, uuid, changeSet, who, null, scl);
assertNotNull(scl);
assertCompasExtension(scl, previousName);
assertHistoryItem(scl, 4, nextVersion, null);
- verify(compasSclDataRepository).create(eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
- verify(compasSclDataRepository).findMetaInfoByUUID(SCL_TYPE, uuid);
- verify(compasSclDataRepository, never()).hasDuplicateSclName(SCL_TYPE, previousName);
+ verify(compasSclDataRepository).create(eq(TENANT), eq(SCL_TYPE), eq(uuid), eq(previousName), anyString(), eq(nextVersion), eq(who), eq(emptyList()));
+ verify(compasSclDataRepository).findMetaInfoByUUID(TENANT, SCL_TYPE, uuid);
+ verify(compasSclDataRepository, never()).hasDuplicateSclName(TENANT, SCL_TYPE, previousName);
}
@Test
@@ -295,7 +296,7 @@ void update_WhenCalledWithXMLStringWithoutSCL_ThenCompasExceptionThrown() {
var scl = "";
var exception = assertThrows(CompasException.class, () -> {
- compasSclDataService.update(SCL_TYPE, uuid, changeSet, who, null, scl);
+ compasSclDataService.update(TENANT, SCL_TYPE, uuid, changeSet, who, null, scl);
});
assertEquals(NO_SCL_ELEMENT_FOUND_ERROR_CODE, exception.getErrorCode());
}
@@ -304,11 +305,11 @@ void update_WhenCalledWithXMLStringWithoutSCL_ThenCompasExceptionThrown() {
void delete_WhenCalledWithoutVersion_ThenRepositoryIsCalled() {
var uuid = UUID.randomUUID();
- doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid);
+ doNothing().when(compasSclDataRepository).delete(TENANT, SCL_TYPE, uuid);
- compasSclDataService.delete(SCL_TYPE, uuid);
+ compasSclDataService.delete(TENANT, SCL_TYPE, uuid);
- verify(compasSclDataRepository).delete(SCL_TYPE, uuid);
+ verify(compasSclDataRepository).delete(TENANT, SCL_TYPE, uuid);
}
@Test
@@ -316,11 +317,11 @@ void delete_WhenCalledWithVersion_ThenRepositoryIsCalled() {
var uuid = UUID.randomUUID();
var version = new Version(1, 0, 0);
- doNothing().when(compasSclDataRepository).delete(SCL_TYPE, uuid, version);
+ doNothing().when(compasSclDataRepository).delete(TENANT, SCL_TYPE, uuid, version);
- compasSclDataService.delete(SCL_TYPE, uuid, version);
+ compasSclDataService.delete(TENANT, SCL_TYPE, uuid, version);
- verify(compasSclDataRepository).delete(SCL_TYPE, uuid, version);
+ verify(compasSclDataRepository).delete(TENANT, SCL_TYPE, uuid, version);
}
@Test
From f331cc2861e6004ef7510b887919b2bb1aa64af1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Jun 2026 11:31:46 +0000
Subject: [PATCH 3/3] fix: improve TenantService trailing slash and no-path URL
handling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Strip trailing slash before extracting last path segment so that
"http://host/realms/compas/" correctly returns "compas"
- Guard against bare hostname URLs (e.g. "http://host") returning the
hostname as tenant by checking that the char before lastSlash is not
also a slash (i.e. not the "://" separator)
- Fix test method name typo: AssTenant → AsTenant
- Update no-path test to assert GLOBAL_TENANT (was incorrectly asserting "host")
- Add new trailing-slash test case
---
.../compas/scl/data/rest/TenantService.java | 15 +++++++++++----
.../compas/scl/data/rest/TenantServiceTest.java | 13 +++++++++----
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java b/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java
index cb4e1c3b..7d915db3 100644
--- a/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java
+++ b/app/src/main/java/org/lfenergy/compas/scl/data/rest/TenantService.java
@@ -43,10 +43,17 @@ public String resolveTenant() {
return GLOBAL_TENANT;
}
// Issuer URL format (Keycloak): http:///auth/realms/
- // Extract the last path segment as the realm / tenant name.
- int lastSlash = issuer.lastIndexOf('/');
- if (lastSlash >= 0 && lastSlash < issuer.length() - 1) {
- return issuer.substring(lastSlash + 1);
+ // Strip any trailing slash so that "http://host/realms/compas/" is treated
+ // the same as "http://host/realms/compas".
+ String normalized = issuer.endsWith("/") ? issuer.substring(0, issuer.length() - 1) : issuer;
+ int lastSlash = normalized.lastIndexOf('/');
+ // Guard against URLs with no path (e.g. "http://host") by ensuring the
+ // character before lastSlash is not also a slash (i.e. not the "://" part).
+ if (lastSlash > 0 && normalized.charAt(lastSlash - 1) != '/') {
+ String segment = normalized.substring(lastSlash + 1);
+ if (!segment.isBlank()) {
+ return segment;
+ }
}
} catch (Exception e) {
// No token available – fall back to global tenant.
diff --git a/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java b/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java
index d71f14e9..fcabc6c4 100644
--- a/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java
+++ b/app/src/test/java/org/lfenergy/compas/scl/data/rest/TenantServiceTest.java
@@ -38,7 +38,7 @@ void resolveTenant_WhenIssuerIsBlank_ThenReturnsGlobalTenant() {
}
@Test
- void resolveTenant_WhenIssuerHasRealmPath_ThenReturnsRealmAssTenant() {
+ void resolveTenant_WhenIssuerHasRealmPath_ThenReturnsRealmAsTenant() {
when(jsonWebToken.getIssuer()).thenReturn("http://host/auth/realms/compas");
assertEquals("compas", tenantService.resolveTenant());
@@ -55,9 +55,14 @@ void resolveTenant_WhenIssuerHasDifferentRealm_ThenReturnsCorrectTenant() {
void resolveTenant_WhenIssuerHasNoPath_ThenReturnsGlobalTenant() {
when(jsonWebToken.getIssuer()).thenReturn("http://host");
- // "http://host" has a last slash at position 6 (before "host"),
- // so host is extracted as tenant
- assertEquals("host", tenantService.resolveTenant());
+ assertEquals(GLOBAL_TENANT, tenantService.resolveTenant());
+ }
+
+ @Test
+ void resolveTenant_WhenIssuerHasTrailingSlash_ThenReturnsRealmAsTenant() {
+ when(jsonWebToken.getIssuer()).thenReturn("http://host/realms/compas/");
+
+ assertEquals("compas", tenantService.resolveTenant());
}
@Test