diff --git a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/WebConfiguration.java b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/WebConfiguration.java index 775e62087..775930c70 100644 --- a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/WebConfiguration.java +++ b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/WebConfiguration.java @@ -1,9 +1,9 @@ package gr.cite.annotation.web; -import gr.cite.annotation.web.interceptors.UserInterceptor; import gr.cite.annotation.web.scope.tenant.TenantInterceptor; import gr.cite.annotation.web.scope.tenant.TenantScopeClaimInterceptor; import gr.cite.annotation.web.scope.tenant.TenantScopeHeaderInterceptor; +import gr.cite.annotation.web.scope.user.UserInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; diff --git a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/config/SecurityConfiguration.java b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/config/SecurityConfiguration.java index 761b144ca..a52e25875 100644 --- a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/config/SecurityConfiguration.java +++ b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/config/SecurityConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -104,7 +105,7 @@ public class SecurityConfiguration { //In the example below, the default client handler will be ignored by the resolver @Override public List>> disableHandlers() { - return List.of(PermissionClientAuthorizationHandler.class); + return new ArrayList<>(); } }; } diff --git a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/controllers/error/GenericErrorHandler.java b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/controllers/error/GenericErrorHandler.java deleted file mode 100644 index 1a7ebfc3a..000000000 --- a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/controllers/error/GenericErrorHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -//package gr.cite.intelcomp.stiviewer.web.controllers.error; -// -//import gr.cite.tools.exception.MyValidationException; -//import org.springframework.http.HttpStatus; -//import org.springframework.http.ResponseEntity; -//import org.springframework.web.bind.annotation.ControllerAdvice; -//import org.springframework.web.bind.annotation.ExceptionHandler; -//import org.springframework.web.context.request.WebRequest; -// -//@ControllerAdvice -//public class GenericErrorHandler { -// -// @ExceptionHandler(MyValidationException.class) -// public ResponseEntity handleValidationException(MyValidationException e, WebRequest webRequest) { -// return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(e); -// } -//} diff --git a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptor.java b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptor.java deleted file mode 100644 index 33b21485a..000000000 --- a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptor.java +++ /dev/null @@ -1,92 +0,0 @@ -package gr.cite.annotation.web.interceptors; - -import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; -import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; -import gr.cite.annotation.common.JsonHandlingService; -import gr.cite.annotation.common.lock.LockByKeyManager; -import gr.cite.annotation.common.scope.user.UserScope; -import gr.cite.annotation.data.UserCredentialEntity; -import gr.cite.annotation.model.UserCredential; -import gr.cite.annotation.query.UserCredentialQuery; -import gr.cite.tools.data.query.QueryFactory; -import gr.cite.tools.exception.MyForbiddenException; -import gr.cite.tools.fieldset.BaseFieldSet; -import gr.cite.tools.logging.LoggerService; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.lang.NonNull; -import org.springframework.stereotype.Component; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.ui.ModelMap; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.context.request.WebRequestInterceptor; - -import java.util.UUID; - -@Component -public class UserInterceptor implements WebRequestInterceptor { - private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserInterceptor.class)); - private final UserScope userScope; - private final ClaimExtractor claimExtractor; - private final CurrentPrincipalResolver currentPrincipalResolver; - private final UserInterceptorCacheService userInterceptorCacheService; - private final QueryFactory queryFactory; - @PersistenceContext - public EntityManager entityManager; - - @Autowired - public UserInterceptor( - UserScope userScope, - ClaimExtractor claimExtractor, - CurrentPrincipalResolver currentPrincipalResolver, - UserInterceptorCacheService userInterceptorCacheService, - QueryFactory queryFactory) { - this.userScope = userScope; - this.currentPrincipalResolver = currentPrincipalResolver; - this.claimExtractor = claimExtractor; - this.userInterceptorCacheService = userInterceptorCacheService; - this.queryFactory = queryFactory; - } - - @Override - public void preHandle(WebRequest request) { - UUID userId = null; - if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) { - String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal()); - if (subjectId == null || subjectId.isBlank()) throw new MyForbiddenException("Empty subjects not allowed"); - - UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId)); - if (cacheValue != null) { - userId = cacheValue.getUserId(); - } else { - userId = this.findExistingUserFromDbForce(subjectId); - - cacheValue = new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId); - - this.userInterceptorCacheService.put(cacheValue); - } - } - this.userScope.setUserId(userId); - } - - private UUID findExistingUserFromDbForce(String subjectId){ - UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).externalIds(subjectId).firstAs(new BaseFieldSet().ensure(UserCredential._user)); - if (userCredential != null) { - return userCredential.getUserId(); - } else { - throw new MyForbiddenException("User not created try again."); - } - } - - @Override - public void postHandle(@NonNull WebRequest request, ModelMap model) { - this.userScope.setUserId(null); - } - - @Override - public void afterCompletion(@NonNull WebRequest request, Exception ex) { - } -} - diff --git a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptorCacheOptions.java b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptorCacheOptions.java deleted file mode 100644 index 30c08781e..000000000 --- a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptorCacheOptions.java +++ /dev/null @@ -1,10 +0,0 @@ -package gr.cite.annotation.web.interceptors; - -import gr.cite.tools.cache.CacheOptions; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "cache.user-by-subject-id") -public class UserInterceptorCacheOptions extends CacheOptions { -} diff --git a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptorCacheService.java b/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptorCacheService.java deleted file mode 100644 index af5012905..000000000 --- a/annotation-service/annotation-web/src/main/java/gr/cite/annotation/web/interceptors/UserInterceptorCacheService.java +++ /dev/null @@ -1,66 +0,0 @@ -package gr.cite.annotation.web.interceptors; - -import gr.cite.tools.cache.CacheService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.UUID; - -@Service -public class UserInterceptorCacheService extends CacheService { - - public static class UserInterceptorCacheValue { - - public UserInterceptorCacheValue() { - } - - public UserInterceptorCacheValue(String subjectId, UUID userId) { - this.subjectId = subjectId; - this.userId = userId; - } - - private String subjectId; - - public String getSubjectId() { - return subjectId; - } - - public void setSubjectId(String subjectId) { - this.subjectId = subjectId; - } - - private UUID userId; - public UUID getUserId() { - return userId; - } - - public void setUserId(UUID userId) { - this.userId = userId; - } - - } - - - @Autowired - public UserInterceptorCacheService(UserInterceptorCacheOptions options) { - super(options); - } - - @Override - protected Class valueClass() { - return UserInterceptorCacheValue.class; - } - - @Override - public String keyOf(UserInterceptorCacheValue value) { - return this.buildKey(value.getSubjectId()); - } - - - public String buildKey(String subject) { - HashMap keyParts = new HashMap<>(); - keyParts.put("$subject$", subject); - return this.generateKey(keyParts); - } -} diff --git a/annotation-service/annotation-web/src/main/resources/config/idpclaims.yml b/annotation-service/annotation-web/src/main/resources/config/idpclaims.yml index 97ff4a10e..26e00f2a1 100644 --- a/annotation-service/annotation-web/src/main/resources/config/idpclaims.yml +++ b/annotation-service/annotation-web/src/main/resources/config/idpclaims.yml @@ -20,11 +20,25 @@ idpclient: Roles: - type: resource_access path: dmp_web.roles + - type: tenant_roles + filterBy: "(.*):::TenantCode::" + extractByExpression: "(.*):(.*)" + extractExpressionValue: "[[g1]]" + GlobalRoles: + - type: resource_access + path: dmp_web.roles + TenantRoles: + - 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 +51,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/annotation-service/annotation-web/src/main/resources/config/permissions.yml b/annotation-service/annotation-web/src/main/resources/config/permissions.yml index 89c8bb4c4..e9afba04c 100644 --- a/annotation-service/annotation-web/src/main/resources/config/permissions.yml +++ b/annotation-service/annotation-web/src/main/resources/config/permissions.yml @@ -2,10 +2,10 @@ permissions: policies: DeferredAffiliation: roles: - - Admin - - User - - Manager - - DescriptionTemplateEditor + - TenantAdmin + - TenantUser + - TenantManager + - TenantDescriptionTemplateEditor clients: [ ] allowAnonymous: false allowAuthenticated: false @@ -19,14 +19,14 @@ permissions: EditTenant: roles: - Admin - clients: [ ] + clients: [ "opendmp-api-dev" ] allowAnonymous: false allowAuthenticated: false DeleteTenant: roles: - Admin claims: [ ] - clients: [ ] + clients: [ "opendmp-api-dev" ] allowAnonymous: false allowAuthenticated: false AllowNoTenant: @@ -39,47 +39,47 @@ permissions: # Users BrowseUser: roles: - - Admin + - TenantAdmin clients: [ ] allowAnonymous: true allowAuthenticated: false EditUser: roles: - - Admin - clients: [ ] + - TenantAdmin + clients: [ "opendmp-api-dev" ] allowAnonymous: false allowAuthenticated: false DeleteUser: roles: - - Admin + - TenantAdmin claims: [ ] - clients: [ ] + clients: [ "opendmp-api-dev" ] allowAnonymous: false allowAuthenticated: false #Annotation BrowseAnnotation: roles: - - Admin + - TenantAdmin entityAffiliated: true clients: [ ] allowAnonymous: true allowAuthenticated: false NewAnnotation: roles: - - Admin + - TenantAdmin entityAffiliated: true clients: [ ] allowAnonymous: true allowAuthenticated: false EditAnnotation: roles: - - Admin + - TenantAdmin clients: [ ] allowAnonymous: true allowAuthenticated: false DeleteAnnotation: roles: - - Admin + - TenantAdmin entityAffiliated: false clients: [ ] allowAnonymous: false @@ -87,13 +87,13 @@ permissions: #Tenant Configuration BrowseTenantConfiguration: roles: - - Admin + - TenantAdmin clients: [ ] allowAnonymous: false allowAuthenticated: false EditTenantConfiguration: roles: - - Admin + - TenantAdmin clients: [ ] allowAnonymous: false allowAuthenticated: false \ No newline at end of file diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/data/TenantEntityManager.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/data/TenantEntityManager.java index 6ff264787..31f73207c 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/data/TenantEntityManager.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/data/TenantEntityManager.java @@ -82,6 +82,7 @@ public class TenantEntityManager { } public void enableTenantFilters() throws InvalidApplicationException { + if (!tenantScope.isSet()) return; if(!tenantScope.isDefaultTenant()) { this.entityManager .unwrap(Session.class) diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/OutboxIntegrationEventConfigurer.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/OutboxIntegrationEventConfigurer.java index 8a5eca059..52602ad8f 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/OutboxIntegrationEventConfigurer.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/OutboxIntegrationEventConfigurer.java @@ -1,5 +1,6 @@ package gr.cite.annotation.integrationevent; +import gr.cite.annotation.data.QueueOutboxEntity; import gr.cite.annotation.integrationevent.outbox.OutboxProperties; import gr.cite.annotation.integrationevent.outbox.OutboxRepositoryImpl; import gr.cite.queueoutbox.IntegrationEventContextCreator; @@ -56,7 +57,11 @@ public class OutboxIntegrationEventConfigurer extends OutboxConfigurer { @Bean public IntegrationEventContextCreator integrationEventContextCreator() { - return (message) -> new IntegrationEventContextImpl(); + return (message) -> { + IntegrationEventContextImpl integrationEventContext = new IntegrationEventContextImpl(); + if (message instanceof QueueOutboxEntity) integrationEventContext.setTenant(((QueueOutboxEntity)message).getTenantId()); + return integrationEventContext; + }; } @Bean diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxPrincipal.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxPrincipal.java index c94019a04..fa10849f8 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxPrincipal.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxPrincipal.java @@ -1,11 +1,13 @@ package gr.cite.annotation.integrationevent.inbox; import gr.cite.commons.web.oidc.principal.MyPrincipal; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import org.springframework.security.oauth2.core.ClaimAccessor; import org.springframework.security.oauth2.jwt.JwtClaimNames; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,12 +24,15 @@ public class InboxPrincipal implements MyPrincipal, ClaimAccessor { this.isAuthenticated = isAuthenticated; } - public static InboxPrincipal build(IntegrationEventProperties properties) { + public static InboxPrincipal build(IntegrationEventProperties properties, ClaimExtractorProperties claimExtractorProperties) { InboxPrincipal inboxPrincipal = new InboxPrincipal(true, "IntegrationEventQueueAppId"); - inboxPrincipal.put("client_id", properties.getAppId()); + List clientKey = claimExtractorProperties.getMapping().getOrDefault("Client", null); + inboxPrincipal.put(clientKey != null && clientKey.getFirst() != null ? clientKey.getFirst().getType() : "client_id", properties.getAppId()); inboxPrincipal.put("active", "true"); - inboxPrincipal.put("nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString()); - inboxPrincipal.put("exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString()); + List notBeforeKey = claimExtractorProperties.getMapping().getOrDefault("NotBefore", null); + inboxPrincipal.put(notBeforeKey != null && notBeforeKey.getFirst() != null ? notBeforeKey.getFirst().getType() :"nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString()); + List expiresAt = claimExtractorProperties.getMapping().getOrDefault("ExpiresAt", null); + inboxPrincipal.put(expiresAt != null && expiresAt.getFirst() != null ? expiresAt.getFirst().getType() :"exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString()); return inboxPrincipal; } @@ -45,7 +50,10 @@ public class InboxPrincipal implements MyPrincipal, ClaimAccessor { public List getClaimAsStringList(String claim) { if (claims == null) return null; - return this.getClaimAsStringList(claim); + if (this.claims.containsKey(claim)){ + return List.of(this.claims.get(claim).toString()); + } + return null; } @Override diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxRepositoryImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxRepositoryImpl.java index ccfda4f8c..2a06b0eb6 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxRepositoryImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/InboxRepositoryImpl.java @@ -245,6 +245,12 @@ public class InboxRepositoryImpl implements InboxRepository { queueMessage.setId(UUID.randomUUID()); Object tenantId = inboxCreatorParams.getHeaders() != null ? inboxCreatorParams.getHeaders().getOrDefault(IntegrationEventMessageConstants.TENANT, null) : null; if (tenantId instanceof UUID) queueMessage.setTenantId((UUID) tenantId); + else if (tenantId instanceof String) { + try { + queueMessage.setTenantId(UUID.fromString((String) tenantId)); + } catch (Exception e) { + } + } queueMessage.setExchange(this.inboxProperties.getExchange()); queueMessage.setRoute(inboxCreatorParams.getRoutingKey()); queueMessage.setQueue(inboxCreatorParams.getQueueName()); diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiesremoval/AnnotationEntitiesRemovalIntegrationEventHandlerImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiesremoval/AnnotationEntitiesRemovalIntegrationEventHandlerImpl.java index 612dc8098..2629f5134 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiesremoval/AnnotationEntitiesRemovalIntegrationEventHandlerImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiesremoval/AnnotationEntitiesRemovalIntegrationEventHandlerImpl.java @@ -15,6 +15,7 @@ import gr.cite.annotation.model.Tenant; import gr.cite.annotation.query.EntityUserQuery; import gr.cite.annotation.query.TenantQuery; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; @@ -83,7 +84,9 @@ public class AnnotationEntitiesRemovalIntegrationEventHandlerImpl implements Ann } CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); - currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + ClaimExtractorProperties claimExtractorProperties = this.applicationContext.getBean(ClaimExtractorProperties.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); entityManager = entityManagerFactory.createEntityManager(); diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiestouch/AnnotationEntitiesTouchedIntegrationEventHandlerImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiestouch/AnnotationEntitiesTouchedIntegrationEventHandlerImpl.java index 191942bef..c96b4273c 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiestouch/AnnotationEntitiesTouchedIntegrationEventHandlerImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/annotationentitiestouch/AnnotationEntitiesTouchedIntegrationEventHandlerImpl.java @@ -15,6 +15,7 @@ import gr.cite.annotation.model.Tenant; import gr.cite.annotation.query.EntityUserQuery; import gr.cite.annotation.query.TenantQuery; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; @@ -85,7 +86,9 @@ public class AnnotationEntitiesTouchedIntegrationEventHandlerImpl implements Ann } CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); - currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + ClaimExtractorProperties claimExtractorProperties = this.applicationContext.getBean(ClaimExtractorProperties.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); entityManager = entityManagerFactory.createEntityManager(); @@ -114,6 +117,7 @@ public class AnnotationEntitiesTouchedIntegrationEventHandlerImpl implements Ann data.setId(UUID.randomUUID()); data.setEntityId(entityEvent.getEntityId()); data.setUserId(user); + data.setTenantId(properties.getTenantId()); data.setCreatedAt(Instant.now()); data.setUpdatedAt(Instant.now()); data.setIsActive(IsActive.Active); diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java index 3b7921a37..86a264349 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java @@ -10,6 +10,7 @@ import gr.cite.annotation.integrationevent.inbox.EventProcessingStatus; import gr.cite.annotation.integrationevent.inbox.InboxPrincipal; import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties; import gr.cite.annotation.service.tenant.TenantService; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.logging.LoggerService; import jakarta.persistence.EntityManager; @@ -53,7 +54,9 @@ public class TenantRemovalIntegrationEventHandlerImpl implements TenantRemovalIn try (FakeRequestScope ignored = new FakeRequestScope()) { try { CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); - currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + ClaimExtractorProperties claimExtractorProperties = this.applicationContext.getBean(ClaimExtractorProperties.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); TenantRemovalConsistencyHandler tenantRemovalConsistencyHandler = this.applicationContext.getBean(TenantRemovalConsistencyHandler.class); if (!(tenantRemovalConsistencyHandler.isConsistent(new TenantRemovalConsistencyPredicates(event.getId())))) diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenanttouch/TenantTouchedIntegrationEventHandlerImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenanttouch/TenantTouchedIntegrationEventHandlerImpl.java index 4c03dcdd0..373758c7c 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenanttouch/TenantTouchedIntegrationEventHandlerImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/tenanttouch/TenantTouchedIntegrationEventHandlerImpl.java @@ -10,6 +10,8 @@ import gr.cite.annotation.integrationevent.inbox.InboxPrincipal; import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties; import gr.cite.annotation.model.persist.TenantTouchedIntegrationEventPersist; import gr.cite.annotation.service.tenant.TenantService; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.validation.ValidatorFactory; @@ -59,7 +61,8 @@ public class TenantTouchedIntegrationEventHandlerImpl implements TenantTouchedIn try (FakeRequestScope ignored = new FakeRequestScope()) { try { CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); - currentPrincipalResolver.push(InboxPrincipal.build(properties)); + ClaimExtractorProperties claimExtractorProperties = this.applicationContext.getBean(ClaimExtractorProperties.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); entityManager = entityManagerFactory.createEntityManager(); diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java index cef55829a..08527936d 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java @@ -14,6 +14,7 @@ import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties; import gr.cite.annotation.model.Tenant; import gr.cite.annotation.query.TenantQuery; import gr.cite.annotation.service.user.UserService; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyValidationException; @@ -89,7 +90,9 @@ public class UserRemovalIntegrationEventHandlerImpl implements UserRemovalIntegr } CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); - currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + ClaimExtractorProperties claimExtractorProperties = this.applicationContext.getBean(ClaimExtractorProperties.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); UserRemovalConsistencyHandler userRemovalConsistencyHandler = this.applicationContext.getBean(UserRemovalConsistencyHandler.class); if (!(userRemovalConsistencyHandler.isConsistent(new UserRemovalConsistencyPredicates(event.getUserId())))) diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/usertouch/UserTouchedIntegrationEventHandlerImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/usertouch/UserTouchedIntegrationEventHandlerImpl.java index 0bb00b430..0962369d0 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/usertouch/UserTouchedIntegrationEventHandlerImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/integrationevent/inbox/usertouch/UserTouchedIntegrationEventHandlerImpl.java @@ -13,6 +13,7 @@ import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties; import gr.cite.annotation.model.Tenant; import gr.cite.annotation.query.TenantQuery; import gr.cite.annotation.service.user.UserService; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.fieldset.BaseFieldSet; @@ -82,7 +83,9 @@ public class UserTouchedIntegrationEventHandlerImpl implements UserTouchedIntegr } CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); - currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + ClaimExtractorProperties claimExtractorProperties = this.applicationContext.getBean(ClaimExtractorProperties.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); entityManager = entityManagerFactory.createEntityManager(); diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/service/tenant/TenantServiceImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/service/tenant/TenantServiceImpl.java index b9f1a37d3..8ee773d2c 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/service/tenant/TenantServiceImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/service/tenant/TenantServiceImpl.java @@ -75,6 +75,7 @@ public class TenantServiceImpl implements TenantService { data.setCode(model.getCode()); data.setIsActive(IsActive.Active); data.setCreatedAt(Instant.now()); + data.setUpdatedAt(Instant.now()); this.entityManager.persist(data); } else { diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/service/user/UserServiceImpl.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/service/user/UserServiceImpl.java index 684e7ba7e..b6bdb0a61 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/service/user/UserServiceImpl.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/service/user/UserServiceImpl.java @@ -5,15 +5,19 @@ import gr.cite.annotation.authorization.AuthorizationFlags; import gr.cite.annotation.authorization.Permission; import gr.cite.annotation.common.JsonHandlingService; import gr.cite.annotation.common.enums.IsActive; +import gr.cite.annotation.common.scope.tenant.TenantScope; import gr.cite.annotation.convention.ConventionService; import gr.cite.annotation.data.*; import gr.cite.annotation.integrationevent.inbox.usertouch.UserTouchedIntegrationEvent; +import gr.cite.annotation.model.Annotation; +import gr.cite.annotation.model.Tenant; import gr.cite.annotation.model.User; import gr.cite.annotation.model.builder.UserBuilder; import gr.cite.annotation.model.deleter.TenantUserDeleter; import gr.cite.annotation.model.deleter.UserContactInfoDeleter; import gr.cite.annotation.model.deleter.UserCredentialDeleter; import gr.cite.annotation.model.deleter.UserDeleter; +import gr.cite.annotation.query.TenantQuery; import gr.cite.annotation.query.TenantUserQuery; import gr.cite.annotation.query.UserContactInfoQuery; import gr.cite.annotation.query.UserCredentialQuery; @@ -31,6 +35,8 @@ import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import jakarta.transaction.Transactional; import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Service; import javax.management.InvalidApplicationException; @@ -57,6 +63,9 @@ public class UserServiceImpl implements UserService { private final BuilderFactory builderFactory; private final QueryFactory queryFactory; + private final TenantScope tenantScope; + + private final MessageSource messageSource; private final JsonHandlingService jsonHandlingService; @@ -65,7 +74,7 @@ public class UserServiceImpl implements UserService { DeleterFactory deleterFactory, ConventionService conventionService, TenantEntityManager entityManager, - BuilderFactory builderFactory, QueryFactory queryFactory, + BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, JsonHandlingService jsonHandlingService) { this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -73,6 +82,8 @@ public class UserServiceImpl implements UserService { this.entityManager = entityManager; this.builderFactory = builderFactory; this.queryFactory = queryFactory; + this.tenantScope = tenantScope; + this.messageSource = messageSource; this.jsonHandlingService = jsonHandlingService; } @@ -197,19 +208,31 @@ public class UserServiceImpl implements UserService { .userIds(userId) .isActive(IsActive.Active) .collect(); + List updatedCreatedIds = new ArrayList<>(); if (models != null) { + List tenantEntities = this.queryFactory.query(TenantQuery.class) + .ids(models.stream().map(UserTouchedIntegrationEvent.TenantUser::getTenant).toList()) + .isActive(IsActive.Active) + .collectAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code)); for (UserTouchedIntegrationEvent.TenantUser model : models) { TenantUserEntity data = items.stream().filter(x -> x.getTenantId().equals(model.getTenant())).findFirst().orElse(null); if (data == null) { - data = new TenantUserEntity(); - data.setId(UUID.randomUUID()); - data.setUserId(userId); - data.setTenantId(model.getTenant()); - data.setCreatedAt(Instant.now()); - data.setUpdatedAt(Instant.now()); - data.setIsActive(IsActive.Active); - entityManager.persist(data); + try { + TenantEntity tenant = tenantEntities.stream().filter(x -> x.getId().equals(model.getTenant())).findFirst().orElse(null); + if (tenant == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getTenant(), Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale())); + this.tenantScope.setTempTenant(this.entityManager.getEntityManager(), tenant.getId(), tenant.getCode()); + data = new TenantUserEntity(); + data.setId(UUID.randomUUID()); + data.setUserId(userId); + data.setTenantId(model.getTenant()); + data.setCreatedAt(Instant.now()); + data.setUpdatedAt(Instant.now()); + data.setIsActive(IsActive.Active); + entityManager.persist(data); + } finally { + this.tenantScope.removeTempTenant(this.entityManager.getEntityManager()); + } } updatedCreatedIds.add(data.getId()); } 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 cd9435b72..c8897881d 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 @@ -87,6 +87,7 @@ public class TenantEntityManager { } public void enableTenantFilters() throws InvalidApplicationException { + if (!tenantScope.isSet()) return; if(!tenantScope.isDefaultTenant()) { this.entityManager .unwrap(Session.class) diff --git a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/OutboxIntegrationEventConfigurer.java b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/OutboxIntegrationEventConfigurer.java index db9278357..42a365559 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/OutboxIntegrationEventConfigurer.java +++ b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/OutboxIntegrationEventConfigurer.java @@ -1,6 +1,7 @@ package eu.eudat.integrationevent; +import eu.eudat.data.QueueOutboxEntity; import eu.eudat.integrationevent.outbox.OutboxProperties; import eu.eudat.integrationevent.outbox.OutboxRepositoryImpl; import gr.cite.queueoutbox.IntegrationEventContextCreator; @@ -57,7 +58,11 @@ public class OutboxIntegrationEventConfigurer extends OutboxConfigurer { @Bean public IntegrationEventContextCreator integrationEventContextCreator() { - return (message) -> new IntegrationEventContextImpl(); + return (message) -> { + IntegrationEventContextImpl integrationEventContext = new IntegrationEventContextImpl(); + if (message instanceof QueueOutboxEntity) integrationEventContext.setTenant(((QueueOutboxEntity)message).getTenantId()); + return integrationEventContext; + }; } @Bean diff --git a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/inbox/InboxPrincipal.java b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/inbox/InboxPrincipal.java index 825fe6d64..3a590e3f1 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/inbox/InboxPrincipal.java +++ b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/inbox/InboxPrincipal.java @@ -1,6 +1,7 @@ package eu.eudat.integrationevent.inbox; import gr.cite.commons.web.oidc.principal.MyPrincipal; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; import org.springframework.security.oauth2.core.ClaimAccessor; import org.springframework.security.oauth2.jwt.JwtClaimNames; @@ -11,8 +12,9 @@ import java.util.List; import java.util.Map; public class InboxPrincipal implements MyPrincipal, ClaimAccessor { - private Map claims; - private boolean isAuthenticated; + private final Map claims; + + private final boolean isAuthenticated; public InboxPrincipal(Boolean isAuthenticated, String name) { this.claims = new HashMap<>(); @@ -20,6 +22,18 @@ public class InboxPrincipal implements MyPrincipal, ClaimAccessor { this.isAuthenticated = isAuthenticated; } + public static InboxPrincipal build(IntegrationEventProperties properties, ClaimExtractorProperties claimExtractorProperties) { + InboxPrincipal inboxPrincipal = new InboxPrincipal(true, "IntegrationEventQueueAppId"); + List clientKey = claimExtractorProperties.getMapping().getOrDefault("Client", null); + inboxPrincipal.put(clientKey != null && clientKey.getFirst() != null ? clientKey.getFirst().getType() : "client_id", properties.getAppId()); + inboxPrincipal.put("active", "true"); + List notBeforeKey = claimExtractorProperties.getMapping().getOrDefault("NotBefore", null); + inboxPrincipal.put(notBeforeKey != null && notBeforeKey.getFirst() != null ? notBeforeKey.getFirst().getType() :"nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString()); + List expiresAt = claimExtractorProperties.getMapping().getOrDefault("ExpiresAt", null); + inboxPrincipal.put(expiresAt != null && expiresAt.getFirst() != null ? expiresAt.getFirst().getType() :"exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString()); + return inboxPrincipal; + } + @Override public Boolean isAuthenticated() { return this.isAuthenticated; @@ -32,8 +46,12 @@ public class InboxPrincipal implements MyPrincipal, ClaimAccessor { @Override public List getClaimAsStringList(String claim) { - if (claims == null) return null; - return this.getClaimAsStringList(claim); + if (claims == null) + return null; + if (this.claims.containsKey(claim)){ + return List.of(this.claims.get(claim).toString()); + } + return null; } @Override @@ -44,13 +62,4 @@ public class InboxPrincipal implements MyPrincipal, ClaimAccessor { public void put(String key, Object value) { this.claims.put(key, value); } - - public static InboxPrincipal build(IntegrationEventProperties properties) { - InboxPrincipal inboxPrincipal = new InboxPrincipal(true, "IntegrationEventQueueAppId"); - inboxPrincipal.put("client_id", properties.getAppId()); - inboxPrincipal.put("active", "true"); - inboxPrincipal.put("nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString()); - inboxPrincipal.put("exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString()); - return inboxPrincipal; - } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandler.java b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandler.java index 4ef529ac2..579b2e9c7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandler.java +++ b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandler.java @@ -1,7 +1,5 @@ package eu.eudat.integrationevent.outbox.tenanttouched; -import javax.management.InvalidApplicationException; - public interface TenantTouchedIntegrationEventHandler { void handle(TenantTouchedIntegrationEvent event); diff --git a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java index 06cd22296..9d18589ad 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/integrationevent/outbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java @@ -1,10 +1,15 @@ package eu.eudat.integrationevent.outbox.tenanttouched; -import eu.eudat.commons.scope.tenant.TenantScope; import eu.eudat.integrationevent.outbox.OutboxIntegrationEvent; import eu.eudat.integrationevent.outbox.OutboxService; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + import java.util.UUID; +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class TenantTouchedIntegrationEventHandlerImpl implements TenantTouchedIntegrationEventHandler { private final OutboxService outboxService; diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/TenantUserQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/TenantUserQuery.java index c0ce98d05..76692c909 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/TenantUserQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/TenantUserQuery.java @@ -194,7 +194,7 @@ public class TenantUserQuery extends QueryBase { @Override protected String fieldNameOf(FieldResolver item) { if (item.match(TenantUser._id)) return TenantUserEntity._id; - else if (item.match(TenantUser._tenant, Tenant._id)) return TenantUserEntity._tenantId; + else if (item.match(TenantUser._tenant)) return TenantUserEntity._tenantId; else if (item.prefix(TenantUser._tenant)) return TenantUserEntity._tenantId; else if (item.match(TenantUser._isActive)) return TenantUserEntity._isActive; else if (item.match(TenantUser._createdAt)) return TenantUserEntity._createdAt; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java index 2aa543af0..311b91c15 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java @@ -25,6 +25,6 @@ public interface TenantService { Tenant persist(TenantPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException; - Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException; + Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException; void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java index 9ae298789..63428733a 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java @@ -9,6 +9,10 @@ import eu.eudat.convention.ConventionService; import eu.eudat.data.TenantEntity; import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEvent; +import eu.eudat.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEventHandler; +import eu.eudat.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEvent; +import eu.eudat.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEventHandler; import eu.eudat.model.Tenant; import eu.eudat.model.builder.TenantBuilder; import eu.eudat.model.deleter.TenantDeleter; @@ -67,18 +71,20 @@ public class TenantServiceImpl implements TenantService { private final EncryptionService encryptionService; private final TenantProperties properties; - + private final TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler; + private final TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler; + @Autowired public TenantServiceImpl( - TenantEntityManager entityManager, - AuthorizationService authorizationService, - DeleterFactory deleterFactory, - BuilderFactory builderFactory, - ConventionService conventionService, - MessageSource messageSource, - XmlHandlingService xmlHandlingService, - ErrorThesaurusProperties errors, - EncryptionService encryptionService, TenantProperties properties) { + TenantEntityManager entityManager, + AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + ConventionService conventionService, + MessageSource messageSource, + XmlHandlingService xmlHandlingService, + ErrorThesaurusProperties errors, + EncryptionService encryptionService, TenantProperties properties, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -89,6 +95,8 @@ public class TenantServiceImpl implements TenantService { this.errors = errors; this.encryptionService = encryptionService; this.properties = properties; + this.tenantTouchedIntegrationEventHandler = tenantTouchedIntegrationEventHandler; + this.tenantRemovalIntegrationEventHandler = tenantRemovalIntegrationEventHandler; } @Override @@ -124,6 +132,11 @@ public class TenantServiceImpl implements TenantService { this.entityManager.flush(); + TenantTouchedIntegrationEvent tenantTouchedIntegrationEvent = new TenantTouchedIntegrationEvent(); + tenantTouchedIntegrationEvent.setId(data.getId()); + tenantTouchedIntegrationEvent.setCode(data.getCode()); + this.tenantTouchedIntegrationEventHandler.handle(tenantTouchedIntegrationEvent); + return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data); } @@ -185,17 +198,25 @@ public class TenantServiceImpl implements TenantService { } @Override - public Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { + public Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException { if (model.getConfig() != null && model.getConfig().getDeposit() != null && model.getConfig().getDeposit().getSources() != null) { - for (TenantSource source : model.getConfig().getDeposit().getSources().stream().collect(Collectors.toList())) { + for (TenantSource source : model.getConfig().getDeposit().getSources().stream().toList()) { source.setClientSecret(this.encryptionService.decryptAES(source.getClientSecret(), properties.getConfigEncryptionAesKey(), properties.getConfigEncryptionAesIv())); } } if (model.getConfig() != null && model.getConfig().getFileTransformers() != null && model.getConfig().getFileTransformers().getSources() != null) { - for (TenantSource source : model.getConfig().getFileTransformers().getSources().stream().collect(Collectors.toList())) { + for (TenantSource source : model.getConfig().getFileTransformers().getSources().stream().toList()) { source.setClientSecret(this.encryptionService.decryptAES(source.getClientSecret(), properties.getConfigEncryptionAesKey(), properties.getConfigEncryptionAesIv())); } } + + TenantEntity data = this.entityManager.find(TenantEntity.class, model.getId()); + if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + TenantTouchedIntegrationEvent tenantTouchedIntegrationEvent = new TenantTouchedIntegrationEvent(); + tenantTouchedIntegrationEvent.setId(data.getId()); + tenantTouchedIntegrationEvent.setCode(data.getCode()); + this.tenantTouchedIntegrationEventHandler.handle(tenantTouchedIntegrationEvent); return model; } @@ -206,6 +227,10 @@ public class TenantServiceImpl implements TenantService { this.authorizationService.authorizeForce(Permission.DeleteTenant); this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id)); + + TenantRemovalIntegrationEvent tenantRemovalIntegrationEvent = new TenantRemovalIntegrationEvent(); + tenantRemovalIntegrationEvent.setId(id); + this.tenantRemovalIntegrationEventHandler.handle(tenantRemovalIntegrationEvent); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java index 4cb016591..51c8c03a5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen import jakarta.servlet.Filter; import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -101,7 +102,7 @@ public class SecurityConfiguration { //In the example below, the default client handler will be ignored by the resolver @Override public List>> disableHandlers() { - return List.of(PermissionClientAuthorizationHandler.class); + return new ArrayList<>(); } }; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java index 4eafcaf46..feef64391 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java @@ -78,7 +78,7 @@ public class TenantController { } @PostMapping("query") - public QueryResult query(@RequestBody TenantLookup lookup) throws MyApplicationException, MyForbiddenException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { + public QueryResult query(@RequestBody TenantLookup lookup) throws MyApplicationException, MyForbiddenException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException { logger.debug("querying {}", Tenant.class.getSimpleName()); this.censorFactory.censor(TenantCensor.class).censor(lookup.getProject(), null); @@ -97,7 +97,7 @@ public class TenantController { } @GetMapping("{id}") - public Tenant get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { + public Tenant get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidApplicationException { logger.debug(new MapLogEntry("retrieving" + Tenant.class.getSimpleName()).And("id", id).And("fields", fieldSet)); this.censorFactory.censor(TenantCensor.class).censor(fieldSet, null);