From 9acc26667b48c63f4ce577146dd0bee5fdd4b67f Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Mon, 1 Apr 2024 18:36:03 +0300 Subject: [PATCH] tenant scope implementation --- .../java/eu/eudat/audit/AuditableAction.java | 3 +- .../eu/eudat/authorization/Permission.java | 1 + .../commons/scope/tenant/TenantScope.java | 2 +- .../commons/scope/tenant/TenantScoped.java | 3 + .../eudat/data/ActionConfirmationEntity.java | 6 + .../java/eu/eudat/data/DescriptionEntity.java | 6 + .../data/DescriptionReferenceEntity.java | 6 + .../eu/eudat/data/DescriptionTagEntity.java | 6 + .../eudat/data/DescriptionTemplateEntity.java | 6 + .../data/DescriptionTemplateTypeEntity.java | 6 + .../eu/eudat/data/DmpBlueprintEntity.java | 6 + .../data/DmpDescriptionTemplateEntity.java | 6 + .../main/java/eu/eudat/data/DmpEntity.java | 6 + .../eu/eudat/data/DmpReferenceEntity.java | 6 + .../java/eu/eudat/data/DmpUserEntity.java | 6 + .../java/eu/eudat/data/EntityDoiEntity.java | 6 + .../java/eu/eudat/data/LanguageEntity.java | 6 + .../main/java/eu/eudat/data/LockEntity.java | 6 + .../eu/eudat/data/PrefillingSourceEntity.java | 6 + .../java/eu/eudat/data/ReferenceEntity.java | 6 + .../eu/eudat/data/ReferenceTypeEntity.java | 6 + .../java/eu/eudat/data/StorageFileEntity.java | 6 + .../eudat/data/SupportiveMaterialEntity.java | 6 + .../main/java/eu/eudat/data/TagEntity.java | 6 + .../eu/eudat/data/TenantEntityManager.java | 32 +-- .../java/eu/eudat/data/TenantUserEntity.java | 9 +- .../eu/eudat/data/UserContactInfoEntity.java | 2 +- .../eu/eudat/data/UserCredentialEntity.java | 2 +- .../data/UserDescriptionTemplateEntity.java | 6 + .../java/eu/eudat/data/UserRoleEntity.java | 11 +- .../eu/eudat/data/UserSettingsEntity.java | 6 + .../eudat/data/tenant/TenantFilterAspect.java | 2 +- .../eu/eudat/data/tenant/TenantListener.java | 39 ++- .../data/tenant/TenantScopedBaseEntity.java | 4 +- .../errorcode/ErrorThesaurusProperties.java | 20 ++ .../deleter/ActionConfirmationDeleter.java | 6 +- .../model/deleter/DescriptionDeleter.java | 6 +- .../deleter/DescriptionReferenceDeleter.java | 6 +- .../model/deleter/DescriptionTagDeleter.java | 6 +- .../deleter/DescriptionTemplateDeleter.java | 6 +- .../DescriptionTemplateTypeDeleter.java | 9 +- .../model/deleter/DmpBlueprintDeleter.java | 6 +- .../eu/eudat/model/deleter/DmpDeleter.java | 5 +- .../DmpDescriptionTemplateDeleter.java | 8 +- .../model/deleter/DmpReferenceDeleter.java | 6 +- .../eudat/model/deleter/DmpUserDeleter.java | 6 +- .../eudat/model/deleter/EntityDoiDeleter.java | 6 +- .../eudat/model/deleter/LanguageDeleter.java | 6 +- .../eu/eudat/model/deleter/LockDeleter.java | 6 +- .../deleter/PrefillingSourceDeleter.java | 6 +- .../eudat/model/deleter/ReferenceDeleter.java | 10 +- .../model/deleter/ReferenceTypeDeleter.java | 6 +- .../deleter/SupportiveMaterialDeleter.java | 6 +- .../eu/eudat/model/deleter/TagDeleter.java | 6 +- .../eu/eudat/model/deleter/TenantDeleter.java | 6 +- .../model/deleter/UserContactInfoDeleter.java | 6 +- .../model/deleter/UserCredentialDeleter.java | 6 +- .../eu/eudat/model/deleter/UserDeleter.java | 5 +- .../UserDescriptionTemplateDeleter.java | 7 +- .../eudat/model/deleter/UserRoleDeleter.java | 9 +- .../deleter/UserSettingsSettingsDeleter.java | 6 +- .../model/persist/DescriptionPersist.java | 25 +- .../ActionConfirmationServiceImpl.java | 6 +- .../description/DescriptionService.java | 4 +- .../description/DescriptionServiceImpl.java | 19 +- .../DescriptionTemplateServiceImpl.java | 23 +- .../DescriptionTemplateTypeServiceImpl.java | 6 +- .../eu/eudat/service/dmp/DmpServiceImpl.java | 9 +- .../dmpblueprint/DmpBlueprintService.java | 2 +- .../dmpblueprint/DmpBlueprintServiceImpl.java | 10 +- .../eudat/service/elastic/ElasticService.java | 5 +- .../service/elastic/ElasticServiceImpl.java | 12 +- .../entitydoi/EntityDoiServiceImpl.java | 6 +- .../service/language/LanguageServiceImpl.java | 6 +- .../eudat/service/lock/LockServiceImpl.java | 6 +- .../PrefillingSourceService.java | 2 +- .../PrefillingSourceServiceImpl.java | 13 +- .../service/reference/ReferenceService.java | 2 +- .../reference/ReferenceServiceImpl.java | 7 +- .../ReferenceTypeServiceImpl.java | 6 +- .../storage/StorageFileCleanupTask.java | 3 + .../service/storage/StorageFileService.java | 3 +- .../storage/StorageFileServiceImpl.java | 9 +- .../SupportiveMaterialServiceImpl.java | 6 +- .../eu/eudat/service/tag/TagServiceImpl.java | 6 +- .../service/tenant/TenantServiceImpl.java | 13 +- .../eu/eudat/service/user/UserService.java | 4 +- .../eudat/service/user/UserServiceImpl.java | 11 +- .../settings/UserSettingsServiceImpl.java | 20 +- .../configurations/WebMVCConfiguration.java | 19 +- .../controllers/DescriptionController.java | 4 +- .../PrefillingSourceController.java | 2 +- .../controllers/PrincipalController.java | 22 +- .../controllers/ReferenceController.java | 2 +- .../tenant/TenantByCodeCacheOptions.java | 10 + .../tenant/TenantByCodeCacheService.java | 78 ++++++ .../tenant/TenantByIdCacheOptions.java | 10 + .../tenant/TenantByIdCacheService.java | 77 ++++++ .../tenant/TenantInterceptor.java | 222 ++++++++++++++++++ .../tenant/TenantScopeClaimInterceptor.java | 200 ++++++++++++++++ .../tenant/TenantScopeConfiguration.java | 9 + .../tenant/TenantScopeHeaderInterceptor.java | 162 +++++++++++++ .../tenant/TenantScopeProperties.java | 53 +++++ .../tenant/UserAllowedTenantCacheOptions.java | 10 + .../tenant/UserAllowedTenantCacheService.java | 90 +++++++ .../{ => user}/UserInterceptor.java | 2 +- .../UserInterceptorCacheOptions.java | 2 +- .../UserInterceptorCacheService.java | 3 +- .../java/eu/eudat/models/AccountBuilder.java | 6 +- .../web/src/main/resources/config/cache.yml | 27 +++ .../src/main/resources/config/idpclaims.yml | 13 +- .../src/main/resources/config/permissions.yml | 2 +- .../web/src/main/resources/config/tenant.yml | 8 +- .../app/core/services/auth/auth.service.ts | 19 +- .../configuration/configuration.service.ts | 5 +- .../services/dashboard/dashboard.service.ts | 3 +- .../description/description.service.ts | 3 +- .../src/app/core/services/dmp/dmp.service.ts | 6 +- .../core/services/http/principal.service.ts | 5 + .../language/language.http.service.ts | 6 +- .../supportive-material.service.ts | 3 +- .../src/app/ui/auth/login/login.component.ts | 34 ++- .../src/app/ui/auth/login/login.module.ts | 2 + .../src/app/ui/auth/login/login.routing.ts | 9 +- .../post-login/post-login.component.html | 29 +++ .../post-login/post-login.component.scss | 17 ++ .../login/post-login/post-login.component.ts | 113 +++++++++ .../src/app/ui/navbar/navbar.component.html | 2 +- .../src/common/http/common-http.module.ts | 6 + .../http/interceptors/interceptor-type.ts | 3 +- .../interceptors/status-code.interceptor.ts | 9 + .../interceptors/tenant-header.interceptor.ts | 27 +++ .../http-error-handling.service.ts | 4 + 133 files changed, 1713 insertions(+), 298 deletions(-) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheOptions.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheService.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheOptions.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheService.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantInterceptor.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeClaimInterceptor.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeConfiguration.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeHeaderInterceptor.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeProperties.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheOptions.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheService.java rename dmp-backend/web/src/main/java/eu/eudat/interceptors/{ => user}/UserInterceptor.java (99%) rename dmp-backend/web/src/main/java/eu/eudat/interceptors/{ => user}/UserInterceptorCacheOptions.java (89%) rename dmp-backend/web/src/main/java/eu/eudat/interceptors/{ => user}/UserInterceptorCacheService.java (96%) create mode 100644 dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.html create mode 100644 dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.scss create mode 100644 dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.ts create mode 100644 dmp-frontend/src/common/http/interceptors/tenant-header.interceptor.ts diff --git a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java index 1c34d4180..c614f310d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java +++ b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java @@ -145,8 +145,9 @@ public class AuditableAction { public static final EventId Maintenance_GenerateElastic = new EventId(220000, "Maintenance_GenerateElastic"); public static final EventId Maintenance_ClearElastic = new EventId(230000, "Maintenance_ClearElastic"); - + public static final EventId Principal_Lookup = new EventId(240000, "Principal_Lookup"); + public static final EventId Principal_MyTenants = new EventId(240001, "Principal_MyTenants"); public static final EventId GetSemantics = new EventId(250000, "GetSemantics"); diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java index 3ee18bba5..ad6e48715 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java @@ -23,6 +23,7 @@ public final class Permission { //Elastic public static String ManageElastic = "ManageElastic"; + //Deposit public static String BrowseDeposit = "BrowseDeposit"; public static String EditDeposit = "BrowseDeposit"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScope.java b/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScope.java index bc428a508..a0cbf2d9a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScope.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScope.java @@ -15,7 +15,7 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; @Component -//@RequestScope +@RequestScope public class TenantScope { public static final String TenantReplaceParameter = "::TenantCode::"; public static final String TenantCodesClaimName = "TenantCodes"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScoped.java b/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScoped.java index 41c85c469..e46c1acaf 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScoped.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/scope/tenant/TenantScoped.java @@ -1,8 +1,11 @@ package eu.eudat.commons.scope.tenant; +import java.beans.Transient; import java.util.UUID; public interface TenantScoped { void setTenantId(UUID tenantId); UUID getTenantId(); + @Transient + boolean allowNullTenant(); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/ActionConfirmationEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/ActionConfirmationEntity.java index 03cdc174c..e0dccab68 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/ActionConfirmationEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/ActionConfirmationEntity.java @@ -140,4 +140,10 @@ public class ActionConfirmationEntity extends TenantScopedBaseEntity { public void setIsActive(IsActive isActive) { this.isActive = isActive; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java index 07a289b3d..35ca528f9 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java @@ -188,5 +188,11 @@ public class DescriptionEntity extends TenantScopedBaseEntity { public void setDescriptionTemplateId(UUID descriptionTemplateId) { this.descriptionTemplateId = descriptionTemplateId; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java index 748955a22..892eac70f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java @@ -104,4 +104,10 @@ public class DescriptionReferenceEntity extends TenantScopedBaseEntity { public void setData(String data) { this.data = data; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java index 29eeb14dd..e0e3cf58a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java @@ -92,4 +92,10 @@ public class DescriptionTagEntity extends TenantScopedBaseEntity { this.isActive = isActive; } + @Override + @Transient + public boolean allowNullTenant() { + return false; + } + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java index e83f93056..411216982 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java @@ -162,4 +162,10 @@ public class DescriptionTemplateEntity extends TenantScopedBaseEntity { public void setVersionStatus(DescriptionTemplateVersionStatus versionStatus) { this.versionStatus = versionStatus; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateTypeEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateTypeEntity.java index fb25418f3..fff2aac27 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateTypeEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateTypeEntity.java @@ -95,4 +95,10 @@ public class DescriptionTemplateTypeEntity extends TenantScopedBaseEntity { public void setStatus(DescriptionTemplateTypeStatus status) { this.status = status; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java index e31fb9bb2..86b3dee8d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java @@ -154,4 +154,10 @@ public class DmpBlueprintEntity extends TenantScopedBaseEntity { public void setIsActive(IsActive isActive) { this.isActive = isActive; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java index d75fd1100..f692c559d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java @@ -104,4 +104,10 @@ public class DmpDescriptionTemplateEntity extends TenantScopedBaseEntity { public void setIsActive(IsActive isActive) { this.isActive = isActive; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpEntity.java index 74cf5ade2..bde053329 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpEntity.java @@ -244,4 +244,10 @@ public class DmpEntity extends TenantScopedBaseEntity { public void setVersionStatus(DmpVersionStatus versionStatus) { this.versionStatus = versionStatus; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpReferenceEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpReferenceEntity.java index 201900d20..64eeca134 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpReferenceEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpReferenceEntity.java @@ -97,4 +97,10 @@ public class DmpReferenceEntity extends TenantScopedBaseEntity { public void setIsActive(IsActive isActive) { this.isActive = isActive; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java index d5ce454ea..4339f60b7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java @@ -119,4 +119,10 @@ public class DmpUserEntity extends TenantScopedBaseEntity { public void setIsActive(IsActive isActive) { this.isActive = isActive; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/EntityDoiEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/EntityDoiEntity.java index 785943463..ee2ea78a6 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/EntityDoiEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/EntityDoiEntity.java @@ -121,4 +121,10 @@ public class EntityDoiEntity extends TenantScopedBaseEntity { this.entityId = entityId; } + @Override + @Transient + public boolean allowNullTenant() { + return false; + } + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java index 3a8292ae3..324172c21 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java @@ -98,4 +98,10 @@ public class LanguageEntity extends TenantScopedBaseEntity { public void setOrdinal(Integer ordinal) { this.ordinal = ordinal; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/LockEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/LockEntity.java index 751198891..42ccbece6 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/LockEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/LockEntity.java @@ -87,4 +87,10 @@ public class LockEntity extends TenantScopedBaseEntity { public void setTouchedAt(Instant touchedAt) { this.touchedAt = touchedAt; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/PrefillingSourceEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/PrefillingSourceEntity.java index f6afb774f..c38fa4298 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/PrefillingSourceEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/PrefillingSourceEntity.java @@ -89,4 +89,10 @@ public class PrefillingSourceEntity extends TenantScopedBaseEntity { public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceEntity.java index 07896263f..734aeb9c2 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceEntity.java @@ -204,4 +204,10 @@ public class ReferenceEntity extends TenantScopedBaseEntity { this.createdById = createdById; } + @Override + @Transient + public boolean allowNullTenant() { + return true; + } + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceTypeEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceTypeEntity.java index ebc5dc00e..41784a3ca 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceTypeEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/ReferenceTypeEntity.java @@ -108,4 +108,10 @@ public class ReferenceTypeEntity extends TenantScopedBaseEntity { public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java index 29be0b222..d0185bc59 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java @@ -139,4 +139,10 @@ public class StorageFileEntity extends TenantScopedBaseEntity { public void setOwnerId(UUID ownerId) { this.ownerId = ownerId; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java index 40bdf128d..d11b38987 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java @@ -101,4 +101,10 @@ public class SupportiveMaterialEntity extends TenantScopedBaseEntity { public void setIsActive(IsActive isActive) { this.isActive = isActive; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java index ef609f06a..12f2b91a7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java @@ -86,4 +86,10 @@ public class TagEntity extends TenantScopedBaseEntity { public void setCreatedById(UUID createdById) { this.createdById = createdById; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/TenantEntityManager.java b/dmp-backend/core/src/main/java/eu/eudat/data/TenantEntityManager.java index d06248cc6..9869eb536 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/TenantEntityManager.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/TenantEntityManager.java @@ -21,15 +21,12 @@ import java.util.UUID; public class TenantEntityManager { @PersistenceContext private EntityManager entityManager; - private final CurrentPrincipalResolver currentPrincipalResolver; - private final ClaimExtractor claimExtractor; - private final AuthorizationService authorizationService; +// private final CurrentPrincipalResolver currentPrincipalResolver; +// private final ClaimExtractor claimExtractor; +// private final AuthorizationService authorizationService; private final TenantScope tenantScope; - public TenantEntityManager(CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractor claimExtractor, AuthorizationService authorizationService, TenantScope tenantScope) { - this.currentPrincipalResolver = currentPrincipalResolver; - this.claimExtractor = claimExtractor; - this.authorizationService = authorizationService; + public TenantEntityManager(TenantScope tenantScope) { this.tenantScope = tenantScope; } @@ -40,10 +37,11 @@ public class TenantEntityManager { public T merge(T entity) throws InvalidApplicationException { if (tenantScope.isMultitenant() && (entity instanceof TenantScoped)) { - this.currentPrincipalResolver.currentPrincipal().isAuthenticated(); - this.claimExtractor.subjectUUID(this.currentPrincipalResolver.currentPrincipal()); - boolean isAllowedNoTenant = authorizationService.authorize(Permission.AllowNoTenant); - +// this.currentPrincipalResolver.currentPrincipal().isAuthenticated(); +// this.claimExtractor.subjectUUID(this.currentPrincipalResolver.currentPrincipal()); +// boolean isAllowedNoTenant = authorizationService.authorize(Permission.AllowNoTenant); + + boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant(); final UUID tenantId = !isAllowedNoTenant ? tenantScope.getTenant() : null; if (!isAllowedNoTenant && !tenantId.equals(((TenantScoped) entity).getTenantId())) throw new MyForbiddenException("tenant tampering"); } @@ -52,8 +50,9 @@ public class TenantEntityManager { public void remove(Object entity) throws InvalidApplicationException { if (tenantScope.isMultitenant() && (entity instanceof TenantScoped)) { - final UUID tenantId = tenantScope.getTenant(); - if (!tenantId.equals(((TenantScoped) entity).getTenantId())) throw new MyForbiddenException("tenant tampering"); + boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant(); + final UUID tenantId = !isAllowedNoTenant ? tenantScope.getTenant() : null; + if (!isAllowedNoTenant && !tenantId.equals(((TenantScoped) entity).getTenantId())) throw new MyForbiddenException("tenant tampering"); } this.entityManager.remove(entity); } @@ -62,10 +61,11 @@ public class TenantEntityManager { T entity = this.entityManager.find(entityClass, primaryKey); if (tenantScope.isMultitenant() && (entity instanceof TenantScoped)) { - this.currentPrincipalResolver.currentPrincipal().isAuthenticated(); - this.claimExtractor.subjectUUID(this.currentPrincipalResolver.currentPrincipal()); - boolean isAllowedNoTenant = authorizationService.authorize(Permission.AllowNoTenant); +// this.currentPrincipalResolver.currentPrincipal().isAuthenticated(); +// this.claimExtractor.subjectUUID(this.currentPrincipalResolver.currentPrincipal()); +// boolean isAllowedNoTenant = authorizationService.authorize(Permission.AllowNoTenant); + boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant(); final UUID tenantId = !isAllowedNoTenant ? tenantScope.getTenant() : null; if (!isAllowedNoTenant && !tenantId.equals(((TenantScoped) entity).getTenantId())) return null; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/TenantUserEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/TenantUserEntity.java index a624f0f70..a86feecb7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/TenantUserEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/TenantUserEntity.java @@ -2,13 +2,14 @@ package eu.eudat.data; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.converters.enums.IsActiveConverter; +import eu.eudat.data.tenant.TenantScopedBaseEntity; import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; @Entity @Table(name = "\"TenantUser\"") -public class TenantUserEntity { +public class TenantUserEntity extends TenantScopedBaseEntity { @Id @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) private UUID id; @@ -82,4 +83,10 @@ public class TenantUserEntity { public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } + + @Override + @Transient + public boolean allowNullTenant() { + return false; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java index 786970267..143465c66 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java @@ -10,7 +10,7 @@ import java.util.UUID; @Entity @Table(name = "\"UserContactInfo\"") -public class UserContactInfoEntity extends TenantScopedBaseEntity { +public class UserContactInfoEntity { @Id @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java index 2cad41cf5..f525d3ce2 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java @@ -11,7 +11,7 @@ import java.util.UUID; @Entity @Table(name = "\"UserCredential\"") -public class UserCredentialEntity extends TenantScopedBaseEntity { +public class UserCredentialEntity { @Id @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java index 21a176324..f83244c9f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java @@ -100,4 +100,10 @@ public class UserDescriptionTemplateEntity extends TenantScopedBaseEntity { public void setRole(UserDescriptionTemplateRole role) { this.role = role; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java index 822a61375..e768558ff 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java @@ -1,10 +1,7 @@ package eu.eudat.data; import eu.eudat.data.tenant.TenantScopedBaseEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; @@ -64,4 +61,10 @@ public class UserRoleEntity extends TenantScopedBaseEntity { this.createdAt = createdAt; } + @Override + @Transient + public boolean allowNullTenant() { + return true; + } + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java index d4a277697..d6a245738 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java @@ -109,4 +109,10 @@ public class UserSettingsEntity extends TenantScopedBaseEntity { public void setName(String name) { this.name = name; } + + @Override + @Transient + public boolean allowNullTenant() { + return true; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantFilterAspect.java b/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantFilterAspect.java index f63a4f567..ecc1b11a0 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantFilterAspect.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantFilterAspect.java @@ -12,7 +12,7 @@ import org.springframework.stereotype.Component; import javax.management.InvalidApplicationException; -//@Aspect +@Aspect @Component public class TenantFilterAspect { diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantListener.java b/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantListener.java index f11a2b93d..2e810510a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantListener.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantListener.java @@ -29,8 +29,14 @@ public class TenantListener { @PrePersist public void setTenantOnCreate(TenantScoped entity) throws InvalidApplicationException { if (tenantScope.isMultitenant()) { - final UUID tenantId = tenantScope.getTenant(); - entity.setTenantId(tenantId); + if (entity.getTenantId() != null && entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) { + logger.error("somebody tried to set not login tenat"); + throw new MyForbiddenException("tenant tampering"); + } + if (!entity.allowNullTenant()) { + final UUID tenantId = tenantScope.getTenant(); + entity.setTenantId(tenantId); + } } else { entity.setTenantId(null); } @@ -40,17 +46,26 @@ public class TenantListener { @PreRemove public void setTenantOnUpdate(TenantScoped entity) throws InvalidApplicationException { if (tenantScope.isMultitenant()) { - if (entity.getTenantId() == null) { - logger.error("somebody tried to set null tenant"); - throw new MyForbiddenException("tenant tampering"); - } - if (entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) { - logger.error("somebody tried to change an entries tenant"); - throw new MyForbiddenException("tenant tampering"); - } + if (!entity.allowNullTenant()){ + if (entity.getTenantId() == null) { + logger.error("somebody tried to set null tenant"); + throw new MyForbiddenException("tenant tampering"); + } + if (entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) { + logger.error("somebody tried to change an entries tenant"); + throw new MyForbiddenException("tenant tampering"); + } - final UUID tenantId = tenantScope.getTenant(); - entity.setTenantId(tenantId); + final UUID tenantId = tenantScope.getTenant(); + entity.setTenantId(tenantId); + } else { + if (entity.getTenantId() != null && entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) { + logger.error("somebody tried to change an entries tenant"); + throw new MyForbiddenException("tenant tampering"); + } + } + + } else { if (entity.getTenantId() != null) { logger.error("somebody tried to set non null tenant"); diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantScopedBaseEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantScopedBaseEntity.java index 0fac936ad..108a1d38d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantScopedBaseEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/tenant/TenantScopedBaseEntity.java @@ -15,8 +15,8 @@ import java.util.UUID; //@Setter //@NoArgsConstructor @FilterDef(name = TenantScopedBaseEntity.tenantFilter, parameters = {@ParamDef(name = TenantScopedBaseEntity.tenantFilterTenantParam, type = String.class)}) -@Filter(name = "tenantFilter", condition = "tenant = (cast(:tenantId as uuid))") -//@EntityListeners(TenantListener.class) +@Filter(name = "tenantFilter", condition = "(tenant = (cast(:tenantId as uuid)) or tenant is null)") +@EntityListeners(TenantListener.class) public abstract class TenantScopedBaseEntity implements TenantScoped, Serializable { private static final long serialVersionUID = 1L; public static final String tenantFilter = "tenantFilter"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java b/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java index e2aaac143..b6e19d58a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java +++ b/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java @@ -144,4 +144,24 @@ public class ErrorThesaurusProperties { public void setDmpDescriptionTemplateCanNotRemove(ErrorDescription dmpDescriptionTemplateCanNotRemove) { this.dmpDescriptionTemplateCanNotRemove = dmpDescriptionTemplateCanNotRemove; } + + private ErrorDescription missingTenant; + + public ErrorDescription getMissingTenant() { + return missingTenant; + } + + public void setMissingTenant(ErrorDescription missingTenant) { + this.missingTenant = missingTenant; + } + + private ErrorDescription tenantNotAllowed; + + public ErrorDescription getTenantNotAllowed() { + return tenantNotAllowed; + } + + public void setTenantNotAllowed(ErrorDescription tenantNotAllowed) { + this.tenantNotAllowed = tenantNotAllowed; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ActionConfirmationDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ActionConfirmationDeleter.java index fe6af4770..791788911 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ActionConfirmationDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ActionConfirmationDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.ActionConfirmationEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.ActionConfirmationQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -26,7 +26,7 @@ import java.util.UUID; public class ActionConfirmationDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ActionConfirmationDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -34,7 +34,7 @@ public class ActionConfirmationDeleter implements Deleter { @Autowired public ActionConfirmationDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionDeleter.java index 9259beb87..2135af4d0 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionDeleter.java @@ -4,6 +4,7 @@ import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionEntity; import eu.eudat.data.DescriptionReferenceEntity; import eu.eudat.data.DescriptionTagEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DescriptionQuery; import eu.eudat.query.DescriptionReferenceQuery; import eu.eudat.query.DescriptionTagQuery; @@ -13,7 +14,6 @@ import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -34,7 +34,7 @@ public class DescriptionDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -43,7 +43,7 @@ public class DescriptionDeleter implements Deleter { @Autowired public DescriptionDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory, ElasticService elasticService) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionReferenceDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionReferenceDeleter.java index 50752b336..7cd5cc0bf 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionReferenceDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionReferenceDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionReferenceEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DescriptionReferenceQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +27,7 @@ public class DescriptionReferenceDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionReferenceDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +35,7 @@ public class DescriptionReferenceDeleter implements Deleter { @Autowired public DescriptionReferenceDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTagDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTagDeleter.java index 887b4a85d..701a63a65 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTagDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTagDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionTagEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DescriptionTagQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +27,7 @@ public class DescriptionTagDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTagDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +35,7 @@ public class DescriptionTagDeleter implements Deleter { @Autowired public DescriptionTagDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateDeleter.java index 725006eb0..c8e43780f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateDeleter.java @@ -5,6 +5,7 @@ import eu.eudat.commons.enums.DmpVersionStatus; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.DmpDescriptionTemplateEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserDescriptionTemplateEntity; import eu.eudat.query.DescriptionQuery; import eu.eudat.query.DescriptionTemplateQuery; @@ -16,7 +17,6 @@ import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -36,7 +36,7 @@ public class DescriptionTemplateDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -44,7 +44,7 @@ public class DescriptionTemplateDeleter implements Deleter { @Autowired public DescriptionTemplateDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateTypeDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateTypeDeleter.java index 775cccf1a..4d0721c42 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateTypeDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DescriptionTemplateTypeDeleter.java @@ -1,11 +1,9 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; -import eu.eudat.data.DescriptionTagEntity; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.DescriptionTemplateTypeEntity; -import eu.eudat.data.ReferenceEntity; -import eu.eudat.query.DescriptionTagQuery; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DescriptionTemplateQuery; import eu.eudat.query.DescriptionTemplateTypeQuery; import gr.cite.tools.data.deleter.Deleter; @@ -13,7 +11,6 @@ import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -33,7 +30,7 @@ public class DescriptionTemplateTypeDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -41,7 +38,7 @@ public class DescriptionTemplateTypeDeleter implements Deleter { @Autowired public DescriptionTemplateTypeDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpBlueprintDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpBlueprintDeleter.java index f0b980ef8..017f242ab 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpBlueprintDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpBlueprintDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DmpBlueprintEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DmpBlueprintQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +27,7 @@ public class DmpBlueprintDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +35,7 @@ public class DmpBlueprintDeleter implements Deleter { @Autowired public DmpBlueprintDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDeleter.java index b0afbde30..8126d5637 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDeleter.java @@ -17,7 +17,6 @@ import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -37,7 +36,7 @@ public class DmpDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -46,7 +45,7 @@ public class DmpDeleter implements Deleter { @Autowired public DmpDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory, ElasticService elasticService) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDescriptionTemplateDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDescriptionTemplateDeleter.java index 404f96ee3..01b444c65 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDescriptionTemplateDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpDescriptionTemplateDeleter.java @@ -2,15 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DmpDescriptionTemplateEntity; -import eu.eudat.data.DmpReferenceEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DmpDescriptionTemplateQuery; -import eu.eudat.query.DmpReferenceQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -28,7 +26,7 @@ import java.util.UUID; public class DmpDescriptionTemplateDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpDescriptionTemplateDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -36,7 +34,7 @@ public class DmpDescriptionTemplateDeleter implements Deleter { @Autowired public DmpDescriptionTemplateDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpReferenceDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpReferenceDeleter.java index 89e3c2b69..4e0c2982f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpReferenceDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpReferenceDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DmpReferenceEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DmpReferenceQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -26,7 +26,7 @@ import java.util.UUID; public class DmpReferenceDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpReferenceDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -34,7 +34,7 @@ public class DmpReferenceDeleter implements Deleter { @Autowired public DmpReferenceDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpUserDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpUserDeleter.java index c1771a37a..7f986768e 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpUserDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/DmpUserDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DmpUserEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DmpUserQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -26,7 +26,7 @@ import java.util.UUID; public class DmpUserDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpUserDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -34,7 +34,7 @@ public class DmpUserDeleter implements Deleter { @Autowired public DmpUserDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/EntityDoiDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/EntityDoiDeleter.java index e090d092c..c0ae7937d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/EntityDoiDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/EntityDoiDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionTemplateTypeEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DescriptionTemplateTypeQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +27,7 @@ public class EntityDoiDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +35,7 @@ public class EntityDoiDeleter implements Deleter { @Autowired public EntityDoiDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java index 0e2add77c..7f173ad17 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.LanguageEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.LanguageQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -26,7 +26,7 @@ import java.util.UUID; public class LanguageDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LanguageDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -34,7 +34,7 @@ public class LanguageDeleter implements Deleter { @Autowired public LanguageDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LockDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LockDeleter.java index c011712a2..430642af4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LockDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LockDeleter.java @@ -1,13 +1,13 @@ package eu.eudat.model.deleter; import eu.eudat.data.LockEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.LockQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -24,7 +24,7 @@ import java.util.UUID; public class LockDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -32,7 +32,7 @@ public class LockDeleter implements Deleter { @Autowired public LockDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/PrefillingSourceDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/PrefillingSourceDeleter.java index 4e952f10b..972ea9e82 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/PrefillingSourceDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/PrefillingSourceDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.PrefillingSourceEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.PrefillingSourceQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -26,7 +26,7 @@ import java.util.UUID; public class PrefillingSourceDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrefillingSourceDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -34,7 +34,7 @@ public class PrefillingSourceDeleter implements Deleter { @Autowired public PrefillingSourceDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceDeleter.java index b522035b4..e0ae7a0a4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceDeleter.java @@ -1,10 +1,7 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; -import eu.eudat.data.DescriptionReferenceEntity; -import eu.eudat.data.DmpReferenceEntity; -import eu.eudat.data.ReferenceEntity; -import eu.eudat.data.TagEntity; +import eu.eudat.data.*; import eu.eudat.query.DescriptionReferenceQuery; import eu.eudat.query.DmpReferenceQuery; import eu.eudat.query.ReferenceQuery; @@ -13,7 +10,6 @@ import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -32,7 +28,7 @@ import java.util.stream.Collectors; public class ReferenceDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ReferenceDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -40,7 +36,7 @@ public class ReferenceDeleter implements Deleter { @Autowired public ReferenceDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceTypeDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceTypeDeleter.java index a627934a5..f1de449a6 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceTypeDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/ReferenceTypeDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.ReferenceTypeEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.ReferenceTypeQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -26,7 +26,7 @@ import java.util.UUID; public class ReferenceTypeDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ReferenceTypeDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -34,7 +34,7 @@ public class ReferenceTypeDeleter implements Deleter { @Autowired public ReferenceTypeDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java index f5a548e64..809b4af5c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.SupportiveMaterialEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.SupportiveMaterialQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +27,7 @@ public class SupportiveMaterialDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(SupportiveMaterialDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +35,7 @@ public class SupportiveMaterialDeleter implements Deleter { @Autowired public SupportiveMaterialDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TagDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TagDeleter.java index 55aa92e01..d163e0c00 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TagDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TagDeleter.java @@ -3,6 +3,7 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionTagEntity; import eu.eudat.data.TagEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.DescriptionTagQuery; import eu.eudat.query.TagQuery; import gr.cite.tools.data.deleter.Deleter; @@ -10,7 +11,6 @@ import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -29,7 +29,7 @@ import java.util.stream.Collectors; public class TagDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TagDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -37,7 +37,7 @@ public class TagDeleter implements Deleter { @Autowired public TagDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TenantDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TenantDeleter.java index 8d5f90e76..ca68887f3 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TenantDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/TenantDeleter.java @@ -2,13 +2,13 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.TenantEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.query.TenantQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +27,7 @@ public class TenantDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +35,7 @@ public class TenantDeleter implements Deleter { @Autowired public TenantDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserContactInfoDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserContactInfoDeleter.java index ff11615d7..bfa5723c7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserContactInfoDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserContactInfoDeleter.java @@ -1,12 +1,12 @@ package eu.eudat.model.deleter; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserContactInfoEntity; import eu.eudat.query.UserContactInfoQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -23,14 +23,14 @@ import java.util.UUID; public class UserContactInfoDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserContactInfoDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @Autowired public UserContactInfoDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory ) { this.entityManager = entityManager; diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserCredentialDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserCredentialDeleter.java index ac88df968..0677f1cec 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserCredentialDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserCredentialDeleter.java @@ -1,12 +1,12 @@ package eu.eudat.model.deleter; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserCredentialEntity; import eu.eudat.query.UserCredentialQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -23,14 +23,14 @@ import java.util.UUID; public class UserCredentialDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserCredentialDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @Autowired public UserCredentialDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory ) { this.entityManager = entityManager; diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDeleter.java index 97f4d5667..ca20045fa 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDeleter.java @@ -8,7 +8,6 @@ import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -27,7 +26,7 @@ import java.util.stream.Collectors; public class UserDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -35,7 +34,7 @@ public class UserDeleter implements Deleter { @Autowired public UserDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDescriptionTemplateDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDescriptionTemplateDeleter.java index be51b19ab..ec6eaea61 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDescriptionTemplateDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserDescriptionTemplateDeleter.java @@ -1,15 +1,14 @@ package eu.eudat.model.deleter; import eu.eudat.commons.enums.IsActive; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserDescriptionTemplateEntity; -import eu.eudat.query.DescriptionTemplateQuery; import eu.eudat.query.UserDescriptionTemplateQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -28,7 +27,7 @@ public class UserDescriptionTemplateDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserDescriptionTemplateDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @@ -36,7 +35,7 @@ public class UserDescriptionTemplateDeleter implements Deleter { @Autowired public UserDescriptionTemplateDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory, DeleterFactory deleterFactory ) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserRoleDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserRoleDeleter.java index 3738e8771..ceeff1743 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserRoleDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserRoleDeleter.java @@ -1,13 +1,12 @@ package eu.eudat.model.deleter; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserRoleEntity; import eu.eudat.query.UserRoleQuery; import gr.cite.tools.data.deleter.Deleter; -import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -15,25 +14,23 @@ import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.management.InvalidApplicationException; -import java.time.Instant; import java.util.List; import java.util.Optional; import java.util.UUID; -import java.util.stream.Collectors; @Component @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class UserRoleDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserRoleDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @Autowired public UserRoleDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory ) { this.entityManager = entityManager; diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserSettingsSettingsDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserSettingsSettingsDeleter.java index b312f05c9..3fcc8af86 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserSettingsSettingsDeleter.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/UserSettingsSettingsDeleter.java @@ -1,12 +1,12 @@ package eu.eudat.model.deleter; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserSettingsEntity; import eu.eudat.query.UserSettingsQuery; import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -23,14 +23,14 @@ import java.util.UUID; public class UserSettingsSettingsDeleter implements Deleter { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserSettingsSettingsDeleter.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; protected final QueryFactory queryFactory; @Autowired public UserSettingsSettingsDeleter( - EntityManager entityManager, + TenantEntityManager entityManager, QueryFactory queryFactory ) { this.entityManager = entityManager; diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionPersist.java index b593565b4..11758939f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionPersist.java @@ -4,22 +4,20 @@ import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.DescriptionStatus; import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; import eu.eudat.commons.validation.BaseValidator; -import eu.eudat.data.DescriptionTemplateEntity; -import eu.eudat.model.DescriptionTemplate; -import gr.cite.tools.exception.MyNotFoundException; -import gr.cite.tools.validation.ValidatorFactory; -import gr.cite.tools.validation.specification.Specification; import eu.eudat.convention.ConventionService; import eu.eudat.data.DescriptionEntity; +import eu.eudat.data.DescriptionTemplateEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.persist.descriptionproperties.PropertyDefinitionPersist; -import jakarta.persistence.EntityManager; +import gr.cite.tools.validation.specification.Specification; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Scope; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; +import javax.management.InvalidApplicationException; import java.util.Arrays; import java.util.List; import java.util.UUID; @@ -151,14 +149,12 @@ public class DescriptionPersist { private final MessageSource messageSource; - private final ValidatorFactory validatorFactory; - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final XmlHandlingService xmlHandlingService; - protected DescriptionPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory, EntityManager entityManager, XmlHandlingService xmlHandlingService) { + protected DescriptionPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, TenantEntityManager entityManager, XmlHandlingService xmlHandlingService) { super(conventionService, errors); this.messageSource = messageSource; - this.validatorFactory = validatorFactory; this.entityManager = entityManager; this.xmlHandlingService = xmlHandlingService; } @@ -170,8 +166,13 @@ public class DescriptionPersist { @Override protected List specifications(DescriptionPersist item) { - DescriptionTemplateEntity descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId()) : null; - DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition()); + DescriptionTemplateEntity descriptionTemplate = null; + try { + descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId()) : null; + } catch (InvalidApplicationException e) { + throw new RuntimeException(e); + } + DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition()); return Arrays.asList( this.spec() .iff(() -> this.isValidGuid(item.getId())) diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/actionconfirmation/ActionConfirmationServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/actionconfirmation/ActionConfirmationServiceImpl.java index d87bea565..5e8868077 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/actionconfirmation/ActionConfirmationServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/actionconfirmation/ActionConfirmationServiceImpl.java @@ -10,6 +10,7 @@ import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity; import eu.eudat.commons.types.actionconfirmation.RemoveCredentialRequestEntity; import eu.eudat.convention.ConventionService; import eu.eudat.data.ActionConfirmationEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.ActionConfirmation; import eu.eudat.model.ReferenceType; @@ -31,7 +32,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import jakarta.xml.bind.JAXBException; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; @@ -49,7 +49,7 @@ import java.util.UUID; public class ActionConfirmationServiceImpl implements ActionConfirmationService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; @@ -60,7 +60,7 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService private final UserScope userScope; public ActionConfirmationServiceImpl( - EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors, UserScope userScope) { this.entityManager = entityManager; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java index a377a67a8..1b8153f3d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java @@ -27,11 +27,11 @@ public interface DescriptionService { Map> getDescriptionSectionPermissions(DescriptionSectionPermissionResolver model); Description persist(DescriptionPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException; - Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException; + Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException, InvalidApplicationException; void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException; - List validate(List descriptionIds); + List validate(List descriptionIds) throws InvalidApplicationException; void clone(UUID dmpId, UUID descriptionId) throws InvalidApplicationException, IOException; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java index a7ed63e7f..c14b9db33 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java @@ -52,7 +52,6 @@ import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidatorFactory; -import jakarta.persistence.EntityManager; import org.apache.commons.io.FilenameUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; @@ -79,7 +78,7 @@ import java.util.stream.Collectors; public class DescriptionServiceImpl implements DescriptionService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; @@ -104,7 +103,7 @@ public class DescriptionServiceImpl implements DescriptionService { @Autowired public DescriptionServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, @@ -298,7 +297,7 @@ public class DescriptionServiceImpl implements DescriptionService { } @Override - public Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException { + public Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting data dmp").And("model", model).And("fields", fields)); this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription); @@ -329,7 +328,7 @@ public class DescriptionServiceImpl implements DescriptionService { return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Description._id), data); } - public List validate(List descriptionIds){ + public List validate(List descriptionIds) throws InvalidApplicationException { List descriptionValidationResults = new ArrayList<>(); List descriptions = this.queryFactory.query(DescriptionQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(descriptionIds).isActive(IsActive.Active).collect(); @@ -349,7 +348,7 @@ public class DescriptionServiceImpl implements DescriptionService { return descriptionValidationResults; } - private @NotNull PropertyDefinitionEntity buildPropertyDefinitionEntity(PropertyDefinitionPersist persist, eu.eudat.commons.types.descriptiontemplate.DefinitionEntity definition, Map> fieldToReferenceMap){ + private @NotNull PropertyDefinitionEntity buildPropertyDefinitionEntity(PropertyDefinitionPersist persist, eu.eudat.commons.types.descriptiontemplate.DefinitionEntity definition, Map> fieldToReferenceMap) throws InvalidApplicationException { PropertyDefinitionEntity data = new PropertyDefinitionEntity(); if (persist == null) return data; if (persist.getFieldSets() != null && !persist.getFieldSets().isEmpty()){ @@ -362,7 +361,7 @@ public class DescriptionServiceImpl implements DescriptionService { return data; } - private @NotNull PropertyDefinitionFieldSetEntity buildPropertyDefinitionFieldSetEntity(PropertyDefinitionFieldSetPersist persist, FieldSetEntity fieldSetEntity, Map> fieldToReferenceMap){ + private @NotNull PropertyDefinitionFieldSetEntity buildPropertyDefinitionFieldSetEntity(PropertyDefinitionFieldSetPersist persist, FieldSetEntity fieldSetEntity, Map> fieldToReferenceMap) throws InvalidApplicationException { PropertyDefinitionFieldSetEntity data = new PropertyDefinitionFieldSetEntity(); if (persist == null) return data; if (!this.conventionService.isListNullOrEmpty(persist.getItems())){ @@ -374,7 +373,7 @@ public class DescriptionServiceImpl implements DescriptionService { return data; } - private @NotNull PropertyDefinitionFieldSetItemEntity buildPropertyDefinitionFieldSetItemEntity(PropertyDefinitionFieldSetItemPersist persist, FieldSetEntity fieldSetEntity, Map> fieldToReferenceMap){ + private @NotNull PropertyDefinitionFieldSetItemEntity buildPropertyDefinitionFieldSetItemEntity(PropertyDefinitionFieldSetItemPersist persist, FieldSetEntity fieldSetEntity, Map> fieldToReferenceMap) throws InvalidApplicationException { PropertyDefinitionFieldSetItemEntity data = new PropertyDefinitionFieldSetItemEntity(); if (persist == null) return data; if (persist.getFields() != null && !persist.getFields().isEmpty()){ @@ -389,7 +388,7 @@ public class DescriptionServiceImpl implements DescriptionService { return data; } - private @NotNull FieldEntity buildFieldEntity(FieldPersist persist, eu.eudat.commons.types.descriptiontemplate.FieldEntity fieldEntity, Map> fieldToReferenceMap){ + private @NotNull FieldEntity buildFieldEntity(FieldPersist persist, eu.eudat.commons.types.descriptiontemplate.FieldEntity fieldEntity, Map> fieldToReferenceMap) throws InvalidApplicationException { FieldType fieldType = fieldEntity != null && fieldEntity.getData() != null ? fieldEntity.getData().getFieldType() : FieldType.FREE_TEXT; FieldEntity data = new FieldEntity(); if (persist == null) return data; @@ -806,7 +805,7 @@ public class DescriptionServiceImpl implements DescriptionService { //region build persist - private @NotNull DescriptionPersist buildDescriptionPersist(DescriptionEntity data){ + private @NotNull DescriptionPersist buildDescriptionPersist(DescriptionEntity data) throws InvalidApplicationException { DescriptionPersist persist = new DescriptionPersist(); if (data == null) return persist; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java index acaf185c2..0e2d38b6b 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java @@ -49,7 +49,6 @@ import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidatorFactory; -import jakarta.persistence.EntityManager; import jakarta.xml.bind.JAXBException; import org.apache.commons.lang3.NotImplementedException; import org.jetbrains.annotations.NotNull; @@ -79,7 +78,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final UserScope userScope; @@ -116,7 +115,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic @Autowired public DescriptionTemplateServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, UserScope userScope, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, @@ -206,7 +205,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return this.builderFactory.builder(DescriptionTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, DescriptionTemplate._id), data); } - private void updateVersionStatusAndSave(DescriptionTemplateEntity data, DescriptionTemplateStatus previousStatus, DescriptionTemplateStatus newStatus) { + private void updateVersionStatusAndSave(DescriptionTemplateEntity data, DescriptionTemplateStatus previousStatus, DescriptionTemplateStatus newStatus) throws InvalidApplicationException { if (previousStatus.equals(newStatus)) return; if (previousStatus.equals(DescriptionTemplateStatus.Finalized)) @@ -298,7 +297,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic this.entityManager.persist(data); } - private @NotNull DefinitionEntity buildDefinitionEntity(DefinitionPersist persist) { + private @NotNull DefinitionEntity buildDefinitionEntity(DefinitionPersist persist) throws InvalidApplicationException { DefinitionEntity data = new DefinitionEntity(); if (persist == null) return data; @@ -313,7 +312,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return data; } - private @NotNull SectionEntity buildSectionEntity(SectionPersist persist) { + private @NotNull SectionEntity buildSectionEntity(SectionPersist persist) throws InvalidApplicationException { SectionEntity data = new SectionEntity(); if (persist == null) return data; @@ -342,7 +341,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return data; } - private @NotNull FieldSetEntity buildFieldSetEntity(FieldSetPersist persist) { + private @NotNull FieldSetEntity buildFieldSetEntity(FieldSetPersist persist) throws InvalidApplicationException { FieldSetEntity data = new FieldSetEntity(); if (persist == null) return data; @@ -367,7 +366,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return data; } - private @NotNull FieldEntity buildFieldEntity(FieldPersist persist) { + private @NotNull FieldEntity buildFieldEntity(FieldPersist persist) throws InvalidApplicationException { FieldEntity data = new FieldEntity(); if (persist == null) return data; @@ -397,7 +396,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return this.fieldDataHelperServiceProvider.get(persist.getFieldType()).applyPersist(persist); } - private @NotNull RuleEntity buildRuleEntity(RulePersist persist, FieldEntity fieldEntity){ + private @NotNull RuleEntity buildRuleEntity(RulePersist persist, FieldEntity fieldEntity) throws InvalidApplicationException { FieldType fieldType = fieldEntity != null && fieldEntity.getData() != null ? fieldEntity.getData().getFieldType() : FieldType.FREE_TEXT; RuleEntity data = new RuleEntity(); if (persist == null) return data; @@ -444,7 +443,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return data; } - private List patchAndSaveReferences(List models, FieldEntity fieldEntity) { + private List patchAndSaveReferences(List models, FieldEntity fieldEntity) throws InvalidApplicationException { if (models == null) models = new ArrayList<>(); List referenceIds = new ArrayList<>(); @@ -520,7 +519,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic return data; } - private @NotNull PageEntity buildPageEntity(PagePersist persist) { + private @NotNull PageEntity buildPageEntity(PagePersist persist) throws InvalidApplicationException { PageEntity data = new PageEntity(); if (persist == null) return data; @@ -881,7 +880,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic //region Export @Override - public ResponseEntity exportXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException { + public ResponseEntity exportXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting data").And("id", id)); this.authorizationService.authorizeForce(Permission.ExportDescriptionTemplate); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplatetype/DescriptionTemplateTypeServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplatetype/DescriptionTemplateTypeServiceImpl.java index de38afd60..d69cea4e0 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplatetype/DescriptionTemplateTypeServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplatetype/DescriptionTemplateTypeServiceImpl.java @@ -5,6 +5,7 @@ import eu.eudat.authorization.Permission; import eu.eudat.commons.enums.IsActive; import eu.eudat.convention.ConventionService; import eu.eudat.data.DescriptionTemplateTypeEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.event.DescriptionTemplateTypeTouchedEvent; import eu.eudat.event.EventBroker; @@ -23,7 +24,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -40,7 +40,7 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; @@ -58,7 +58,7 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy @Autowired public DescriptionTemplateTypeServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java index 7be2dc957..13e4b48fb 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java @@ -60,7 +60,6 @@ import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidatorFactory; -import jakarta.persistence.EntityManager; import jakarta.xml.bind.JAXBException; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; @@ -84,7 +83,7 @@ public class DmpServiceImpl implements DmpService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; @@ -128,7 +127,7 @@ public class DmpServiceImpl implements DmpService { @Autowired public DmpServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, @@ -450,7 +449,7 @@ public class DmpServiceImpl implements DmpService { return this.builderFactory.builder(DmpBuilder.class).build(BaseFieldSet.build(fields, Dmp._id), newDmp); } - private void updateVersionStatusAndSave(DmpEntity data, DmpStatus previousStatus, DmpStatus newStatus) { + private void updateVersionStatusAndSave(DmpEntity data, DmpStatus previousStatus, DmpStatus newStatus) throws InvalidApplicationException { if (previousStatus.equals(newStatus)) return; if (previousStatus.equals(DmpStatus.Finalized) && newStatus.equals(DmpStatus.Draft)){ @@ -1083,7 +1082,7 @@ public class DmpServiceImpl implements DmpService { return persist.getToken(); } - public void dmpInvitationAccept(String token) { + public void dmpInvitationAccept(String token) throws InvalidApplicationException { ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.DmpInvitation).isActive(IsActive.Active).first(); if (action == null){ diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintService.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintService.java index e7c7b9f0a..bd5d641b8 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintService.java @@ -28,7 +28,7 @@ public interface DmpBlueprintService { void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; boolean fieldInBlueprint(DmpBlueprintEntity dmpBlueprintEntity, DmpBlueprintSystemFieldType type); - boolean fieldInBlueprint(UUID id, DmpBlueprintSystemFieldType type); + boolean fieldInBlueprint(UUID id, DmpBlueprintSystemFieldType type) throws InvalidApplicationException; DmpBlueprint buildClone(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java index fe192a8e2..b09cd918c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java @@ -9,6 +9,7 @@ import eu.eudat.commons.types.dmpblueprint.*; import eu.eudat.commons.types.dmpblueprint.importexport.*; import eu.eudat.convention.ConventionService; import eu.eudat.data.DmpBlueprintEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.DmpBlueprint; import eu.eudat.model.builder.DmpBlueprintBuilder; @@ -34,7 +35,6 @@ import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidatorFactory; -import jakarta.persistence.EntityManager; import jakarta.xml.bind.JAXBException; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; @@ -61,7 +61,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; @@ -85,7 +85,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { @Autowired public DmpBlueprintServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, @@ -162,7 +162,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { return this.builderFactory.builder(DmpBlueprintBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, DmpBlueprint._id), data); } - private void updateVersionStatusAndSave(DmpBlueprintEntity data, DmpBlueprintStatus previousStatus, DmpBlueprintStatus newStatus) { + private void updateVersionStatusAndSave(DmpBlueprintEntity data, DmpBlueprintStatus previousStatus, DmpBlueprintStatus newStatus) throws InvalidApplicationException { if (previousStatus.equals(newStatus)) return; if (previousStatus.equals(DmpBlueprintStatus.Finalized)) @@ -320,7 +320,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { return false; } - public boolean fieldInBlueprint(UUID id, DmpBlueprintSystemFieldType type) { + public boolean fieldInBlueprint(UUID id, DmpBlueprintSystemFieldType type) throws InvalidApplicationException { DmpBlueprintEntity data = this.entityManager.find(DmpBlueprintEntity.class, id); if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, DmpBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale())); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticService.java b/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticService.java index 092b531e9..f58965132 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticService.java @@ -3,6 +3,7 @@ package eu.eudat.service.elastic; import eu.eudat.data.DescriptionEntity; import eu.eudat.data.DmpEntity; +import javax.management.InvalidApplicationException; import java.io.IOException; public interface ElasticService { @@ -21,9 +22,9 @@ public interface ElasticService { void deleteDmp(DmpEntity dmp) throws IOException; - void persistDescription(DescriptionEntity description) throws IOException; + void persistDescription(DescriptionEntity description) throws IOException, InvalidApplicationException; - void deleteDescription(DescriptionEntity description) throws IOException; + void deleteDescription(DescriptionEntity description) throws IOException, InvalidApplicationException; void deleteDmpIndex() throws IOException; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticServiceImpl.java index 0621511e5..667ccd73e 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/elastic/ElasticServiceImpl.java @@ -8,6 +8,7 @@ import eu.eudat.authorization.Permission; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.DescriptionEntity; import eu.eudat.data.DmpEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.elastic.data.DescriptionElasticEntity; import eu.eudat.elastic.data.DmpElasticEntity; import eu.eudat.elastic.data.nested.*; @@ -28,7 +29,6 @@ import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; @@ -41,6 +41,8 @@ import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.stereotype.Service; +import javax.management.InvalidApplicationException; + @Service public class ElasticServiceImpl implements ElasticService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintServiceImpl.class)); @@ -49,11 +51,11 @@ public class ElasticServiceImpl implements ElasticService { private final ElasticsearchTemplate elasticsearchTemplate; private final QueryFactory queryFactory; private final BuilderFactory builderFactory; - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final MessageSource messageSource; private final AuthorizationService authorizationService; - public ElasticServiceImpl(AppElasticProperties appElasticProperties, ElasticsearchClient restHighLevelClient, ElasticsearchTemplate elasticsearchTemplate, QueryFactory queryFactory, BuilderFactory builderFactory, EntityManager entityManager, MessageSource messageSource, AuthorizationService authorizationService) { + public ElasticServiceImpl(AppElasticProperties appElasticProperties, ElasticsearchClient restHighLevelClient, ElasticsearchTemplate elasticsearchTemplate, QueryFactory queryFactory, BuilderFactory builderFactory, TenantEntityManager entityManager, MessageSource messageSource, AuthorizationService authorizationService) { this.appElasticProperties = appElasticProperties; this.restHighLevelClient = restHighLevelClient; this.elasticsearchTemplate = elasticsearchTemplate; @@ -295,7 +297,7 @@ public class ElasticServiceImpl implements ElasticService { } @Override - public void persistDescription(DescriptionEntity description) throws IOException { + public void persistDescription(DescriptionEntity description) throws IOException, InvalidApplicationException { if (!this.enabled()) return; this.ensureIndexes(); @@ -310,7 +312,7 @@ public class ElasticServiceImpl implements ElasticService { } @Override - public void deleteDescription(DescriptionEntity description) throws IOException { + public void deleteDescription(DescriptionEntity description) throws IOException, InvalidApplicationException { if (!this.enabled()) return; this.ensureIndexes(); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/entitydoi/EntityDoiServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/entitydoi/EntityDoiServiceImpl.java index 8bbb126e5..239d0434c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/entitydoi/EntityDoiServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/entitydoi/EntityDoiServiceImpl.java @@ -6,6 +6,7 @@ import eu.eudat.commons.enums.EntityType; import eu.eudat.commons.enums.IsActive; import eu.eudat.convention.ConventionService; import eu.eudat.data.EntityDoiEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.event.EntityDoiTouchedEvent; import eu.eudat.event.EventBroker; @@ -24,7 +25,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -41,7 +41,7 @@ public class EntityDoiServiceImpl implements EntityDoiService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(EntityDoiServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; @@ -59,7 +59,7 @@ public class EntityDoiServiceImpl implements EntityDoiService { @Autowired public EntityDoiServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java index 4be900a4d..7081e44b8 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java @@ -5,6 +5,7 @@ import eu.eudat.authorization.Permission; import eu.eudat.commons.enums.IsActive; import eu.eudat.convention.ConventionService; import eu.eudat.data.LanguageEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.Language; import eu.eudat.model.builder.LanguageBuilder; @@ -23,7 +24,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.hibernate.FlushMode; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; @@ -41,7 +41,7 @@ import java.util.UUID; public class LanguageServiceImpl implements LanguageService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; @@ -52,7 +52,7 @@ public class LanguageServiceImpl implements LanguageService { public LanguageServiceImpl( - EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, ConventionService conventionService, MessageSource messageSource, ErrorThesaurusProperties errors, StorageFileService storageFileService){ this.entityManager = entityManager; this.authorizationService = authorizationService; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java index 98ca5bdc9..0a3f35480 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java @@ -8,6 +8,7 @@ import eu.eudat.commons.enums.LockTargetType; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.convention.ConventionService; import eu.eudat.data.LockEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.Lock; import eu.eudat.model.LockStatus; @@ -27,7 +28,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -46,7 +46,7 @@ public class LockServiceImpl implements LockService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockServiceImpl.class)); private final Comparator compareByTouchedAt = Comparator.comparing(o -> o.getTouchedAt()); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final UserScope userScope; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; @@ -60,7 +60,7 @@ public class LockServiceImpl implements LockService { @Autowired public LockServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, UserScope userScope, AuthorizationService authorizationService, DeleterFactory deleterFactory, diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceService.java b/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceService.java index ead478ab2..fc5cbe4c2 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceService.java @@ -28,6 +28,6 @@ public interface PrefillingSourceService { List searchPrefillings(PrefillingSearchRequest model); - Description getPrefilledDescription(DescriptionProfilingRequest model, FieldSet fields) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException; + Description getPrefilledDescription(DescriptionProfilingRequest model, FieldSet fields) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceServiceImpl.java index aee9507a6..8d2f9fcd4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/prefillingsource/PrefillingSourceServiceImpl.java @@ -17,6 +17,7 @@ import eu.eudat.commons.types.prefillingsource.PrefillingSourceDefinitionFixedVa import eu.eudat.convention.ConventionService; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.PrefillingSourceEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.*; import eu.eudat.model.builder.DescriptionTemplateBuilder; @@ -50,8 +51,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import gr.cite.tools.validation.ValidatorFactory; -import jakarta.persistence.EntityManager; import jakarta.xml.bind.JAXBException; import org.apache.commons.lang3.StringEscapeUtils; import org.jetbrains.annotations.NotNull; @@ -78,7 +77,7 @@ import java.util.stream.Stream; public class PrefillingSourceServiceImpl implements PrefillingSourceService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrefillingSourceServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; @@ -88,16 +87,15 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { private final XmlHandlingService xmlHandlingService; private final ExternalFetcherService externalFetcherService; private final ErrorThesaurusProperties errors; - private final ValidatorFactory validatorFactory; private final JsonHandlingService jsonHandlingService; private final ReferenceService referenceService; private static final String Zenodo = "Zenodo"; public PrefillingSourceServiceImpl( - EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, QueryFactory queryFactory, ConventionService conventionService, MessageSource messageSource, - XmlHandlingService xmlHandlingService, ExternalFetcherService externalFetcherService, ErrorThesaurusProperties errors, ValidatorFactory validatorFactory, JsonHandlingService jsonHandlingService, ReferenceService referenceService) { + XmlHandlingService xmlHandlingService, ExternalFetcherService externalFetcherService, ErrorThesaurusProperties errors, JsonHandlingService jsonHandlingService, ReferenceService referenceService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -108,7 +106,6 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { this.xmlHandlingService = xmlHandlingService; this.externalFetcherService = externalFetcherService; this.errors = errors; - this.validatorFactory = validatorFactory; this.jsonHandlingService = jsonHandlingService; this.referenceService = referenceService; } @@ -340,7 +337,7 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { return prefillings; } - public Description getPrefilledDescription(DescriptionProfilingRequest model, FieldSet fieldSet) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException { + public Description getPrefilledDescription(DescriptionProfilingRequest model, FieldSet fieldSet) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException { PrefillingSourceEntity prefillingSourceEntity = this.queryFactory.query(PrefillingSourceQuery.class).ids(model.getPrefillingSourceId()).first(); if (prefillingSourceEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPrefillingSourceId(), PrefillingSource.class.getSimpleName()}, LocaleContextHolder.getLocale())); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceService.java b/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceService.java index 7ab043e5f..eebb1aff8 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceService.java @@ -22,5 +22,5 @@ public interface ReferenceService { void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; - List searchReferenceData(ReferenceSearchLookup lookup) throws MyNotFoundException; + List searchReferenceData(ReferenceSearchLookup lookup) throws MyNotFoundException, InvalidApplicationException; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java index 4fc5a90df..c9e922037 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/reference/ReferenceServiceImpl.java @@ -13,6 +13,7 @@ import eu.eudat.commons.types.referencetype.*; import eu.eudat.convention.ConventionService; import eu.eudat.data.ReferenceEntity; import eu.eudat.data.ReferenceTypeEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.model.Reference; import eu.eudat.model.ReferenceType; import eu.eudat.model.builder.ReferenceBuilder; @@ -57,7 +58,7 @@ import java.util.stream.Collectors; public class ReferenceServiceImpl implements ReferenceService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ReferenceServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; @@ -68,7 +69,7 @@ public class ReferenceServiceImpl implements ReferenceService { public final ExternalFetcherService externalFetcherService; public ReferenceServiceImpl( - EntityManager entityManager, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, @@ -159,7 +160,7 @@ public class ReferenceServiceImpl implements ReferenceService { } @Override - public List searchReferenceData(ReferenceSearchLookup lookup) throws MyNotFoundException { + public List searchReferenceData(ReferenceSearchLookup lookup) throws MyNotFoundException, InvalidApplicationException { int initialOffset = 0; if (lookup.getPage() != null && !lookup.getPage().isEmpty()){ initialOffset = lookup.getPage().getOffset(); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/referencetype/ReferenceTypeServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/referencetype/ReferenceTypeServiceImpl.java index 3f775bb96..2e182190a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/referencetype/ReferenceTypeServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/referencetype/ReferenceTypeServiceImpl.java @@ -9,6 +9,7 @@ import eu.eudat.commons.types.externalfetcher.*; import eu.eudat.commons.types.referencetype.*; import eu.eudat.convention.ConventionService; import eu.eudat.data.ReferenceTypeEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.ReferenceType; import eu.eudat.model.builder.ReferenceTypeBuilder; @@ -27,7 +28,6 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; -import jakarta.persistence.EntityManager; import jakarta.xml.bind.JAXBException; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; @@ -46,7 +46,7 @@ import java.util.UUID; public class ReferenceTypeServiceImpl implements ReferenceTypeService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ReferenceTypeServiceImpl.class)); - private final EntityManager entityManager; + private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; @@ -57,7 +57,7 @@ public class ReferenceTypeServiceImpl implements ReferenceTypeService { public ReferenceTypeServiceImpl( - EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors) { this.entityManager = entityManager; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/storage/StorageFileCleanupTask.java b/dmp-backend/core/src/main/java/eu/eudat/service/storage/StorageFileCleanupTask.java index f63dd3408..7ff2c597a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/storage/StorageFileCleanupTask.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/storage/StorageFileCleanupTask.java @@ -1,6 +1,7 @@ package eu.eudat.service.storage; import eu.eudat.commons.fake.FakeRequestScope; +import eu.eudat.commons.scope.tenant.TenantScope; import eu.eudat.data.StorageFileEntity; import eu.eudat.model.StorageFile; import eu.eudat.query.StorageFileQuery; @@ -117,6 +118,8 @@ public class StorageFileCleanupTask implements Closeable, ApplicationListener validate(@RequestParam(value="descriptionIds") List descriptionIds) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + public List validate(@RequestParam(value="descriptionIds") List descriptionIds) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { logger.debug(new MapLogEntry("validating" + Description.class.getSimpleName()).And("descriptionIds", descriptionIds)); this.censorFactory.censor(DescriptionCensor.class).censor(null, null); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/PrefillingSourceController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/PrefillingSourceController.java index fa55207df..cdc777ec9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/PrefillingSourceController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/PrefillingSourceController.java @@ -163,7 +163,7 @@ public class PrefillingSourceController { @PostMapping("generate") @ValidationFilterAnnotation(validator = DescriptionProfilingRequest.DescriptionProfilingRequestValidator.ValidatorName, argumentName = "model") - public Description generate(@RequestBody DescriptionProfilingRequest model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException { + public Description generate(@RequestBody DescriptionProfilingRequest model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting" + Prefilling.class.getSimpleName()).And("model", model)); this.censorFactory.censor(DescriptionCensor.class).censor(fieldSet, null); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/PrincipalController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/PrincipalController.java index 0ee3fd5b0..2ad57ad54 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/PrincipalController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/PrincipalController.java @@ -1,21 +1,26 @@ package eu.eudat.controllers; import eu.eudat.audit.AuditableAction; +import eu.eudat.commons.scope.tenant.TenantScope; import eu.eudat.models.Account; import eu.eudat.models.AccountBuilder; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; import gr.cite.commons.web.oidc.principal.MyPrincipal; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.management.InvalidApplicationException; +import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping(value = { "/api/principal/" }) @@ -25,15 +30,17 @@ public class PrincipalController { private final CurrentPrincipalResolver currentPrincipalResolver; private final AccountBuilder accountBuilder; + private final ClaimExtractor claimExtractor; @Autowired public PrincipalController( CurrentPrincipalResolver currentPrincipalResolver, AccountBuilder accountBuilder, - AuditService auditService) { + AuditService auditService, ClaimExtractor claimExtractor) { this.currentPrincipalResolver = currentPrincipalResolver; this.accountBuilder = accountBuilder; this.auditService = auditService; + this.claimExtractor = claimExtractor; } @RequestMapping(path = "me", method = RequestMethod.GET ) @@ -71,4 +78,17 @@ public class PrincipalController { return me; } + @GetMapping("my-tenants") + public List myTenants() { + logger.debug("my-tenants"); + + MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal(); + List tenants = this.claimExtractor.asStrings(principal, TenantScope.TenantCodesClaimName); + + this.auditService.track(AuditableAction.Principal_MyTenants); + //auditService.trackIdentity(AuditableAction.IdentityTracking_Action); + + return tenants == null ? null : tenants.stream().distinct().collect(Collectors.toList()); + } + } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/ReferenceController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/ReferenceController.java index 524537af6..ffb3f213b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/ReferenceController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/ReferenceController.java @@ -93,7 +93,7 @@ public class ReferenceController { @PostMapping("search") - public List searchReferenceWithDefinition(@RequestBody ReferenceSearchLookup lookup) throws MyNotFoundException { + public List searchReferenceWithDefinition(@RequestBody ReferenceSearchLookup lookup) throws MyNotFoundException, InvalidApplicationException { logger.debug("search with db definition {}", Reference.class.getSimpleName()); this.censorFactory.censor(ReferenceCensor.class).censor(lookup.getProject(), null); diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheOptions.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheOptions.java new file mode 100644 index 000000000..38d7542d3 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheOptions.java @@ -0,0 +1,10 @@ +package eu.eudat.interceptors.tenant; + +import gr.cite.tools.cache.CacheOptions; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "cache.tenant-by-code") +public class TenantByCodeCacheOptions extends CacheOptions { +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheService.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheService.java new file mode 100644 index 000000000..ddf9fda84 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByCodeCacheService.java @@ -0,0 +1,78 @@ +package eu.eudat.interceptors.tenant; + +import eu.eudat.convention.ConventionService; +import eu.eudat.event.TenantTouchedEvent; +import gr.cite.tools.cache.CacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.UUID; + +@Service +public class TenantByCodeCacheService extends CacheService { + + public static class TenantByCodeCacheValue { + + public TenantByCodeCacheValue() { + } + + public TenantByCodeCacheValue(String tenantCode, UUID tenantId) { + this.tenantCode = tenantCode; + this.tenantId = tenantId; + } + + private String tenantCode; + + public String getTenantCode() { + return tenantCode; + } + + public void setTenantCode(String tenantCode) { + this.tenantCode = tenantCode; + } + + private UUID tenantId; + + public UUID getTenantId() { + return tenantId; + } + + public void setTenantId(UUID tenantId) { + this.tenantId = tenantId; + } + } + + private final ConventionService conventionService; + + @Autowired + public TenantByCodeCacheService(TenantByCodeCacheOptions options, ConventionService conventionService) { + super(options); + this.conventionService = conventionService; + } + + @EventListener + public void handleTenantTouchedEvent(TenantTouchedEvent event) { + if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) + this.evict(this.buildKey(event.getTenantCode())); + if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode())) + this.evict(this.buildKey(event.getPreviousTenantCode())); + } + + @Override + protected Class valueClass() { + return TenantByCodeCacheValue.class; + } + + @Override + public String keyOf(TenantByCodeCacheValue value) { + return this.buildKey(value.getTenantCode()); + } + + public String buildKey(String code) { + HashMap keyParts = new HashMap<>(); + keyParts.put("$code$", code); + return this.generateKey(keyParts); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheOptions.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheOptions.java new file mode 100644 index 000000000..2de9f2e0c --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheOptions.java @@ -0,0 +1,10 @@ +package eu.eudat.interceptors.tenant; + +import gr.cite.tools.cache.CacheOptions; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "cache.tenant-by-id") +public class TenantByIdCacheOptions extends CacheOptions { +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheService.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheService.java new file mode 100644 index 000000000..2ff624348 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantByIdCacheService.java @@ -0,0 +1,77 @@ +package eu.eudat.interceptors.tenant; + +import eu.eudat.convention.ConventionService; +import eu.eudat.event.TenantTouchedEvent; +import gr.cite.tools.cache.CacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Locale; +import java.util.UUID; + +@Service +public class TenantByIdCacheService extends CacheService { + + public static class TenantByIdCacheValue { + + public TenantByIdCacheValue() { + } + + public TenantByIdCacheValue(String tenantCode, UUID tenantId) { + this.tenantCode = tenantCode; + this.tenantId = tenantId; + } + + private String tenantCode; + + public String getTenantCode() { + return tenantCode; + } + + public void setTenantCode(String tenantCode) { + this.tenantCode = tenantCode; + } + + private UUID tenantId; + + public UUID getTenantId() { + return tenantId; + } + + public void setTenantId(UUID tenantId) { + this.tenantId = tenantId; + } + } + + private final ConventionService conventionService; + + @Autowired + public TenantByIdCacheService(TenantByIdCacheOptions options, ConventionService conventionService) { + super(options); + this.conventionService = conventionService; + } + + @EventListener + public void handleTenantTouchedEvent(TenantTouchedEvent event) { + if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) + this.evict(this.buildKey(event.getTenantId())); + } + + @Override + protected Class valueClass() { + return TenantByIdCacheValue.class; + } + + @Override + public String keyOf(TenantByIdCacheValue value) { + return this.buildKey(value.getTenantId()); + } + + public String buildKey(UUID id) { + HashMap keyParts = new HashMap<>(); + keyParts.put("$tenantId$", id.toString().toLowerCase(Locale.ROOT)); + return this.generateKey(keyParts); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantInterceptor.java new file mode 100644 index 000000000..660e71852 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantInterceptor.java @@ -0,0 +1,222 @@ +package eu.eudat.interceptors.tenant; + + +import eu.eudat.authorization.Permission; +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.scope.tenant.TenantScope; +import eu.eudat.commons.scope.user.UserScope; +import eu.eudat.data.DmpReferenceEntity; +import eu.eudat.data.ReferenceEntity; +import eu.eudat.data.TenantUserEntity; +import eu.eudat.data.UserEntity; +import eu.eudat.data.tenant.TenantScopedBaseEntity; +import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.query.utils.BuildSubQueryInput; +import eu.eudat.query.utils.QueryUtilsService; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; +import org.hibernate.Session; +import org.jetbrains.annotations.NotNull; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; +import org.springframework.ui.ModelMap; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.context.request.WebRequestInterceptor; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +@Component +public class TenantInterceptor implements WebRequestInterceptor { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantInterceptor.class)); + private final TenantScope tenantScope; + private final UserScope userScope; + private final CurrentPrincipalResolver currentPrincipalResolver; + private final ClaimExtractor claimExtractor; + private final ApplicationContext applicationContext; + private final TenantScopeProperties tenantScopeProperties; + private final UserAllowedTenantCacheService userAllowedTenantCacheService; + private final PlatformTransactionManager transactionManager; + private final ErrorThesaurusProperties errors; + private final QueryUtilsService queryUtilsService; + @PersistenceContext + public EntityManager entityManager; + + @Autowired + public TenantInterceptor( + TenantScope tenantScope, + UserScope userScope, + CurrentPrincipalResolver currentPrincipalResolver, + ClaimExtractor claimExtractor, + ApplicationContext applicationContext, + TenantScopeProperties tenantScopeProperties, + UserAllowedTenantCacheService userAllowedTenantCacheService, + PlatformTransactionManager transactionManager, + ErrorThesaurusProperties errors, QueryUtilsService queryUtilsService) { + this.tenantScope = tenantScope; + this.userScope = userScope; + this.currentPrincipalResolver = currentPrincipalResolver; + this.claimExtractor = claimExtractor; + this.applicationContext = applicationContext; + this.tenantScopeProperties = tenantScopeProperties; + this.userAllowedTenantCacheService = userAllowedTenantCacheService; + this.transactionManager = transactionManager; + this.errors = errors; + this.queryUtilsService = queryUtilsService; + } + + @Override + public void preHandle(@NotNull WebRequest request) throws InvalidApplicationException { + if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return; + if (!this.tenantScope.isMultitenant()) return; + + boolean isAllowedNoTenant = this.applicationContext.getBean(AuthorizationService.class).authorize(Permission.AllowNoTenant); + if (tenantScope.isSet() && this.entityManager != null) { + List currentPrincipalTenantCodes = this.claimExtractor.asStrings(this.currentPrincipalResolver.currentPrincipal(), TenantScope.TenantCodesClaimName); + if ((currentPrincipalTenantCodes == null || !currentPrincipalTenantCodes.contains(tenantScope.getTenantCode())) && !isAllowedNoTenant) { + logger.warn("tenant not allowed {}", this.tenantScope.getTenant()); + throw new MyForbiddenException(this.errors.getTenantNotAllowed().getCode(), this.errors.getTenantNotAllowed().getMessage()); + } + + boolean isUserAllowedTenant = false; + UserAllowedTenantCacheService.UserAllowedTenantCacheValue cacheValue = this.userAllowedTenantCacheService.lookup(this.userAllowedTenantCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.getTenant())); + if (cacheValue != null) { + isUserAllowedTenant = cacheValue.isAllowed(); + } else { + isUserAllowedTenant = this.isUserAllowedTenant(); + this.userAllowedTenantCacheService.put(new UserAllowedTenantCacheService.UserAllowedTenantCacheValue(this.userScope.getUserId(), this.tenantScope.getTenant(), isUserAllowedTenant)); + } + + if (isUserAllowedTenant) { + this.entityManager + .unwrap(Session.class) + .enableFilter(TenantScopedBaseEntity.tenantFilter).setParameter(TenantScopedBaseEntity.tenantFilterTenantParam, tenantScope.getTenant().toString()); + } else { + if (isAllowedNoTenant || this.isWhiteListedEndpoint(request)) { + tenantScope.setTenant(null, null); + } else { + logger.warn("tenant not allowed {}", this.tenantScope.getTenant()); + throw new MyForbiddenException(this.errors.getTenantNotAllowed().getCode(), this.errors.getTenantNotAllowed().getMessage()); + } + } + } else { + if (!isAllowedNoTenant) { + if (!this.isWhiteListedEndpoint(request)) { + logger.warn("tenant scope not provided"); + throw new MyForbiddenException(this.errors.getMissingTenant().getCode(), this.errors.getMissingTenant().getMessage()); + } + } + } + } + + private boolean isWhiteListedEndpoint(WebRequest request) { + String servletPath = ((ServletWebRequest) request).getRequest().getServletPath(); + if (this.tenantScopeProperties.getWhiteListedEndpoints() != null) { + for (String whiteListedEndpoint : this.tenantScopeProperties.getWhiteListedEndpoints()) { + if (servletPath.toLowerCase(Locale.ROOT).startsWith(whiteListedEndpoint.toLowerCase(Locale.ROOT))) { + return true; + } + } + } + return false; + } + + private boolean isUserAllowedTenant() throws InvalidApplicationException { + if (userScope.isSet()) { + + CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(Tuple.class); + Root root = query.from(UserEntity.class); + query.where(criteriaBuilder.and( + criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active), + criteriaBuilder.in(root.get(UserEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(TenantUserEntity.class, UUID.class) + .query(query) + .criteriaBuilder(criteriaBuilder) + .keyPathFunc((subQueryRoot) -> subQueryRoot.get(TenantUserEntity._userId)) + .filterFunc((subQueryRoot, cb) -> + { + try { + return cb.and( + criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._tenantId), this.tenantScope.getTenant()), + criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._userId), this.userScope.getUserId()), + criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._isActive), IsActive.Active) + ); + } catch (InvalidApplicationException e) { + throw new RuntimeException(e); + } + } + ) + )) + ) + )); + query.multiselect(root.get(UserEntity._id).alias(UserEntity._id)); + List results = this.entityManager.createQuery(query).getResultList(); + if (results.isEmpty() && this.tenantScopeProperties.getAutoCreateTenantUser()) { + return this.createTenantUser(); + } else { + return !results.isEmpty(); + } + } + + return false; + } + + private boolean createTenantUser() throws InvalidApplicationException { + TenantUserEntity user = new TenantUserEntity(); + user.setId(UUID.randomUUID()); + user.setCreatedAt(Instant.now()); + user.setUpdatedAt(Instant.now()); + user.setIsActive(IsActive.Active); + user.setTenantId(this.tenantScope.getTenant()); + user.setUserId(userScope.getUserId()); + + + + DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); + definition.setName(UUID.randomUUID().toString()); + definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); + definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); + TransactionStatus status = null; + try { + status = transactionManager.getTransaction(definition); + this.entityManager.persist(user); + this.entityManager.flush(); + transactionManager.commit(status); + } catch (Exception ex) { + if (status != null) transactionManager.rollback(status); + throw ex; + } + return true; + } + + @Override + public void postHandle(@NonNull WebRequest request, ModelMap model) { + this.tenantScope.setTenant(null, null); + } + + @Override + public void afterCompletion(@NonNull WebRequest request, Exception ex) { + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeClaimInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeClaimInterceptor.java new file mode 100644 index 000000000..c103ce2f9 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeClaimInterceptor.java @@ -0,0 +1,200 @@ +package eu.eudat.interceptors.tenant; + + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.scope.tenant.TenantScope; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.TenantEntity; +import eu.eudat.errorcode.ErrorThesaurusProperties; +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.commons.web.oidc.principal.MyPrincipal; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorContext; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import org.jetbrains.annotations.NotNull; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.ui.ModelMap; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.context.request.WebRequestInterceptor; + +import javax.management.InvalidApplicationException; +import java.util.List; +import java.util.UUID; + +@Component +public class TenantScopeClaimInterceptor implements WebRequestInterceptor { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantScopeClaimInterceptor.class)); + private final TenantScope tenantScope; + private final ConventionService conventionService; + private final TenantScopeProperties tenantScopeProperties; + private final ErrorThesaurusProperties errorThesaurusProperties; + private final ClaimExtractor claimExtractor; + private final CurrentPrincipalResolver currentPrincipalResolver; + private final String clientTenantClaimName; + private final ClaimExtractorContext claimExtractorContext; + private final TenantByCodeCacheService tenantByCodeCacheService; + private final TenantByIdCacheService tenantByIdCacheService; + @PersistenceContext + public EntityManager entityManager; + + @Autowired + public TenantScopeClaimInterceptor( + TenantScope tenantScope, + ConventionService conventionService, + ClaimExtractor claimExtractor, + CurrentPrincipalResolver currentPrincipalResolver, + ErrorThesaurusProperties errorThesaurusProperties, + TenantScopeProperties tenantScopeProperties, + ClaimExtractorContext claimExtractorContext, + TenantByCodeCacheService tenantByCodeCacheService, + TenantByIdCacheService tenantByIdCacheService + ) { + this.tenantScope = tenantScope; + this.conventionService = conventionService; + this.currentPrincipalResolver = currentPrincipalResolver; + this.claimExtractor = claimExtractor; + this.errorThesaurusProperties = errorThesaurusProperties; + this.tenantScopeProperties = tenantScopeProperties; + this.claimExtractorContext = claimExtractorContext; + this.tenantByCodeCacheService = tenantByCodeCacheService; + this.tenantByIdCacheService = tenantByIdCacheService; + this.clientTenantClaimName = this.tenantScopeProperties.getClientClaimsPrefix() + TenantScope.TenantClaimName; + } + + @Override + public void preHandle(@NotNull WebRequest request) throws InvalidApplicationException { + if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return; + if (!this.tenantScope.isMultitenant()) return; + + MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal(); + if (principal != null && principal.isAuthenticated() /* principal.Claims.Any() */) { + Boolean scoped = this.scopeByPrincipal(this.tenantScope, principal); + if (!scoped) scoped = this.scopeByClient(this.tenantScope, principal); + if (!scoped && this.tenantScope.isSet() && this.tenantScopeProperties.getEnforceTrustedTenant()) + throw new MyForbiddenException(this.errorThesaurusProperties.getMissingTenant().getCode(), this.errorThesaurusProperties.getMissingTenant().getMessage()); + } + } + + private Boolean scopeByPrincipal(TenantScope scope, MyPrincipal principal) { + String tenantCode = this.claimExtractor.tenantString(principal); + if (tenantCode == null || tenantCode.isBlank()) + tenantCode = this.claimExtractor.asString(principal, this.clientTenantClaimName); + + UUID tenantId = this.conventionService.parseUUIDSafe(tenantCode); + if (tenantId == null && tenantCode == null) + return Boolean.FALSE; + if (tenantId == null) { + TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode)); + if (cacheValue != null) { + tenantId = cacheValue.getTenantId(); + } else { + tenantId = this.getTenantIdFromDatabase(tenantCode); + this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId)); + this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId)); + } + } else { + logger.debug("tenant claim was set to {}", tenantId); + TenantByIdCacheService.TenantByIdCacheValue cacheValue = this.tenantByIdCacheService.lookup(this.tenantByIdCacheService.buildKey(tenantId)); + + if (cacheValue != null) { + tenantCode = cacheValue.getTenantCode(); + } else { + tenantCode = this.getTenantCodeFromDatabase(tenantId); + this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId)); + this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId)); + } + } + + if (tenantId != null && tenantCode != null && !tenantCode.isBlank()) { + logger.debug("parsed tenant header and set tenant id to {}", tenantId); + this.tenantScope.setTenant(tenantId, tenantCode); + this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode); + } + return tenantId != null; + } + + private Boolean scopeByClient(TenantScope scope, MyPrincipal principal) throws InvalidApplicationException { + String client = this.claimExtractor.client(principal); + + Boolean isWhiteListed = this.tenantScopeProperties.getWhiteListedClients() != null && !this.conventionService.isNullOrEmpty(client) && this.tenantScopeProperties.getWhiteListedClients().contains(client); + logger.debug("client is whitelisted : {}, scope is set: {}, with value {}", isWhiteListed, scope.isSet(), (scope.isSet() ? scope.getTenant() : null)); + + return isWhiteListed && scope.isSet(); + } + + private UUID getTenantIdFromDatabase(String tenantCode) { + CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(Tuple.class); + Root root = query.from(TenantEntity.class); + query = query.where( + criteriaBuilder.and( + criteriaBuilder.equal(root.get(TenantEntity._code), tenantCode), + criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active) + ) + ).multiselect(root.get(TenantEntity._id).alias(TenantEntity._id)); + List results = this.entityManager.createQuery(query).getResultList(); + if (results.size() == 1) { + Object o; + try { + o = results.getFirst().get(TenantEntity._id); + } catch (IllegalArgumentException e) { + return null; + } + if (o == null) return null; + try { + return (UUID) o; + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + private String getTenantCodeFromDatabase(UUID tenantId) { + CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(Tuple.class); + Root root = query.from(TenantEntity.class); + query = query.where( + criteriaBuilder.and( + criteriaBuilder.equal(root.get(TenantEntity._id), tenantId), + criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active) + ) + ).multiselect(root.get(TenantEntity._code).alias(TenantEntity._code)); + List results = this.entityManager.createQuery(query).getResultList(); + if (results.size() == 1) { + Object o; + try { + o = results.getFirst().get(TenantEntity._code); + } catch (IllegalArgumentException e) { + return null; + } + if (o == null) return null; + try { + return (String) o; + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + @Override + public void postHandle(@NonNull WebRequest request, ModelMap model) { + this.tenantScope.setTenant(null, null); + this.claimExtractorContext.removeReplaceParameter(TenantScope.TenantReplaceParameter); + } + + @Override + public void afterCompletion(@NonNull WebRequest request, Exception ex) { + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeConfiguration.java new file mode 100644 index 000000000..d928e3add --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeConfiguration.java @@ -0,0 +1,9 @@ +package eu.eudat.interceptors.tenant; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(TenantScopeProperties.class) +public class TenantScopeConfiguration { +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeHeaderInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeHeaderInterceptor.java new file mode 100644 index 000000000..26c201526 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeHeaderInterceptor.java @@ -0,0 +1,162 @@ +package eu.eudat.interceptors.tenant; + + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.scope.tenant.TenantScope; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.TenantEntity; +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorContext; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import org.jetbrains.annotations.NotNull; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.ui.ModelMap; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.context.request.WebRequestInterceptor; + +import java.util.List; +import java.util.UUID; + +@Component +public class TenantScopeHeaderInterceptor implements WebRequestInterceptor { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantScopeHeaderInterceptor.class)); + private final TenantScope tenantScope; + private final ConventionService conventionService; + private final TenantByCodeCacheService tenantByCodeCacheService; + private final TenantByIdCacheService tenantByIdCacheService; + private final ClaimExtractorContext claimExtractorContext; + private final CurrentPrincipalResolver currentPrincipalResolver; + @PersistenceContext + public EntityManager entityManager; + + @Autowired + public TenantScopeHeaderInterceptor( + TenantScope tenantScope, + ConventionService conventionService, + TenantByCodeCacheService tenantByCodeCacheService, + TenantByIdCacheService tenantByIdCacheService, + ClaimExtractorContext claimExtractorContext, + CurrentPrincipalResolver currentPrincipalResolver + ) { + this.tenantScope = tenantScope; + this.conventionService = conventionService; + this.tenantByCodeCacheService = tenantByCodeCacheService; + this.tenantByIdCacheService = tenantByIdCacheService; + this.claimExtractorContext = claimExtractorContext; + this.currentPrincipalResolver = currentPrincipalResolver; + } + + @Override + public void preHandle(@NotNull WebRequest request) { + if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return; + if (!this.tenantScope.isMultitenant()) return; + + String tenantCode = request.getHeader(TenantScope.TenantClaimName); + logger.debug("retrieved request tenant header is: {}", tenantCode); + if (this.conventionService.isNullOrEmpty(tenantCode)) return; + + UUID tenantId = this.conventionService.parseUUIDSafe(tenantCode); + if (tenantId == null && tenantCode == null) return; + if (tenantId == null) { + TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode)); + if (cacheValue != null) { + tenantId = cacheValue.getTenantId(); + } else { + tenantId = this.getTenantIdFromDatabase(tenantCode); + this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId)); + this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId)); + } + } else { + TenantByIdCacheService.TenantByIdCacheValue cacheValue = this.tenantByIdCacheService.lookup(this.tenantByIdCacheService.buildKey(tenantId)); + if (cacheValue != null) { + tenantCode = cacheValue.getTenantCode(); + } else { + tenantCode = this.getTenantCodeFromDatabase(tenantId); + this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId)); + this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId)); + } + } + + if (tenantId != null && tenantCode != null && !tenantCode.isBlank()) { + logger.debug("parsed tenant header and set tenant id to {}", tenantId); + this.tenantScope.setTenant(tenantId, tenantCode); + this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode); + } + } + + private UUID getTenantIdFromDatabase(String tenantCode) { + CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(Tuple.class); + Root root = query.from(TenantEntity.class); + query = query.where( + criteriaBuilder.and( + criteriaBuilder.equal(root.get(TenantEntity._code), tenantCode), + criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active) + ) + ).multiselect(root.get(TenantEntity._id).alias(TenantEntity._id)); + List results = this.entityManager.createQuery(query).getResultList(); + if (results.size() == 1) { + Object o; + try { + o = results.getFirst().get(TenantEntity._id); + } catch (IllegalArgumentException e) { + return null; + } + if (o == null) return null; + try { + return (UUID) o; + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + private String getTenantCodeFromDatabase(UUID tenantId) { + CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(Tuple.class); + Root root = query.from(TenantEntity.class); + query = query.where( + criteriaBuilder.and( + criteriaBuilder.equal(root.get(TenantEntity._id), tenantId), + criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active) + ) + ).multiselect(root.get(TenantEntity._code).alias(TenantEntity._code)); + List results = this.entityManager.createQuery(query).getResultList(); + if (results.size() == 1) { + Object o; + try { + o = results.getFirst().get(TenantEntity._code); + } catch (IllegalArgumentException e) { + return null; + } + if (o == null) return null; + try { + return (String) o; + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + @Override + public void postHandle(@NonNull WebRequest request, ModelMap model) { + + this.tenantScope.setTenant(null, null); + this.claimExtractorContext.removeReplaceParameter(TenantScope.TenantReplaceParameter); + } + + @Override + public void afterCompletion(@NonNull WebRequest request, Exception ex) { + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeProperties.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeProperties.java new file mode 100644 index 000000000..8d619d23d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/TenantScopeProperties.java @@ -0,0 +1,53 @@ +package eu.eudat.interceptors.tenant; + + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.HashSet; +import java.util.List; + +@ConfigurationProperties(prefix = "tenant.interceptor") +public class TenantScopeProperties { + + private String clientClaimsPrefix; + public String getClientClaimsPrefix() { + return clientClaimsPrefix; + } + public void setClientClaimsPrefix(String clientClaimsPrefix) { + this.clientClaimsPrefix = clientClaimsPrefix; + } + + private HashSet whiteListedClients; + public HashSet getWhiteListedClients() { + return whiteListedClients; + } + public void setWhiteListedClients(HashSet whiteListedClients) { + this.whiteListedClients = whiteListedClients; + } + + private List whiteListedEndpoints; + public List getWhiteListedEndpoints() { + return whiteListedEndpoints; + } + public void setWhiteListedEndpoints(List whiteListedEndpoints) { + this.whiteListedEndpoints = whiteListedEndpoints; + } + + private Boolean enforceTrustedTenant; + public Boolean getEnforceTrustedTenant() { + return enforceTrustedTenant; + } + public void setEnforceTrustedTenant(Boolean enforceTrustedTenant) { + this.enforceTrustedTenant = enforceTrustedTenant; + } + + private Boolean autoCreateTenantUser; + + public Boolean getAutoCreateTenantUser() { + return autoCreateTenantUser; + } + + public void setAutoCreateTenantUser(Boolean autoCreateTenantUser) { + this.autoCreateTenantUser = autoCreateTenantUser; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheOptions.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheOptions.java new file mode 100644 index 000000000..d5bd5d9ca --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheOptions.java @@ -0,0 +1,10 @@ +package eu.eudat.interceptors.tenant; + +import gr.cite.tools.cache.CacheOptions; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "cache.user-allowed-tenant") +public class UserAllowedTenantCacheOptions extends CacheOptions { +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheService.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheService.java new file mode 100644 index 000000000..7bcc92a69 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/tenant/UserAllowedTenantCacheService.java @@ -0,0 +1,90 @@ +package eu.eudat.interceptors.tenant; + +import eu.eudat.event.UserAddedToTenantEvent; +import eu.eudat.event.UserRemovedFromTenantEvent; +import gr.cite.tools.cache.CacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Locale; +import java.util.UUID; + +@Service +public class UserAllowedTenantCacheService extends CacheService { + + public static class UserAllowedTenantCacheValue { + + public UserAllowedTenantCacheValue() { + } + + public UserAllowedTenantCacheValue(UUID userId, UUID tenantId, boolean isAllowed) { + this.userId = userId; + this.tenantId = tenantId; + this.isAllowed = isAllowed; + } + + private UUID userId; + + public UUID getUserId() { + return userId; + } + + public void setUserId(UUID userId) { + this.userId = userId; + } + + private UUID tenantId; + + public UUID getTenantId() { + return tenantId; + } + + public void setTenantId(UUID tenantId) { + this.tenantId = tenantId; + } + + private boolean isAllowed; + + public boolean isAllowed() { + return isAllowed; + } + + public void setAllowed(boolean allowed) { + isAllowed = allowed; + } + } + + @Autowired + public UserAllowedTenantCacheService(UserAllowedTenantCacheOptions options) { + super(options); + } + + @EventListener + public void handleUserRemovedFromTenantEvent(UserRemovedFromTenantEvent event) { + this.evict(this.buildKey(event.getUserId(), event.getTenantId())); + } + + @EventListener + public void handleUserAddedToTenantEvent(UserAddedToTenantEvent event) { + this.evict(this.buildKey(event.getUserId(), event.getTenantId())); + } + + @Override + protected Class valueClass() { + return UserAllowedTenantCacheValue.class; + } + + @Override + public String keyOf(UserAllowedTenantCacheValue value) { + return this.buildKey(value.getUserId(), value.getTenantId()); + } + + public String buildKey(UUID userId, UUID tenantId) { + HashMap keyParts = new HashMap<>(); + keyParts.put("$user_id$", userId.toString().toLowerCase(Locale.ROOT)); + keyParts.put("$tenant_id$", tenantId.toString().toLowerCase(Locale.ROOT)); + return this.generateKey(keyParts); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptor.java similarity index 99% rename from dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java rename to dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptor.java index dd1696511..9445584d9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptor.java @@ -1,4 +1,4 @@ -package eu.eudat.interceptors; +package eu.eudat.interceptors.user; import eu.eudat.authorization.ClaimNames; diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheOptions.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptorCacheOptions.java similarity index 89% rename from dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheOptions.java rename to dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptorCacheOptions.java index 166b13af7..5d3e6bab7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheOptions.java +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptorCacheOptions.java @@ -1,4 +1,4 @@ -package eu.eudat.interceptors; +package eu.eudat.interceptors.user; import gr.cite.tools.cache.CacheOptions; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptorCacheService.java similarity index 96% rename from dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java rename to dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptorCacheService.java index f742041a8..679b57a6f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/user/UserInterceptorCacheService.java @@ -1,9 +1,8 @@ -package eu.eudat.interceptors; +package eu.eudat.interceptors.user; import eu.eudat.convention.ConventionService; import gr.cite.tools.cache.CacheService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import java.util.HashMap; diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/AccountBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/models/AccountBuilder.java index 90a7482da..884b1f484 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/AccountBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/AccountBuilder.java @@ -3,6 +3,7 @@ package eu.eudat.models; import eu.eudat.commons.JsonHandlingService; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.types.user.AdditionalInfoEntity; +import eu.eudat.data.TenantEntityManager; import eu.eudat.data.UserEntity; import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; @@ -11,7 +12,6 @@ import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorKeys; import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; -import jakarta.persistence.EntityManager; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -29,8 +29,8 @@ public class AccountBuilder { private final AuthorizationConfiguration authorizationConfiguration; private final JsonHandlingService jsonHandlingService; private final UserScope userScope; - private final EntityManager entityManager; - public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, AuthorizationConfiguration authorizationConfiguration, JsonHandlingService jsonHandlingService, UserScope userScope, EntityManager entityManager) { + private final TenantEntityManager entityManager; + public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, AuthorizationConfiguration authorizationConfiguration, JsonHandlingService jsonHandlingService, UserScope userScope, TenantEntityManager entityManager) { this.claimExtractor = claimExtractor; this.currentPrincipalResolver = currentPrincipalResolver; this.authorizationConfiguration = authorizationConfiguration; diff --git a/dmp-backend/web/src/main/resources/config/cache.yml b/dmp-backend/web/src/main/resources/config/cache.yml index bb670773b..050ca19de 100644 --- a/dmp-backend/web/src/main/resources/config/cache.yml +++ b/dmp-backend/web/src/main/resources/config/cache.yml @@ -50,10 +50,37 @@ cache: maximumSize: 500 enableRecordStats: false expireAfterWriteSeconds: 60 + - names: [ tenantByCode ] + allowNullValues: true + initialCapacity: 100 + maximumSize: 500 + enableRecordStats: false + expireAfterWriteSeconds: 30 + - names: [ tenantById ] + allowNullValues: true + initialCapacity: 100 + maximumSize: 500 + enableRecordStats: false + expireAfterWriteSeconds: 60 + - names: [ userAllowedTenant ] + allowNullValues: true + initialCapacity: 100 + maximumSize: 500 + enableRecordStats: false + expireAfterWriteSeconds: 60 mapCaches: userBySubjectId: name: userBySubjectId keyPattern: user_by_subject_$subject$:v0 + tenantByCode: + name: tenantByCode + keyPattern: tenant_by_code_$code$:v0 + tenantById: + name: tenantById + keyPattern: tenant_by_id_$tenantId$:v0 + userAllowedTenant: + name: userAllowedTenant + keyPattern: user_allowed_tenant$tenant_id$_$user_id$:v0 supportiveMaterial: name: supportiveMaterial keyPattern: supportive_material_$type$_$lang$:v0 diff --git a/dmp-backend/web/src/main/resources/config/idpclaims.yml b/dmp-backend/web/src/main/resources/config/idpclaims.yml index 97ff4a10e..94e843a48 100644 --- a/dmp-backend/web/src/main/resources/config/idpclaims.yml +++ b/dmp-backend/web/src/main/resources/config/idpclaims.yml @@ -20,11 +20,17 @@ idpclient: Roles: - type: resource_access path: dmp_web.roles + - type: tenant_roles + filterBy: "(.*):::TenantCode::" + extractByExpression: "(.*):(.*)" + extractExpressionValue: "[[g1]]" Scope: - type: scope AccessToken: - type: x-access-token visibility: SENSITIVE + Tenant: + - type: x-tenant IssuedAt: - type: iat Issuer: @@ -37,5 +43,8 @@ idpclient: - type: azp Authorities: - type: authorities - ExternalProviderName: - - type: identity_provider \ No newline at end of file + TenantCodes: + - type: tenant_roles + filterBy: "(.*):(.*)" + extractByExpression: "(.*):(.*)" + extractExpressionValue: "[[g2]]" \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/config/permissions.yml b/dmp-backend/web/src/main/resources/config/permissions.yml index b8b9d5f90..6b925144b 100644 --- a/dmp-backend/web/src/main/resources/config/permissions.yml +++ b/dmp-backend/web/src/main/resources/config/permissions.yml @@ -672,7 +672,7 @@ permissions: allowAuthenticated: false AllowNoTenant: roles: - - Admin + - TenantManager claims: [ ] clients: [ ] allowAnonymous: false diff --git a/dmp-backend/web/src/main/resources/config/tenant.yml b/dmp-backend/web/src/main/resources/config/tenant.yml index 8e2dbd774..df2f0017c 100644 --- a/dmp-backend/web/src/main/resources/config/tenant.yml +++ b/dmp-backend/web/src/main/resources/config/tenant.yml @@ -2,4 +2,10 @@ tenant: configEncryptionAesKey: rmpTvZnRWzyisUtFADBcZCn0q7Z75Xdz configEncryptionAesIv: ec05d521a23f80ad multitenancy: - is-multitenant: false \ No newline at end of file + is-multitenant: true + interceptor: + client-claims-prefix: client_ + white-listed-clients: [ ] + enforce-trusted-tenant: false + auto-create-tenant-user: true + white-listed-endpoints: [ '/api/principal/my-tenants', '/api/principal/me' ] \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/auth/auth.service.ts b/dmp-frontend/src/app/core/services/auth/auth.service.ts index fd6d59630..1b6f6d5c4 100644 --- a/dmp-frontend/src/app/core/services/auth/auth.service.ts +++ b/dmp-frontend/src/app/core/services/auth/auth.service.ts @@ -39,6 +39,7 @@ export class AuthService extends BaseService { private appAccount: AppAccount; private _authState: boolean; + private _selectedTenant: string; constructor( private installationConfiguration: ConfigurationService, private language: TranslateService, @@ -69,6 +70,21 @@ export class AuthService extends BaseService { }); } + public selectedTenant(selectedTenant?: string): string { + if (selectedTenant !== undefined) { + this._selectedTenant = selectedTenant; + if (selectedTenant == null) { + localStorage.removeItem('selectedTenant'); + } else { + localStorage.setItem('selectedTenant', selectedTenant); + } + } + if (this._selectedTenant === undefined) { + this._selectedTenant = localStorage.getItem('selectedTenant'); + } + return this._selectedTenant; + } + public getAuthenticationStateObservable(): Observable { return this.authenticationStateSubject.asObservable(); } @@ -83,6 +99,7 @@ export class AuthService extends BaseService { this.authState(false); this.accessToken = undefined; this.appAccount = undefined; + this.selectedTenant(null); } private authState(authState?: boolean): boolean { @@ -255,7 +272,7 @@ export class AuthService extends BaseService { }) .catch((error) => this.onAuthenticateError(error)); } else { - this.zone.run(() => this.router.navigate([returnUrl])); + this.zone.run(() => this.router.navigate(['/login/post'])); } }); } diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index 0d502a974..43863854a 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -113,7 +113,7 @@ export class ConfigurationService extends BaseComponent { get notificationServiceAddress(): string { return this._notificationServiceAddress || './'; } - + private _notificationServiceEnabled: boolean; get notificationServiceEnabled(): boolean { return this._notificationServiceEnabled; @@ -123,7 +123,7 @@ export class ConfigurationService extends BaseComponent { get annotationServiceAddress(): string { return this._annotationServiceAddress || './'; } - + private _annotationServiceEnabled: boolean; get annotationServiceEnabled(): boolean { return this._annotationServiceEnabled; @@ -161,6 +161,7 @@ export class ConfigurationService extends BaseComponent { params.interceptorContext = { excludedInterceptors: [ InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor, InterceptorType.JSONContentType, InterceptorType.Locale, InterceptorType.ProgressIndication, diff --git a/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts b/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts index 5a2b4b295..f70791cc5 100644 --- a/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts +++ b/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts @@ -37,7 +37,8 @@ export class DashboardService { const url = `${this.apiBase}/public/get-statistics`; const params = new BaseHttpParams(); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http.get(url, { params: params }).pipe(catchError((error: any) => throwError(error))); } diff --git a/dmp-frontend/src/app/core/services/description/description.service.ts b/dmp-frontend/src/app/core/services/description/description.service.ts index f45ae4bb7..4bcc22e32 100644 --- a/dmp-frontend/src/app/core/services/description/description.service.ts +++ b/dmp-frontend/src/app/core/services/description/description.service.ts @@ -41,7 +41,8 @@ export class DescriptionService { const url = `${this.apiBase}/public/query`; const params = new BaseHttpParams(); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http.post>(url, q, {params: params}).pipe(catchError((error: any) => throwError(error))); } diff --git a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts index b4a5d92ce..7fa2ef6e7 100644 --- a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts +++ b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts @@ -45,7 +45,8 @@ export class DmpService { const url = `${this.apiBase}/public/query`; const params = new BaseHttpParams(); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http.post>(url, q, {params: params}).pipe(catchError((error: any) => throwError(error))); } @@ -66,7 +67,8 @@ export class DmpService { let params: BaseHttpParams = new BaseHttpParams(options); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http diff --git a/dmp-frontend/src/app/core/services/http/principal.service.ts b/dmp-frontend/src/app/core/services/http/principal.service.ts index a33ac37f8..fb2d64c65 100644 --- a/dmp-frontend/src/app/core/services/http/principal.service.ts +++ b/dmp-frontend/src/app/core/services/http/principal.service.ts @@ -19,4 +19,9 @@ export class PrincipalService { const url = `${this.apiBase}/me`; return this.http.get(url, options); } + + public myTenants(options?: Object): Observable> { + const url = `${this.apiBase}/my-tenants`; + return this.http.get>(url, options); + } } diff --git a/dmp-frontend/src/app/core/services/language/language.http.service.ts b/dmp-frontend/src/app/core/services/language/language.http.service.ts index a34317331..3ed510d55 100644 --- a/dmp-frontend/src/app/core/services/language/language.http.service.ts +++ b/dmp-frontend/src/app/core/services/language/language.http.service.ts @@ -44,7 +44,8 @@ export class LanguageHttpService { let params: BaseHttpParams = new BaseHttpParams(options); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http @@ -56,7 +57,8 @@ export class LanguageHttpService { const url = `${this.apiBase}/public/available-languages`; const params = new BaseHttpParams(); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http.post>(url, q, { params: params }).pipe(catchError((error: any) => throwError(error))); } diff --git a/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts b/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts index ccdfd5301..217f1ef77 100644 --- a/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts +++ b/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts @@ -44,7 +44,8 @@ export class SupportiveMaterialService { const url = `${this.apiBase}/public/get-payload/${type}/${language}`; const params = new BaseHttpParams(); params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] + excludedInterceptors: [InterceptorType.AuthToken, + InterceptorType.TenantHeaderInterceptor] }; return this.http.get(url, { params: params, responseType: 'blob', observe: 'response' }); } diff --git a/dmp-frontend/src/app/ui/auth/login/login.component.ts b/dmp-frontend/src/app/ui/auth/login/login.component.ts index 9fe5e0c52..d87d863fb 100644 --- a/dmp-frontend/src/app/ui/auth/login/login.component.ts +++ b/dmp-frontend/src/app/ui/auth/login/login.component.ts @@ -1,7 +1,10 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, Input, NgZone, OnInit } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { AuthService } from '@app/core/services/auth/auth.service'; import { BaseComponent } from '@common/base/base.component'; +import { KeycloakService } from 'keycloak-angular'; +import { from } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-login', @@ -18,12 +21,33 @@ export class LoginComponent extends BaseComponent implements OnInit { //public cofigurableProviders: ConfigurableProvider[]; constructor( + private zone: NgZone, + private router: Router, private authService: AuthService, - private route: ActivatedRoute + private route: ActivatedRoute, + private keycloakService: KeycloakService ) { super(); } ngOnInit(): void { - this.returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/'; - this.authService.authenticate(this.returnUrl ? this.returnUrl : "/"); + this.returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/login/post'; + this.keycloakService.isLoggedIn().then(isLoggedIn => { + if (!isLoggedIn) { + this.authService.authenticate('/login/post'); + } else { + this.authService.prepareAuthRequest(from(this.keycloakService.getToken())).pipe(takeUntil(this._destroyed)).subscribe( + () => { + let returnUrL = this.returnUrl; + let queryParams: Params = {}; + if(!this.authService.selectedTenant()){ + returnUrL = '/login/post'; + queryParams.returnUrl = this.returnUrl; + } + this.zone.run(() => this.router.navigate([returnUrL],{queryParams} )); + }, + (error) => this.authService.authenticate('/login/post') ); + + } + + }); } } diff --git a/dmp-frontend/src/app/ui/auth/login/login.module.ts b/dmp-frontend/src/app/ui/auth/login/login.module.ts index 224ebb388..4cafdc86e 100644 --- a/dmp-frontend/src/app/ui/auth/login/login.module.ts +++ b/dmp-frontend/src/app/ui/auth/login/login.module.ts @@ -7,6 +7,7 @@ import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; import { MergeEmailConfirmation } from './merge-email-confirmation/merge-email-confirmation.component'; import { UnlinkEmailConfirmation } from './unlink-email-confirmation/unlink-email-confirmation.component'; +import { PostLoginComponent } from './post-login/post-login.component'; @NgModule({ imports: [ @@ -19,6 +20,7 @@ import { UnlinkEmailConfirmation } from './unlink-email-confirmation/unlink-emai LoginComponent, MergeEmailConfirmation, UnlinkEmailConfirmation, + PostLoginComponent ], exports: [ LoginComponent diff --git a/dmp-frontend/src/app/ui/auth/login/login.routing.ts b/dmp-frontend/src/app/ui/auth/login/login.routing.ts index 403d00cc1..7beaba215 100644 --- a/dmp-frontend/src/app/ui/auth/login/login.routing.ts +++ b/dmp-frontend/src/app/ui/auth/login/login.routing.ts @@ -4,14 +4,19 @@ import { LoginComponent } from './login.component'; import { MergeEmailConfirmation } from './merge-email-confirmation/merge-email-confirmation.component'; import { UnlinkEmailConfirmation } from './unlink-email-confirmation/unlink-email-confirmation.component'; import { AuthGuard } from '@app/core/auth-guard.service'; +import { PostLoginComponent } from './post-login/post-login.component'; const routes: Routes = [ { path: '', component: LoginComponent }, - { - path: 'merge/confirmation/:token', + { + path: 'merge/confirmation/:token', component: MergeEmailConfirmation, canActivate: [AuthGuard] }, + { + path: 'post', + component: PostLoginComponent + }, { path: 'unlink/confirmation/:token', component: UnlinkEmailConfirmation }, ]; diff --git a/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.html b/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.html new file mode 100644 index 000000000..d91ff3ad1 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.html @@ -0,0 +1,29 @@ +
+ + +

{{'APP.TENANT-CHOOSE-DIALOG.TITLE' | translate}}

+
+ +
+
+ + {{'APP.TENANT-CHOOSE-DIALOG.FIELDS.TENANT-CODE' | translate}} + + + {{tenant.code}} + + + {{formGroup.get('tenantCode').getError('backendError')?.message}} + {{'COMMONS.VALIDATION.REQUIRED' | translate}} + +
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.scss b/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.scss new file mode 100644 index 000000000..7d0c86080 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.scss @@ -0,0 +1,17 @@ +.tenant-choose-dialog { + padding-top: 1em; + + .editor-actions { + margin-top: 30px; + } + + .confirmation-message { + padding-bottom: 1rem; + font-size: 0.8rem; + } + + .display-flex { + display: flex; + font-size: 0.8rem !important; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.ts b/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.ts new file mode 100644 index 000000000..4a0a94b5c --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/post-login/post-login.component.ts @@ -0,0 +1,113 @@ +import { Component, OnInit } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Tenant } from '@app/core/model/tenant/tenant'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; +import { PrincipalService } from '@app/core/services/http/principal.service'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { BaseHttpParams } from '@common/http/base-http-params'; +import { InterceptorType } from '@common/http/interceptors/interceptor-type'; +import { KeycloakService } from 'keycloak-angular'; +import { from } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + templateUrl: './post-login.component.html', + styleUrls: ['./post-login.component.scss'], +}) +export class PostLoginComponent extends BaseComponent implements OnInit { + formGroup: UntypedFormGroup = null; + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + protected tenants: Partial[] = []; + protected selectedTenant = null; + + returnUrl: string; + + constructor( + private formService: FormService, + private route: ActivatedRoute, + private router: Router, + protected installationConfiguration: ConfigurationService, + private authService: AuthService, + private keycloakService: KeycloakService, + private principalService: PrincipalService + ) { + super(); + } + + ngOnInit(): void { + this.formGroup = this.formBuilder.group({ + tenantCode: ['', [Validators.required]] + }); + if (this.authService.hasAccessToken()) { + this.loadUserTenants(); + } else { + this.keycloakService.getToken().then(token => { + this.authService.currentAuthenticationToken(token); + this.loadUserTenants(); + }); + } + } + + loadUserTenants() { + const params = new BaseHttpParams(); + params.interceptorContext = { + excludedInterceptors: [InterceptorType.TenantHeaderInterceptor] + }; + if (this.authService.selectedTenant()) { + this.loadUser(); + return; + } + this.principalService.myTenants({ params: params }).subscribe(myTenants => { + if (myTenants) { + if (myTenants.length > 1) { + this.tenants = myTenants.map(function (code) { return { 'code': code }; }); + } else if (myTenants.length === 1) { + this.authService.selectedTenant(myTenants[0]); + this.loadUser(); + } else { + this.authService.selectedTenant(null); + //this.loadUser(); + } + } else { + this.authService.selectedTenant(null); + //this.loadUser(); + } + }); + } + + loadUser(): void { + const returnUrl = '/home'; + // const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/home'; + this.authService.prepareAuthRequest(from(this.keycloakService.getToken()), {}).pipe(takeUntil(this._destroyed)).subscribe(() => this.authService.onAuthenticateSuccess(returnUrl), (error) => this.authService.onAuthenticateError(error)); + } + + save(e: Event): void { + e.preventDefault(); + this.formSubmit(); + this.loadUser(); + } + + cancel(): void { + this.router.navigate(['/logout']); + } + + formSubmit(): void { + this.formService.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { return; } + + this.selectedTenant = this.formGroup.value['tenantCode']; + this.authService.selectedTenant(this.selectedTenant); + } + + public isFormValid(): Boolean { + return this.formGroup.valid; + } + + clearErrorModel() { + this.formService.validateAllFormFields(this.formGroup); + } +} diff --git a/dmp-frontend/src/app/ui/navbar/navbar.component.html b/dmp-frontend/src/app/ui/navbar/navbar.component.html index c1ff5224f..403d1363f 100644 --- a/dmp-frontend/src/app/ui/navbar/navbar.component.html +++ b/dmp-frontend/src/app/ui/navbar/navbar.component.html @@ -99,4 +99,4 @@
- \ No newline at end of file + diff --git a/dmp-frontend/src/common/http/common-http.module.ts b/dmp-frontend/src/common/http/common-http.module.ts index 35f48be43..d84f55f41 100644 --- a/dmp-frontend/src/common/http/common-http.module.ts +++ b/dmp-frontend/src/common/http/common-http.module.ts @@ -8,6 +8,7 @@ import { RequestTimingInterceptor } from './interceptors/request-timing.intercep import { ResponsePayloadInterceptor } from './interceptors/response-payload.interceptor'; import { UnauthorizedResponseInterceptor } from './interceptors/unauthorized-response.interceptor'; import { StatusCodeInterceptor } from './interceptors/status-code.interceptor'; +import { TenantHeaderInterceptor } from './interceptors/tenant-header.interceptor'; @NgModule({ imports: [ @@ -15,6 +16,11 @@ import { StatusCodeInterceptor } from './interceptors/status-code.interceptor'; declarations: [ ], providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: TenantHeaderInterceptor, + multi: true, + }, { provide: HTTP_INTERCEPTORS, useClass: AuthTokenInterceptor, diff --git a/dmp-frontend/src/common/http/interceptors/interceptor-type.ts b/dmp-frontend/src/common/http/interceptors/interceptor-type.ts index d0dcf9938..d4f3175e9 100644 --- a/dmp-frontend/src/common/http/interceptors/interceptor-type.ts +++ b/dmp-frontend/src/common/http/interceptors/interceptor-type.ts @@ -6,5 +6,6 @@ export enum InterceptorType { RequestTiming = 4, UnauthorizedResponse = 5, ResponsePayload = 5, - StatusCode = 6 + StatusCode = 6, + TenantHeaderInterceptor = 7 } diff --git a/dmp-frontend/src/common/http/interceptors/status-code.interceptor.ts b/dmp-frontend/src/common/http/interceptors/status-code.interceptor.ts index 03ea053e2..d83bb4a4f 100644 --- a/dmp-frontend/src/common/http/interceptors/status-code.interceptor.ts +++ b/dmp-frontend/src/common/http/interceptors/status-code.interceptor.ts @@ -7,6 +7,8 @@ import { HttpHandler, HttpRequest, HttpEvent } from "@angular/common/http"; import { Observable } from "rxjs"; import { Router } from "@angular/router"; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; +import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { AuthService } from '@app/core/services/auth/auth.service'; @Injectable() export class StatusCodeInterceptor extends BaseInterceptor { @@ -17,11 +19,18 @@ export class StatusCodeInterceptor extends BaseInterceptor { if (err.status === 480) { this.router.navigate(['confirmation']); } + const error: HttpError = this.httpErrorHandlingService.getError(err); + if (error.statusCode === 403 && error.errorCode === 103) { + this.authService.selectedTenant(null); + this.router.navigate(['/login/post']); + } })); } constructor( private router: Router, + private httpErrorHandlingService: HttpErrorHandlingService, + private authService: AuthService, configurationService: ConfigurationService ) { super(configurationService); } } diff --git a/dmp-frontend/src/common/http/interceptors/tenant-header.interceptor.ts b/dmp-frontend/src/common/http/interceptors/tenant-header.interceptor.ts new file mode 100644 index 000000000..abf04486f --- /dev/null +++ b/dmp-frontend/src/common/http/interceptors/tenant-header.interceptor.ts @@ -0,0 +1,27 @@ +import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; +import { BaseInterceptor } from '@common/http/interceptors/base.interceptor'; +import { InterceptorType } from '@common/http/interceptors/interceptor-type'; +import { Observable } from 'rxjs'; + +@Injectable() +export class TenantHeaderInterceptor extends BaseInterceptor { + + constructor( + public installationConfiguration: ConfigurationService, + private authService: AuthService) { super(installationConfiguration); } + + get type(): InterceptorType { return InterceptorType.TenantHeaderInterceptor; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable> { + const selectedTenant: string = this.authService.selectedTenant(); + if (!selectedTenant) { return next.handle(req); } + + req = req.clone({ + headers: req.headers.set('x-tenant', selectedTenant) + }); + return next.handle(req); + } +} diff --git a/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts b/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts index 754a6a8c9..f8c7fafa5 100644 --- a/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts +++ b/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts @@ -13,6 +13,9 @@ export class HttpErrorHandlingService { const error: HttpError = new HttpError(); error.statusCode = errorResponse.status; error.messages = this.parseMessages(error.statusCode, errorResponse); + try { + error.errorCode = + errorResponse.error.code; + } catch {} // if (error && error.error && error.error.error) { // errorMsg = error.error.error; @@ -60,6 +63,7 @@ export class HttpErrorHandlingService { export class HttpError { statusCode: number; messages: string[]; + errorCode: number; getMessagesString(): string { return this.messages ? this.messages.join(', ') : null;