Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-06-18 16:09:58 +03:00
commit 88a814125d
63 changed files with 1103 additions and 272 deletions

View File

@ -56,8 +56,6 @@ public class TenantByCodeCacheService extends CacheService<TenantByCodeCacheServ
public void handleTenantTouchedEvent(TenantTouchedEvent event) { public void handleTenantTouchedEvent(TenantTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
this.evict(this.buildKey(event.getTenantCode())); this.evict(this.buildKey(event.getTenantCode()));
if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode()))
this.evict(this.buildKey(event.getPreviousTenantCode()));
} }
@Override @Override

View File

@ -45,17 +45,15 @@ public class TenantByIdCacheService extends CacheService<TenantByIdCacheService.
} }
} }
private final ConventionService conventionService;
@Autowired @Autowired
public TenantByIdCacheService(TenantByIdCacheOptions options, ConventionService conventionService) { public TenantByIdCacheService(TenantByIdCacheOptions options) {
super(options); super(options);
this.conventionService = conventionService;
} }
@EventListener @EventListener
public void handleTenantTouchedEvent(TenantTouchedEvent event) { public void handleTenantTouchedEvent(TenantTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) if (event.getTenantId() != null)
this.evict(this.buildKey(event.getTenantId())); this.evict(this.buildKey(event.getTenantId()));
} }

View File

@ -1,8 +1,10 @@
package gr.cite.annotation.web.scope.user; package gr.cite.annotation.web.scope.user;
import gr.cite.annotation.convention.ConventionService; import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.event.UserCredentialTouchedEvent;
import gr.cite.tools.cache.CacheService; import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashMap; import java.util.HashMap;
@ -10,6 +12,7 @@ import java.util.UUID;
@Service @Service
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> { public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
private final ConventionService conventionService;
public static class UserInterceptorCacheValue { public static class UserInterceptorCacheValue {
@ -43,9 +46,16 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
} }
@EventListener
public void handleTenantTouchedEvent(UserCredentialTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getSubjectId()))
this.evict(this.buildKey(event.getSubjectId()));
}
@Autowired @Autowired
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) { public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService){
super(options); super(options);
this.conventionService = conventionService;
} }
@Override @Override

View File

@ -13,25 +13,25 @@ cache:
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 600 expireAfterWriteSeconds: 20
- names: [ tenantById ] - names: [ tenantById ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 600 expireAfterWriteSeconds: 20
- names: [ userBySubjectId ] - names: [ userBySubjectId ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 320 expireAfterWriteSeconds: 20
- names: [ userAccessTenant ] - names: [ userAccessTenant ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 320 expireAfterWriteSeconds: 20
- names: [ "affiliation" ] - names: [ "affiliation" ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100

View File

@ -34,4 +34,8 @@ public class EventBroker {
this.applicationEventPublisher.publishEvent(event); this.applicationEventPublisher.publishEvent(event);
} }
public void emit(UserCredentialTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}
} }

View File

@ -6,15 +6,13 @@ public class TenantTouchedEvent {
public TenantTouchedEvent() { public TenantTouchedEvent() {
} }
public TenantTouchedEvent(UUID tenantId, String tenantCode, String previousTenantCode) { public TenantTouchedEvent(UUID tenantId, String tenantCode) {
this.tenantId = tenantId; this.tenantId = tenantId;
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
this.previousTenantCode = previousTenantCode;
} }
private UUID tenantId; private UUID tenantId;
private String tenantCode; private String tenantCode;
private String previousTenantCode;
public UUID getTenantId() { public UUID getTenantId() {
return tenantId; return tenantId;
@ -32,11 +30,4 @@ public class TenantTouchedEvent {
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
} }
public String getPreviousTenantCode() {
return previousTenantCode;
}
public void setPreviousTenantCode(String previousTenantCode) {
this.previousTenantCode = previousTenantCode;
}
} }

View File

@ -0,0 +1,33 @@
package gr.cite.annotation.event;
import java.util.UUID;
public class UserCredentialTouchedEvent {
public UserCredentialTouchedEvent() {
}
public UserCredentialTouchedEvent(UUID id, String subjectId) {
this.id = id;
this.subjectId = subjectId;
}
private UUID id;
public UUID getId() {
return this.id;
}
public void setId(UUID id) {
this.id = id;
}
private String subjectId;
public String getSubjectId() {
return this.subjectId;
}
public void setSubjectId(String subjectId) {
this.subjectId = subjectId;
}
}

View File

@ -6,15 +6,11 @@ public class UserTouchedEvent {
public UserTouchedEvent() { public UserTouchedEvent() {
} }
public UserTouchedEvent(UUID userId, String subjectId, String previousSubjectId) { public UserTouchedEvent(UUID userId) {
this.userId = userId; this.userId = userId;
this.subjectId = subjectId;
this.previousSubjectId = previousSubjectId;
} }
private UUID userId; private UUID userId;
private String subjectId;
private String previousSubjectId;
public UUID getUserId() { public UUID getUserId() {
return userId; return userId;
@ -24,19 +20,4 @@ public class UserTouchedEvent {
this.userId = userId; this.userId = userId;
} }
public String getSubjectId() {
return subjectId;
}
public void setSubjectId(String subjectId) {
this.subjectId = subjectId;
}
public String getPreviousSubjectId() {
return previousSubjectId;
}
public void setPreviousSubjectId(String previousSubjectId) {
this.previousSubjectId = previousSubjectId;
}
} }

View File

@ -3,6 +3,8 @@ package gr.cite.annotation.model.deleter;
import gr.cite.annotation.common.enums.IsActive; import gr.cite.annotation.common.enums.IsActive;
import gr.cite.annotation.data.TenantEntity; import gr.cite.annotation.data.TenantEntity;
import gr.cite.annotation.data.TenantEntityManager; import gr.cite.annotation.data.TenantEntityManager;
import gr.cite.annotation.event.EventBroker;
import gr.cite.annotation.event.TenantTouchedEvent;
import gr.cite.annotation.query.TenantQuery; import gr.cite.annotation.query.TenantQuery;
import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,17 +30,16 @@ public class TenantDeleter implements Deleter {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
protected final QueryFactory queryFactory; protected final QueryFactory queryFactory;
private final DeleterFactory deleterFactory; private final EventBroker eventBroker;
@Autowired @Autowired
public TenantDeleter( public TenantDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory, QueryFactory queryFactory, EventBroker eventBroker
DeleterFactory deleterFactory
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory; this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +70,7 @@ public class TenantDeleter implements Deleter {
logger.trace("updating item"); logger.trace("updating item");
this.entityManager.merge(item); this.entityManager.merge(item);
logger.trace("updated item"); logger.trace("updated item");
this.eventBroker.emit(new TenantTouchedEvent(item.getId(), item.getCode()));
} }
} }

View File

@ -3,6 +3,8 @@ package gr.cite.annotation.model.deleter;
import gr.cite.annotation.common.enums.IsActive; import gr.cite.annotation.common.enums.IsActive;
import gr.cite.annotation.data.TenantEntityManager; import gr.cite.annotation.data.TenantEntityManager;
import gr.cite.annotation.data.TenantUserEntity; import gr.cite.annotation.data.TenantUserEntity;
import gr.cite.annotation.event.EventBroker;
import gr.cite.annotation.event.UserRemovedFromTenantEvent;
import gr.cite.annotation.query.TenantUserQuery; import gr.cite.annotation.query.TenantUserQuery;
import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,17 +30,15 @@ public class TenantUserDeleter implements Deleter {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final DeleterFactory deleterFactory; private final EventBroker eventBroker;
@Autowired @Autowired
public TenantUserDeleter( public TenantUserDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory, QueryFactory queryFactory, EventBroker eventBroker
DeleterFactory deleterFactory
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory; this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +69,7 @@ public class TenantUserDeleter implements Deleter {
logger.trace("updating item"); logger.trace("updating item");
this.entityManager.merge(item); this.entityManager.merge(item);
logger.trace("updated item"); logger.trace("updated item");
this.eventBroker.emit(new UserRemovedFromTenantEvent(item.getUserId(), item.getTenantId()));
} }
} }
} }

View File

@ -2,6 +2,8 @@ package gr.cite.annotation.service.tenant;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import gr.cite.annotation.data.TenantEntityManager; import gr.cite.annotation.data.TenantEntityManager;
import gr.cite.annotation.event.EventBroker;
import gr.cite.annotation.event.TenantTouchedEvent;
import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.annotation.authorization.AuthorizationFlags; import gr.cite.annotation.authorization.AuthorizationFlags;
import gr.cite.annotation.authorization.Permission; import gr.cite.annotation.authorization.Permission;
@ -23,6 +25,8 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException; import javax.management.InvalidApplicationException;
@ -45,17 +49,21 @@ public class TenantServiceImpl implements TenantService {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
private final BuilderFactory builderFactory; private final BuilderFactory builderFactory;
private final EventBroker eventBroker;
private final MessageSource messageSource;
public TenantServiceImpl(AuthorizationService authorizationService, public TenantServiceImpl(AuthorizationService authorizationService,
DeleterFactory deleterFactory, DeleterFactory deleterFactory,
ConventionService conventionService, ConventionService conventionService,
TenantEntityManager entityManager, TenantEntityManager entityManager,
BuilderFactory builderFactory) { BuilderFactory builderFactory, EventBroker eventBroker, MessageSource messageSource) {
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
this.conventionService = conventionService; this.conventionService = conventionService;
this.entityManager = entityManager; this.entityManager = entityManager;
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.eventBroker = eventBroker;
this.messageSource = messageSource;
} }
@Override @Override
@ -91,6 +99,7 @@ public class TenantServiceImpl implements TenantService {
this.entityManager.flush(); this.entityManager.flush();
this.eventBroker.emit(new TenantTouchedEvent(data.getId(), data.getCode()));
return this.builderFactory.builder(TenantBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, Tenant._id), data); return this.builderFactory.builder(TenantBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, Tenant._id), data);
} }
@ -98,9 +107,14 @@ public class TenantServiceImpl implements TenantService {
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting Tenant: {}", id); logger.debug("deleting Tenant: {}", id);
TenantEntity data = this.entityManager.find(TenantEntity.class, id);
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.authorizationService.authorizeForce(Permission.DeleteTenant); this.authorizationService.authorizeForce(Permission.DeleteTenant);
this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id)); this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id));
this.eventBroker.emit(new TenantTouchedEvent(data.getId(), data.getCode()));
} }
} }

View File

@ -8,6 +8,10 @@ import gr.cite.annotation.common.enums.IsActive;
import gr.cite.annotation.common.scope.tenant.TenantScope; import gr.cite.annotation.common.scope.tenant.TenantScope;
import gr.cite.annotation.convention.ConventionService; import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.data.*; import gr.cite.annotation.data.*;
import gr.cite.annotation.event.EventBroker;
import gr.cite.annotation.event.UserAddedToTenantEvent;
import gr.cite.annotation.event.UserCredentialTouchedEvent;
import gr.cite.annotation.event.UserTouchedEvent;
import gr.cite.annotation.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent; import gr.cite.annotation.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent;
import gr.cite.annotation.model.Tenant; import gr.cite.annotation.model.Tenant;
import gr.cite.annotation.model.User; import gr.cite.annotation.model.User;
@ -62,6 +66,7 @@ public class UserServiceImpl implements UserService {
private final TenantScope tenantScope; private final TenantScope tenantScope;
private final MessageSource messageSource; private final MessageSource messageSource;
private final EventBroker eventBroker;
private final JsonHandlingService jsonHandlingService; private final JsonHandlingService jsonHandlingService;
@ -70,7 +75,7 @@ public class UserServiceImpl implements UserService {
DeleterFactory deleterFactory, DeleterFactory deleterFactory,
ConventionService conventionService, ConventionService conventionService,
TenantEntityManager entityManager, TenantEntityManager entityManager,
BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, EventBroker eventBroker,
JsonHandlingService jsonHandlingService) { JsonHandlingService jsonHandlingService) {
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
@ -80,6 +85,7 @@ public class UserServiceImpl implements UserService {
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.tenantScope = tenantScope; this.tenantScope = tenantScope;
this.messageSource = messageSource; this.messageSource = messageSource;
this.eventBroker = eventBroker;
this.jsonHandlingService = jsonHandlingService; this.jsonHandlingService = jsonHandlingService;
} }
@ -124,6 +130,7 @@ public class UserServiceImpl implements UserService {
this.persistTenantUser(model.getTenantUsers(), data.getId()); this.persistTenantUser(model.getTenantUsers(), data.getId());
this.entityManager.flush(); this.entityManager.flush();
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
return this.builderFactory.builder(UserBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, User._id), data); return this.builderFactory.builder(UserBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, User._id), data);
} }
@ -135,6 +142,7 @@ public class UserServiceImpl implements UserService {
this.authorizationService.authorizeForce(Permission.DeleteUser); this.authorizationService.authorizeForce(Permission.DeleteUser);
this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id)); this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id));
this.eventBroker.emit(new UserTouchedEvent(id));
} }
private void persistUserCredential(List<UserTouchedIntegrationEvent.UserCredential> models, UUID userId) throws InvalidApplicationException { private void persistUserCredential(List<UserTouchedIntegrationEvent.UserCredential> models, UUID userId) throws InvalidApplicationException {
@ -155,6 +163,7 @@ public class UserServiceImpl implements UserService {
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
entityManager.persist(data); entityManager.persist(data);
} }
this.eventBroker.emit(new UserCredentialTouchedEvent(data.getId(), data.getExternalId()));
updatedCreatedIds.add(data.getId()); updatedCreatedIds.add(data.getId());
} }
} }
@ -191,6 +200,7 @@ public class UserServiceImpl implements UserService {
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
data.setIsActive(IsActive.Active); data.setIsActive(IsActive.Active);
entityManager.persist(data); entityManager.persist(data);
this.eventBroker.emit(new UserAddedToTenantEvent(data.getUserId(), data.getTenantId()));
} finally { } finally {
this.tenantScope.removeTempTenant(this.entityManager); this.tenantScope.removeTempTenant(this.entityManager);
} }

View File

@ -66,7 +66,7 @@
<dependency> <dependency>
<groupId>org.opencdmp</groupId> <groupId>org.opencdmp</groupId>
<artifactId>file-transformer-base</artifactId> <artifactId>file-transformer-base</artifactId>
<version>0.0.22</version> <version>0.0.23</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>gr.cite</groupId> <groupId>gr.cite</groupId>

View File

@ -131,6 +131,7 @@ public final class Permission {
//Reference //Reference
public static String BrowseReference = "BrowseReference"; public static String BrowseReference = "BrowseReference";
public static String BrowseExternalReference = "BrowseExternalReference";
public static String EditReference = "EditReference"; public static String EditReference = "EditReference";
public static String DeleteReference = "DeleteReference"; public static String DeleteReference = "DeleteReference";

View File

@ -11,7 +11,7 @@ public class AdditionalInfoEntity {
private UUID organizationId; private UUID organizationId;
public String getAvatarUrl() { public String getAvatarUrl() {
return avatarUrl; return this.avatarUrl;
} }
public void setAvatarUrl(String avatarUrl) { public void setAvatarUrl(String avatarUrl) {
@ -19,7 +19,7 @@ public class AdditionalInfoEntity {
} }
public String getTimezone() { public String getTimezone() {
return timezone; return this.timezone;
} }
public void setTimezone(String timezone) { public void setTimezone(String timezone) {
@ -27,7 +27,7 @@ public class AdditionalInfoEntity {
} }
public String getCulture() { public String getCulture() {
return culture; return this.culture;
} }
public void setCulture(String culture) { public void setCulture(String culture) {
@ -35,7 +35,7 @@ public class AdditionalInfoEntity {
} }
public String getLanguage() { public String getLanguage() {
return language; return this.language;
} }
public void setLanguage(String language) { public void setLanguage(String language) {
@ -43,7 +43,7 @@ public class AdditionalInfoEntity {
} }
public UUID getOrganizationId() { public UUID getOrganizationId() {
return organizationId; return this.organizationId;
} }
public void setOrganizationId(UUID organizationId) { public void setOrganizationId(UUID organizationId) {
@ -51,7 +51,7 @@ public class AdditionalInfoEntity {
} }
public String getRoleOrganization() { public String getRoleOrganization() {
return roleOrganization; return this.roleOrganization;
} }
public void setRoleOrganization(String roleOrganization) { public void setRoleOrganization(String roleOrganization) {

View File

@ -57,4 +57,8 @@ public class EventBroker {
this.applicationEventPublisher.publishEvent(event); this.applicationEventPublisher.publishEvent(event);
} }
public void emit(UserCredentialTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}
} }

View File

@ -6,18 +6,16 @@ public class TenantTouchedEvent {
public TenantTouchedEvent() { public TenantTouchedEvent() {
} }
public TenantTouchedEvent(UUID tenantId, String tenantCode, String previousTenantCode) { public TenantTouchedEvent(UUID tenantId, String tenantCode) {
this.tenantId = tenantId; this.tenantId = tenantId;
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
this.previousTenantCode = previousTenantCode;
} }
private UUID tenantId; private UUID tenantId;
private String tenantCode; private String tenantCode;
private String previousTenantCode;
public UUID getTenantId() { public UUID getTenantId() {
return tenantId; return this.tenantId;
} }
public void setTenantId(UUID tenantId) { public void setTenantId(UUID tenantId) {
@ -25,18 +23,11 @@ public class TenantTouchedEvent {
} }
public String getTenantCode() { public String getTenantCode() {
return tenantCode; return this.tenantCode;
} }
public void setTenantCode(String tenantCode) { public void setTenantCode(String tenantCode) {
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
} }
public String getPreviousTenantCode() {
return previousTenantCode;
}
public void setPreviousTenantCode(String previousTenantCode) {
this.previousTenantCode = previousTenantCode;
}
} }

View File

@ -0,0 +1,33 @@
package org.opencdmp.event;
import java.util.UUID;
public class UserCredentialTouchedEvent {
public UserCredentialTouchedEvent() {
}
public UserCredentialTouchedEvent(UUID id, String subjectId) {
this.id = id;
this.subjectId = subjectId;
}
private UUID id;
public UUID getId() {
return this.id;
}
public void setId(UUID id) {
this.id = id;
}
private String subjectId;
public String getSubjectId() {
return this.subjectId;
}
public void setSubjectId(String subjectId) {
this.subjectId = subjectId;
}
}

View File

@ -13,7 +13,7 @@ public class UserTouchedEvent {
private UUID userId; private UUID userId;
public UUID getUserId() { public UUID getUserId() {
return userId; return this.userId;
} }
public void setUserId(UUID userId) { public void setUserId(UUID userId) {

View File

@ -1,15 +1,18 @@
package org.opencdmp.model.deleter; package org.opencdmp.model.deleter;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.*;
import org.opencdmp.query.DescriptionTagQuery;
import org.opencdmp.query.TenantConfigurationQuery;
import org.opencdmp.query.TenantQuery;
import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.TenantConfigurationEntity;
import org.opencdmp.data.TenantEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.event.EventBroker;
import org.opencdmp.event.TenantTouchedEvent;
import org.opencdmp.query.TenantConfigurationQuery;
import org.opencdmp.query.TenantQuery;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -24,7 +27,7 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component @Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TenantDeleter implements Deleter { public class TenantDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantDeleter.class)); private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantDeleter.class));
@ -34,16 +37,18 @@ public class TenantDeleter implements Deleter {
protected final QueryFactory queryFactory; protected final QueryFactory queryFactory;
protected final DeleterFactory deleterFactory; protected final DeleterFactory deleterFactory;
private final EventBroker eventBroker;
@Autowired @Autowired
public TenantDeleter( public TenantDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory, QueryFactory queryFactory,
DeleterFactory deleterFactory DeleterFactory deleterFactory, EventBroker eventBroker
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -83,6 +88,7 @@ public class TenantDeleter implements Deleter {
logger.trace("updating item"); logger.trace("updating item");
this.entityManager.merge(item); this.entityManager.merge(item);
logger.trace("updated item"); logger.trace("updated item");
this.eventBroker.emit(new TenantTouchedEvent(item.getId(), item.getCode()));
} }
} }

View File

@ -1,14 +1,15 @@
package org.opencdmp.model.deleter; package org.opencdmp.model.deleter;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.TenantUserEntity;
import org.opencdmp.query.TenantUserQuery;
import gr.cite.tools.data.deleter.Deleter; 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.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.TenantUserEntity;
import org.opencdmp.event.EventBroker;
import org.opencdmp.event.UserRemovedFromTenantEvent;
import org.opencdmp.query.TenantUserQuery;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -22,23 +23,22 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@Component @Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TenantUserDeleter implements Deleter { public class TenantUserDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantUserDeleter.class)); private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantUserDeleter.class));
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final DeleterFactory deleterFactory; private final EventBroker eventBroker;
@Autowired @Autowired
public TenantUserDeleter( public TenantUserDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory, QueryFactory queryFactory, EventBroker eventBroker
DeleterFactory deleterFactory
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory; this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +69,7 @@ public class TenantUserDeleter implements Deleter {
logger.trace("updating item"); logger.trace("updating item");
this.entityManager.merge(item); this.entityManager.merge(item);
logger.trace("updated item"); logger.trace("updated item");
this.eventBroker.emit(new UserRemovedFromTenantEvent(item.getUserId(), item.getTenantId()));
} }
} }
} }

View File

@ -6,6 +6,8 @@ import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.data.TenantEntityManager; import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserCredentialEntity; import org.opencdmp.data.UserCredentialEntity;
import org.opencdmp.event.EventBroker;
import org.opencdmp.event.UserCredentialTouchedEvent;
import org.opencdmp.query.UserCredentialQuery; import org.opencdmp.query.UserCredentialQuery;
import org.opencdmp.service.keycloak.KeycloakService; import org.opencdmp.service.keycloak.KeycloakService;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -28,16 +30,18 @@ public class UserCredentialDeleter implements Deleter {
protected final QueryFactory queryFactory; protected final QueryFactory queryFactory;
private final KeycloakService keycloakService; private final KeycloakService keycloakService;
private final EventBroker eventBroker;
@Autowired @Autowired
public UserCredentialDeleter( public UserCredentialDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory, KeycloakService keycloakService QueryFactory queryFactory, KeycloakService keycloakService, EventBroker eventBroker
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.keycloakService = keycloakService; this.keycloakService = keycloakService;
this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -67,6 +71,8 @@ public class UserCredentialDeleter implements Deleter {
logger.trace("deleted item"); logger.trace("deleted item");
this.keycloakService.removeFromAllGroups(item.getExternalId()); this.keycloakService.removeFromAllGroups(item.getExternalId());
this.eventBroker.emit(new UserCredentialTouchedEvent(item.getId(), item.getExternalId()));
} }
} }

View File

@ -0,0 +1,88 @@
package org.opencdmp.model.persist;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
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 java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class DescriptionCommonModelConfig {
private String id;
public static final String _id = "id";
private UUID sectionId;
public static final String _sectionId = "_sectionId";
private UUID templateId;
public static final String _templateId = "templateId";
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public UUID getSectionId() {
return sectionId;
}
public void setSectionId(UUID sectionId) {
this.sectionId = sectionId;
}
public UUID getTemplateId() {
return templateId;
}
public void setTemplateId(UUID templateId) {
this.templateId = templateId;
}
@Component(DescriptionCommonModelConfigValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class DescriptionCommonModelConfigValidator extends BaseValidator<DescriptionCommonModelConfig> {
public static final String ValidatorName = "DescriptionCommonModelConfigValidator";
private final MessageSource messageSource;
protected DescriptionCommonModelConfigValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<DescriptionCommonModelConfig> modelClass() {
return DescriptionCommonModelConfig.class;
}
@Override
protected List<Specification> specifications(DescriptionCommonModelConfig item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isEmpty(item.getId()))
.failOn(DescriptionCommonModelConfig._id).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionCommonModelConfig._id}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getId()))
.must(() -> this.isValidGuid(UUID.fromString(item.getId())))
.failOn(DescriptionCommonModelConfig._id).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionCommonModelConfig._id}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> this.isValidGuid(item.getSectionId()))
.failOn(DescriptionCommonModelConfig._sectionId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionCommonModelConfig._sectionId}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> this.isValidGuid(item.getTemplateId()))
.failOn(DescriptionCommonModelConfig._templateId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionCommonModelConfig._templateId}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -0,0 +1,127 @@
package org.opencdmp.model.persist;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DmpEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
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 java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class DmpCommonModelConfig {
private UUID fileId;
public static final String _fileId = "fileId";
private String label;
public static final String _label = "label";
private String repositoryId;
public static final String _repositoryId = "repositoryId";
private UUID blueprintId;
public static final String _blueprintId = "blueprintId";
private List<DescriptionCommonModelConfig> descriptions;
public static final String _descriptions = "descriptions";
public UUID getFileId() {
return fileId;
}
public void setFileId(UUID fileId) {
this.fileId = fileId;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public UUID getBlueprintId() {
return blueprintId;
}
public void setBlueprintId(UUID blueprintId) {
this.blueprintId = blueprintId;
}
public List<DescriptionCommonModelConfig> getDescriptions() {
return descriptions;
}
public void setDescriptions(List<DescriptionCommonModelConfig> descriptions) {
this.descriptions = descriptions;
}
@Component(DmpCommonModelConfigValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class DmpCommonModelConfigValidator extends BaseValidator<DmpCommonModelConfig> {
public static final String ValidatorName = "DmpCommonModelConfigValidator";
private final MessageSource messageSource;
private final ValidatorFactory validatorFactory;
protected DmpCommonModelConfigValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
super(conventionService, errors);
this.messageSource = messageSource;
this.validatorFactory = validatorFactory;
}
@Override
protected Class<DmpCommonModelConfig> modelClass() {
return DmpCommonModelConfig.class;
}
@Override
protected List<Specification> specifications(DmpCommonModelConfig item) {
return Arrays.asList(
this.spec()
.must(() -> this.isValidGuid(item.getFileId()))
.failOn(DmpCommonModelConfig._fileId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DmpCommonModelConfig._fileId}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getLabel()))
.failOn(DmpCommonModelConfig._label).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DmpCommonModelConfig._label}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getLabel()))
.must(() -> this.lessEqualLength(item.getLabel(), DmpEntity._labelLength))
.failOn(DmpCommonModelConfig._label).failWith(this.messageSource.getMessage("Validation_MaxLength", new Object[]{DmpCommonModelConfig._label}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getRepositoryId()))
.failOn(DmpCommonModelConfig._repositoryId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DmpCommonModelConfig._repositoryId}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getRepositoryId()))
.must(() -> this.isValidGuid(UUID.fromString(item.getRepositoryId())))
.failOn(DmpCommonModelConfig._repositoryId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DmpCommonModelConfig._repositoryId}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> this.isValidGuid(item.getBlueprintId()))
.failOn(DmpCommonModelConfig._blueprintId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DmpCommonModelConfig._blueprintId}, LocaleContextHolder.getLocale())),
this.navSpec()
.iff(() -> !this.isListNullOrEmpty(item.getDescriptions()))
.on(DmpCommonModelConfig._descriptions)
.over(item.getDescriptions())
.using((itm) -> this.validatorFactory.validator(DescriptionCommonModelConfig.DescriptionCommonModelConfigValidator.class))
);
}
}
}

View File

@ -232,6 +232,7 @@ public class ReferenceQuery extends QueryBase<ReferenceEntity> {
List<Predicate> predicates = new ArrayList<>(); List<Predicate> predicates = new ArrayList<>();
if (userId != null || usePublic) { if (userId != null || usePublic) {
predicates.add(queryContext.CriteriaBuilder.or( predicates.add(queryContext.CriteriaBuilder.or(
this.authService.authorize(Permission.BrowseExternalReference) ? queryContext.CriteriaBuilder.equal(queryContext.Root.get(ReferenceEntity._sourceType), ReferenceSourceType.External) : queryContext.CriteriaBuilder.or(),
userId != null ? queryContext.CriteriaBuilder.equal(queryContext.Root.get(ReferenceEntity._createdById), userId) : queryContext.CriteriaBuilder.or(), //Creates a false query userId != null ? queryContext.CriteriaBuilder.equal(queryContext.Root.get(ReferenceEntity._createdById), userId) : queryContext.CriteriaBuilder.or(), //Creates a false query
queryContext.CriteriaBuilder.in(queryContext.Root.get(ReferenceEntity._id)).value(this.queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(DmpReferenceEntity.class, UUID.class) queryContext.CriteriaBuilder.in(queryContext.Root.get(ReferenceEntity._id)).value(this.queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(DmpReferenceEntity.class, UUID.class)
.query(queryContext.Query) .query(queryContext.Query)

View File

@ -1669,15 +1669,18 @@ public class DescriptionServiceImpl implements DescriptionService {
if (!referenceTypeEntity.getCode().equals(model.getType().getCode())) throw new MyApplicationException("Invalid reference for field " + model.getId()); if (!referenceTypeEntity.getCode().equals(model.getType().getCode())) throw new MyApplicationException("Invalid reference for field " + model.getId());
ReferenceEntity referenceEntity = this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(); //TODO: optimize ReferenceEntity referenceEntity = model.getId() != null ? this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(): null; //TODO: optimize
if (referenceEntity == null) referenceEntity = this.queryFactory.query(ReferenceQuery.class).references(model.getReference()).typeIds(referenceTypeEntity.getId()).sources(model.getSource()).first(); if (referenceEntity == null && !this.conventionService.isNullOrEmpty(model.getReference())) {
List<ReferenceEntity> referenceEntities = this.queryFactory.query(ReferenceQuery.class).references(model.getReference()).typeIds(referenceTypeEntity.getId()).collect();
if (referenceEntities != null && referenceEntities.size() == 1) referenceEntity = referenceEntities.getFirst();
}
ReferencePersist persist = new ReferencePersist(); ReferencePersist persist = new ReferencePersist();
persist.setTypeId(referenceTypeEntity.getId()); persist.setTypeId(referenceTypeEntity.getId());
if (referenceEntity == null) { if (referenceEntity == null) {
persist.setLabel(model.getLabel()); persist.setLabel(model.getLabel());
persist.setReference(model.getReference()); persist.setReference(!this.conventionService.isNullOrEmpty(model.getReference()) ? model.getReference() : UUID.randomUUID().toString());
persist.setSource("internal"); persist.setSource("internal");
persist.setSourceType(ReferenceSourceType.Internal); persist.setSourceType(ReferenceSourceType.Internal);
} else { } else {

View File

@ -7,12 +7,12 @@ import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.fieldset.FieldSet;
import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.JAXBException;
import org.opencdmp.commons.types.dmp.importexport.DmpImportExport; import org.opencdmp.commons.types.dmp.importexport.DmpImportExport;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.model.DmpUser; import org.opencdmp.model.DmpUser;
import org.opencdmp.model.DmpValidationResult; import org.opencdmp.model.DmpValidationResult;
import org.opencdmp.model.dmp.Dmp; import org.opencdmp.model.dmp.Dmp;
import org.opencdmp.model.persist.*; import org.opencdmp.model.persist.*;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
@ -59,5 +59,7 @@ public interface DmpService {
Dmp importXml(byte[] bytes, String label, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, TransformerException, InvalidApplicationException, IOException, InstantiationException, IllegalAccessException, SAXException; Dmp importXml(byte[] bytes, String label, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, TransformerException, InvalidApplicationException, IOException, InstantiationException, IllegalAccessException, SAXException;
Dmp importJson(MultipartFile file, String label, String repositoryId, String format, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException; Dmp importJson(DmpCommonModelConfig dmpCommonModelConfig, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException;
PreprocessingDmpModel preprocessingDmp(UUID fileId, String repositoryId) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException;
} }

View File

@ -64,6 +64,7 @@ import org.opencdmp.data.*;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.DmpTouchedEvent; import org.opencdmp.event.DmpTouchedEvent;
import org.opencdmp.event.EventBroker; import org.opencdmp.event.EventBroker;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.integrationevent.outbox.annotationentityremoval.AnnotationEntityRemovalIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.annotationentityremoval.AnnotationEntityRemovalIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
@ -107,7 +108,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
@ -2051,16 +2051,19 @@ public class DmpServiceImpl implements DmpService {
//region Import RDA JSON //region Import RDA JSON
public PreprocessingDmpModel preprocessingDmp(UUID fileId, String repositoryId) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException {
return this.fileTransformerService.preprocessingDmp(fileId, repositoryId);
}
public Dmp importJson(MultipartFile file, String label, String repositoryId, String format, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException { public Dmp importJson(DmpCommonModelConfig dmpCommonModelConfig, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException {
DmpModel model = this.fileTransformerService.importDmp(file, repositoryId, format); logger.debug(new MapLogEntry("import data").And("file id", dmpCommonModelConfig.getFileId()).And("label", dmpCommonModelConfig.getLabel()).And("fields", fields));
DmpModel model = this.fileTransformerService.importDmp(dmpCommonModelConfig);
if (model == null) throw new MyNotFoundException("Plan Import Error"); if (model == null) throw new MyNotFoundException("Plan Import Error");
logger.debug(new MapLogEntry("import data").And("bytes", file.getBytes()).And("label", label).And("fields", fields));
DmpPersist persist = new DmpPersist(); DmpPersist persist = new DmpPersist();
persist.setLabel(label); persist.setLabel(dmpCommonModelConfig.getLabel());
persist.setStatus(DmpStatus.Draft); persist.setStatus(DmpStatus.Draft);
persist.setDescription(model.getDescription()); persist.setDescription(model.getDescription());
switch (model.getAccessType()) { switch (model.getAccessType()) {
@ -2163,7 +2166,7 @@ public class DmpServiceImpl implements DmpService {
} }
} else { } else {
// custom fields // custom fields
if (field.getCategory().equals(org.opencdmp.commonmodels.enums.DmpBlueprintFieldCategory.Extra) && commonModel.getProperties() != null && this.conventionService.isListNullOrEmpty(commonModel.getProperties().getDmpBlueprintValues())){ if (field.getCategory().equals(org.opencdmp.commonmodels.enums.DmpBlueprintFieldCategory.Extra) && commonModel.getProperties() != null && !this.conventionService.isListNullOrEmpty(commonModel.getProperties().getDmpBlueprintValues())){
DmpBlueprintValueModel dmpBlueprintValueModel = commonModel.getProperties().getDmpBlueprintValues().stream().filter(x -> x.getFieldId().equals(field.getId())).findFirst().orElse(null); DmpBlueprintValueModel dmpBlueprintValueModel = commonModel.getProperties().getDmpBlueprintValues().stream().filter(x -> x.getFieldId().equals(field.getId())).findFirst().orElse(null);
ExtraFieldModel extraFieldModel = (ExtraFieldModel) field; ExtraFieldModel extraFieldModel = (ExtraFieldModel) field;
if (dmpBlueprintValueModel != null) dmpBlueprintValues.put(dmpBlueprintValueModel.getFieldId(), this.commonModelDmpBlueprintValueToPersist(dmpBlueprintValueModel, extraFieldModel)); if (dmpBlueprintValueModel != null) dmpBlueprintValues.put(dmpBlueprintValueModel.getFieldId(), this.commonModelDmpBlueprintValueToPersist(dmpBlueprintValueModel, extraFieldModel));
@ -2207,15 +2210,18 @@ public class DmpServiceImpl implements DmpService {
if (this.conventionService.isNullOrEmpty(model.getLabel()) && this.conventionService.isNullOrEmpty(model.getReference())) throw new MyApplicationException("Dmp Reference without label and reference id "); if (this.conventionService.isNullOrEmpty(model.getLabel()) && this.conventionService.isNullOrEmpty(model.getReference())) throw new MyApplicationException("Dmp Reference without label and reference id ");
ReferenceEntity referenceEntity = this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(); //TODO: optimize ReferenceEntity referenceEntity = model.getId() != null ? this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(): null; //TODO: optimize
if (referenceEntity == null) referenceEntity = this.queryFactory.query(ReferenceQuery.class).references(model.getReference()).typeIds(referenceTypeEntity.getId()).sources(model.getSource()).first(); if (referenceEntity == null && !this.conventionService.isNullOrEmpty(model.getReference())) {
List<ReferenceEntity> referenceEntities = this.queryFactory.query(ReferenceQuery.class).references(model.getReference()).typeIds(referenceTypeEntity.getId()).collect();
if (referenceEntities != null && referenceEntities.size() == 1) referenceEntity = referenceEntities.getFirst();
}
ReferencePersist persist = new ReferencePersist(); ReferencePersist persist = new ReferencePersist();
persist.setTypeId(referenceTypeEntity.getId()); persist.setTypeId(referenceTypeEntity.getId());
if (referenceEntity == null) { if (referenceEntity == null) {
persist.setLabel(model.getLabel()); persist.setLabel(model.getLabel());
persist.setReference(model.getReference()); persist.setReference(!this.conventionService.isNullOrEmpty(model.getReference()) ? model.getReference() : UUID.randomUUID().toString());
persist.setSource("internal"); persist.setSource("internal");
persist.setSourceType(ReferenceSourceType.Internal); persist.setSourceType(ReferenceSourceType.Internal);
} else { } else {

View File

@ -7,6 +7,10 @@ import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel; import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerClient; import org.opencdmp.filetransformerbase.interfaces.FileTransformerClient;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration; import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.opencdmp.filetransformerbase.models.misc.DescriptionImportModel;
import org.opencdmp.filetransformerbase.models.misc.DmpImportModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDescriptionModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
@ -30,9 +34,9 @@ public class FileTransformerRepository implements FileTransformerClient {
} }
@Override @Override
public DmpModel importDmp(FileEnvelopeModel fileEnvelope) { public DmpModel importDmp(DmpImportModel dmpImportModel) {
logger.debug(new MapLogEntry("importDmp").And("fileEnvelope", fileEnvelope)); logger.debug(new MapLogEntry("importDmp").And("fileEnvelope", dmpImportModel.getFile()));
return this.transformerClient.post().uri("/import/dmp").bodyValue(fileEnvelope) return this.transformerClient.post().uri("/import/dmp").bodyValue(dmpImportModel)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(DmpModel.class)).block(); .exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(DmpModel.class)).block();
} }
@ -44,9 +48,9 @@ public class FileTransformerRepository implements FileTransformerClient {
} }
@Override @Override
public DescriptionModel importDescription(FileEnvelopeModel fileEnvelope) { public DescriptionModel importDescription(DescriptionImportModel descriptionImportModel) {
logger.debug(new MapLogEntry("importDescription").And("fileEnvelope", fileEnvelope)); logger.debug(new MapLogEntry("importDescription").And("fileEnvelope", descriptionImportModel.getFile()));
return this.transformerClient.post().uri("/import/description").bodyValue(fileEnvelope) return this.transformerClient.post().uri("/import/description").bodyValue(descriptionImportModel)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(DescriptionModel.class)).block(); .exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(DescriptionModel.class)).block();
} }
@ -57,5 +61,19 @@ public class FileTransformerRepository implements FileTransformerClient {
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<FileTransformerConfiguration>() {})).block(); .exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<FileTransformerConfiguration>() {})).block();
} }
@Override
public PreprocessingDmpModel preprocessingDmp(FileEnvelopeModel fileEnvelopeModel) {
logger.debug(new MapLogEntry("preprocessingDmp").And("fileEnvelope", fileEnvelopeModel));
return this.transformerClient.post().uri("/preprocessing/dmp").bodyValue(fileEnvelopeModel)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(PreprocessingDmpModel.class)).block();
}
@Override
public PreprocessingDescriptionModel preprocessingDescription(FileEnvelopeModel fileEnvelopeModel) {
logger.debug(new MapLogEntry("preprocessingDescription").And("fileEnvelope", fileEnvelopeModel));
return this.transformerClient.post().uri("/preprocessing/description").bodyValue(fileEnvelopeModel)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(PreprocessingDescriptionModel.class)).block();
}
} }

View File

@ -2,8 +2,9 @@ package org.opencdmp.service.filetransformer;
import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.JAXBException;
import org.opencdmp.commonmodels.models.dmp.DmpModel; import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.model.file.RepositoryFileFormat; import org.opencdmp.model.file.RepositoryFileFormat;
import org.springframework.web.multipart.MultipartFile; import org.opencdmp.model.persist.DmpCommonModelConfig;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException; import javax.crypto.IllegalBlockSizeException;
@ -23,6 +24,7 @@ public interface FileTransformerService {
org.opencdmp.model.file.FileEnvelope exportDescription(UUID descriptionId, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException; org.opencdmp.model.file.FileEnvelope exportDescription(UUID descriptionId, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
DmpModel importDmp(MultipartFile file, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, JAXBException; DmpModel importDmp(DmpCommonModelConfig dmpCommonModelConfig) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, JAXBException;
PreprocessingDmpModel preprocessingDmp(UUID fileId, String repositoryId) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException;
} }

View File

@ -1,22 +1,26 @@
package org.opencdmp.service.filetransformer; package org.opencdmp.service.filetransformer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeCacheService; import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeCacheService;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeFilterFunction; import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeFilterFunction;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeModel; import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeModel;
import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.JAXBException;
import org.apache.commons.io.FilenameUtils;
import org.opencdmp.authorization.AuthorizationFlags; import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.Permission; import org.opencdmp.authorization.Permission;
import org.opencdmp.commonmodels.models.FileEnvelopeModel; import org.opencdmp.commonmodels.models.FileEnvelopeModel;
import org.opencdmp.commonmodels.models.description.DescriptionModel; import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel; import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.commonmodels.models.dmpblueprint.DmpBlueprintModel;
import org.opencdmp.commons.JsonHandlingService; import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.StorageType; import org.opencdmp.commons.enums.StorageType;
@ -26,20 +30,28 @@ import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.commons.types.filetransformer.FileTransformerSourceEntity; import org.opencdmp.commons.types.filetransformer.FileTransformerSourceEntity;
import org.opencdmp.commons.types.tenantconfiguration.FileTransformerTenantConfigurationEntity; import org.opencdmp.commons.types.tenantconfiguration.FileTransformerTenantConfigurationEntity;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.StorageFileEntity;
import org.opencdmp.data.TenantConfigurationEntity; import org.opencdmp.data.TenantConfigurationEntity;
import org.opencdmp.event.TenantConfigurationTouchedEvent; import org.opencdmp.event.TenantConfigurationTouchedEvent;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration; import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.opencdmp.filetransformerbase.models.misc.DescriptionImportModel;
import org.opencdmp.filetransformerbase.models.misc.DmpImportModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.model.StorageFile; import org.opencdmp.model.StorageFile;
import org.opencdmp.model.builder.commonmodels.description.DescriptionCommonModelBuilder; import org.opencdmp.model.builder.commonmodels.description.DescriptionCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.descriptiontemplate.DescriptionTemplateCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.dmp.DmpCommonModelBuilder; import org.opencdmp.model.builder.commonmodels.dmp.DmpCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.dmpblueprint.DmpBlueprintCommonModelBuilder;
import org.opencdmp.model.description.Description; import org.opencdmp.model.description.Description;
import org.opencdmp.model.dmp.Dmp; import org.opencdmp.model.dmp.Dmp;
import org.opencdmp.model.dmpblueprint.DmpBlueprint;
import org.opencdmp.model.file.RepositoryFileFormat; import org.opencdmp.model.file.RepositoryFileFormat;
import org.opencdmp.model.persist.DescriptionCommonModelConfig;
import org.opencdmp.model.persist.DmpCommonModelConfig;
import org.opencdmp.model.persist.StorageFilePersist; import org.opencdmp.model.persist.StorageFilePersist;
import org.opencdmp.model.tenantconfiguration.TenantConfiguration; import org.opencdmp.model.tenantconfiguration.TenantConfiguration;
import org.opencdmp.query.DescriptionQuery; import org.opencdmp.query.*;
import org.opencdmp.query.DmpQuery;
import org.opencdmp.query.TenantConfigurationQuery;
import org.opencdmp.service.encryption.EncryptionService; import org.opencdmp.service.encryption.EncryptionService;
import org.opencdmp.service.storage.StorageFileService; import org.opencdmp.service.storage.StorageFileService;
import org.opencdmp.service.tenant.TenantProperties; import org.opencdmp.service.tenant.TenantProperties;
@ -48,8 +60,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.MediaType;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -64,6 +78,7 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Service @Service
public class FileTransformerServiceImpl implements FileTransformerService { public class FileTransformerServiceImpl implements FileTransformerService {
@ -119,9 +134,12 @@ public class FileTransformerServiceImpl implements FileTransformerService {
exchangeFilterFunctions.add(tokenExchangeFilterFunction); exchangeFilterFunctions.add(tokenExchangeFilterFunction);
exchangeFilterFunctions.add(logRequest()); exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse()); exchangeFilterFunctions.add(logResponse());
}).codecs(codecs -> codecs }).codecs(codecs -> {
.defaultCodecs() codecs.defaultCodecs().maxInMemorySize(source.getMaxInMemorySizeInBytes());
.maxInMemorySize(source.getMaxInMemorySizeInBytes()) codecs.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper().registerModule(new JavaTimeModule()), MediaType.APPLICATION_JSON));
codecs.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(new ObjectMapper().registerModule(new JavaTimeModule()), MediaType.APPLICATION_JSON));
}
).build()); ).build());
this.clients.put(repositoryIdByTenant, repository); this.clients.put(repositoryIdByTenant, repository);
return repository; return repository;
@ -295,37 +313,105 @@ public class FileTransformerServiceImpl implements FileTransformerService {
} }
@Override @Override
public DmpModel importDmp(MultipartFile file, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, JAXBException { public DmpModel importDmp(DmpCommonModelConfig dmpCommonModelConfig) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, JAXBException {
this.authorizationService.authorizeForce(Permission.NewDmp); this.authorizationService.authorizeForce(Permission.NewDmp);
if (file == null) return null; StorageFileEntity tempFile = this.queryFactory.query(StorageFileQuery.class).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(dmpCommonModelConfig.getFileId()).first();
if (tempFile == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{dmpCommonModelConfig.getFileId(), StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale()));
//GK: First get the right client //GK: First get the right client
FileTransformerRepository repository = this.getRepository(repositoryId); FileTransformerRepository repository = this.getRepository(dmpCommonModelConfig.getRepositoryId());
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{dmpCommonModelConfig.getRepositoryId(), FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale()));
String name = FilenameUtils.removeExtension(file.getOriginalFilename()); DmpBlueprintQuery dmpBlueprintQuery = this.queryFactory.query(DmpBlueprintQuery.class).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(dmpCommonModelConfig.getBlueprintId());
String extension = FilenameUtils.getExtension(file.getOriginalFilename()); DmpBlueprintModel dmpBlueprintModel = this.builderFactory.builder(DmpBlueprintCommonModelBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(dmpBlueprintQuery.first());
String mimeType = URLConnection.guessContentTypeFromName(file.getOriginalFilename()); if (dmpBlueprintModel == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{dmpCommonModelConfig.getBlueprintId(), DmpBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale()));
DmpImportModel dmpImportModel = new DmpImportModel();
dmpImportModel.setBlueprintModel(dmpBlueprintModel);
if (!this.conventionService.isListNullOrEmpty(dmpCommonModelConfig.getDescriptions())){
List<DescriptionTemplateEntity> descriptionTemplateEntities = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(dmpCommonModelConfig.getDescriptions().stream().map(x -> x.getTemplateId()).distinct().collect(Collectors.toList())).collect();
if (descriptionTemplateEntities == null) throw new MyApplicationException("Description Templates Not Exist!");
List<DescriptionImportModel> descriptionImportModels = new ArrayList<>();
for (DescriptionCommonModelConfig descriptionCommonModelConfig : dmpCommonModelConfig.getDescriptions()) {
DescriptionTemplateEntity descriptionTemplateEntity = descriptionTemplateEntities.stream().filter(x -> x.getId().equals(descriptionCommonModelConfig.getTemplateId())).findFirst().orElse(null);
if (descriptionTemplateEntity != null){
DescriptionTemplateModel descriptionTemplateModel = this.builderFactory.builder(DescriptionTemplateCommonModelBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(descriptionTemplateEntity);
DescriptionImportModel descriptionImportModel = new DescriptionImportModel();
descriptionImportModel.setId(descriptionCommonModelConfig.getId());
descriptionImportModel.setSectionId(descriptionCommonModelConfig.getSectionId());
descriptionImportModel.setDescriptionTemplate(descriptionTemplateModel);
descriptionImportModels.add(descriptionImportModel);
}
}
dmpImportModel.setDescriptions(descriptionImportModels);
}
String originalFileName = tempFile.getName() + (tempFile.getExtension().startsWith(".") ? "" : ".") + tempFile.getExtension();
String mimeType = URLConnection.guessContentTypeFromName(originalFileName);
FileEnvelopeModel fileEnvelope = new FileEnvelopeModel(); FileEnvelopeModel fileEnvelope = new FileEnvelopeModel();
fileEnvelope.setFile(file.getBytes()); fileEnvelope.setFile(this.storageFileService.readAsBytesSafe(dmpCommonModelConfig.getFileId()));
fileEnvelope.setMimeType(mimeType); fileEnvelope.setMimeType(mimeType);
fileEnvelope.setFilename(name + (extension.startsWith(".") ? "" : ".") + extension); fileEnvelope.setFilename(originalFileName);
if (repository.getConfiguration() != null && repository.getConfiguration().isUseSharedStorage()){ if (repository.getConfiguration() != null && repository.getConfiguration().isUseSharedStorage()){
StorageFilePersist storageFilePersist = new StorageFilePersist(); StorageFilePersist storageFilePersist = new StorageFilePersist();
storageFilePersist.setName(name); storageFilePersist.setName(tempFile.getName());
storageFilePersist.setExtension(extension); storageFilePersist.setExtension(tempFile.getExtension());
storageFilePersist.setMimeType(mimeType); storageFilePersist.setMimeType(mimeType);
storageFilePersist.setOwnerId(this.userScope.getUserIdSafe()); storageFilePersist.setOwnerId(this.userScope.getUserIdSafe());
storageFilePersist.setStorageType(StorageType.Transformer); storageFilePersist.setStorageType(StorageType.Transformer);
StorageFile storageFile = this.storageFileService.persistBytes(storageFilePersist, file.getBytes(), new BaseFieldSet(StorageFile._id, StorageFile._fileRef, StorageFile._mimeType, StorageFile._extension, StorageFile._name)); StorageFile storageFile = this.storageFileService.persistBytes(storageFilePersist, fileEnvelope.getFile(), new BaseFieldSet(StorageFile._id, StorageFile._fileRef, StorageFile._mimeType, StorageFile._extension, StorageFile._name));
fileEnvelope.setFileRef(storageFile.getFileRef()); fileEnvelope.setFileRef(storageFile.getFileRef());
} }
return repository.importDmp(fileEnvelope); dmpImportModel.setFile(fileEnvelope);
return repository.importDmp(dmpImportModel);
}
@Override
public PreprocessingDmpModel preprocessingDmp(UUID fileId, String repositoryId) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException {
this.authorizationService.authorizeForce(Permission.NewDmp);
StorageFileEntity tempFile = this.queryFactory.query(StorageFileQuery.class).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(fileId).first();
if (tempFile == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{fileId, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale()));
//GK: First get the right client
FileTransformerRepository repository = this.getRepository(repositoryId);
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{repositoryId, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale()));
String originalFileName = tempFile.getName() + (tempFile.getExtension().startsWith(".") ? "" : ".") + tempFile.getExtension();
String mimeType = URLConnection.guessContentTypeFromName(originalFileName);
FileEnvelopeModel fileEnvelope = new FileEnvelopeModel();
fileEnvelope.setFile(this.storageFileService.readAsBytesSafe(fileId));
fileEnvelope.setMimeType(mimeType);
fileEnvelope.setFilename(originalFileName);
if (repository.getConfiguration() != null && repository.getConfiguration().isUseSharedStorage()){
StorageFilePersist storageFilePersist = new StorageFilePersist();
storageFilePersist.setName(tempFile.getName());
storageFilePersist.setExtension(tempFile.getExtension());
storageFilePersist.setMimeType(mimeType);
storageFilePersist.setOwnerId(this.userScope.getUserIdSafe());
storageFilePersist.setStorageType(StorageType.Transformer);
StorageFile storageFile = this.storageFileService.persistBytes(storageFilePersist, fileEnvelope.getFile(), new BaseFieldSet(StorageFile._id, StorageFile._fileRef, StorageFile._mimeType, StorageFile._extension, StorageFile._name));
fileEnvelope.setFileRef(storageFile.getFileRef());
}
return repository.preprocessingDmp(fileEnvelope);
} }
} }

View File

@ -25,6 +25,7 @@ import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.*; import org.opencdmp.data.*;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.*;
import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEvent; import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEvent;
import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEvent; import org.opencdmp.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEvent;
@ -81,6 +82,7 @@ public class TenantServiceImpl implements TenantService {
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final CurrentPrincipalResolver currentPrincipalResolver; private final CurrentPrincipalResolver currentPrincipalResolver;
private final ClaimExtractor claimExtractor; private final ClaimExtractor claimExtractor;
private final EventBroker eventBroker;
@Autowired @Autowired
@ -91,7 +93,7 @@ public class TenantServiceImpl implements TenantService {
BuilderFactory builderFactory, BuilderFactory builderFactory,
ConventionService conventionService, ConventionService conventionService,
MessageSource messageSource, MessageSource messageSource,
ErrorThesaurusProperties errors, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractor claimExtractor) { ErrorThesaurusProperties errors, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractor claimExtractor, EventBroker eventBroker) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
@ -108,6 +110,7 @@ public class TenantServiceImpl implements TenantService {
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.currentPrincipalResolver = currentPrincipalResolver; this.currentPrincipalResolver = currentPrincipalResolver;
this.claimExtractor = claimExtractor; this.claimExtractor = claimExtractor;
this.eventBroker = eventBroker;
} }
@Override @Override
@ -155,6 +158,8 @@ public class TenantServiceImpl implements TenantService {
this.autoAssignGlobalAdminsToNewTenant(data); this.autoAssignGlobalAdminsToNewTenant(data);
} }
this.eventBroker.emit(new TenantTouchedEvent(data.getId(), data.getCode()));
return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data); return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data);
} }
@ -178,6 +183,7 @@ public class TenantServiceImpl implements TenantService {
tenantUserEntity.setCreatedAt(Instant.now()); tenantUserEntity.setCreatedAt(Instant.now());
tenantUserEntity.setUpdatedAt(Instant.now()); tenantUserEntity.setUpdatedAt(Instant.now());
this.entityManager.persist(tenantUserEntity); this.entityManager.persist(tenantUserEntity);
this.eventBroker.emit(new UserAddedToTenantEvent(tenantUserEntity.getUserId(), tenantUserEntity.getTenantId()));
UserCredentialEntity userCredential = userCredentialEntities.stream().filter(x-> !this.conventionService.isNullOrEmpty(x.getExternalId()) && x.getUserId().equals(userId)).findFirst().orElse(null); UserCredentialEntity userCredential = userCredentialEntities.stream().filter(x-> !this.conventionService.isNullOrEmpty(x.getExternalId()) && x.getUserId().equals(userId)).findFirst().orElse(null);
if (userCredential == null) continue; if (userCredential == null) continue;
@ -193,12 +199,16 @@ public class TenantServiceImpl implements TenantService {
item.setCreatedAt(Instant.now()); item.setCreatedAt(Instant.now());
this.entityManager.persist(item); this.entityManager.persist(item);
keycloakIdsToAddToTenantGroup.add(userCredential.getExternalId()); keycloakIdsToAddToTenantGroup.add(userCredential.getExternalId());
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredential.getId(), userCredential.getExternalId()));
} }
this.entityManager.flush(); this.entityManager.flush();
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) { for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
this.userTouchedIntegrationEventHandler.handle(userId); this.userTouchedIntegrationEventHandler.handle(userId);
this.eventBroker.emit(new UserTouchedEvent(userId));
} }
this.entityManager.flush(); this.entityManager.flush();
@ -214,6 +224,8 @@ public class TenantServiceImpl implements TenantService {
@Override @Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting : {}", id); logger.debug("deleting : {}", id);
TenantEntity data = this.entityManager.find(TenantEntity.class, id);
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.authorizationService.authorizeForce(Permission.DeleteTenant); this.authorizationService.authorizeForce(Permission.DeleteTenant);
@ -222,6 +234,8 @@ public class TenantServiceImpl implements TenantService {
TenantRemovalIntegrationEvent tenantRemovalIntegrationEvent = new TenantRemovalIntegrationEvent(); TenantRemovalIntegrationEvent tenantRemovalIntegrationEvent = new TenantRemovalIntegrationEvent();
tenantRemovalIntegrationEvent.setId(id); tenantRemovalIntegrationEvent.setId(id);
this.tenantRemovalIntegrationEventHandler.handle(tenantRemovalIntegrationEvent); this.tenantRemovalIntegrationEventHandler.handle(tenantRemovalIntegrationEvent);
this.eventBroker.emit(new TenantTouchedEvent(data.getId(), data.getCode()));
} }

View File

@ -33,7 +33,9 @@ import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.scope.user.UserScope; import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.commons.types.actionconfirmation.MergeAccountConfirmationEntity; import org.opencdmp.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
import org.opencdmp.commons.types.actionconfirmation.RemoveCredentialRequestEntity; import org.opencdmp.commons.types.actionconfirmation.RemoveCredentialRequestEntity;
import org.opencdmp.commons.types.notification.*; import org.opencdmp.commons.types.notification.DataType;
import org.opencdmp.commons.types.notification.FieldInfo;
import org.opencdmp.commons.types.notification.NotificationFieldData;
import org.opencdmp.commons.types.reference.DefinitionEntity; import org.opencdmp.commons.types.reference.DefinitionEntity;
import org.opencdmp.commons.types.user.AdditionalInfoEntity; import org.opencdmp.commons.types.user.AdditionalInfoEntity;
import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity; import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity;
@ -41,8 +43,7 @@ import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.*; import org.opencdmp.data.*;
import org.opencdmp.data.tenant.TenantScopedBaseEntity; import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.EventBroker; import org.opencdmp.event.*;
import org.opencdmp.event.UserTouchedEvent;
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
@ -287,6 +288,8 @@ public class UserServiceImpl implements UserService {
this.entityManager.reloadTenantFilters(); this.entityManager.reloadTenantFilters();
} }
this.userRemovalIntegrationEventHandler.handle(id); this.userRemovalIntegrationEventHandler.handle(id);
this.eventBroker.emit(new UserTouchedEvent(id));
} }
//endregion //endregion
@ -407,6 +410,8 @@ public class UserServiceImpl implements UserService {
tenantUserEntity.setCreatedAt(Instant.now()); tenantUserEntity.setCreatedAt(Instant.now());
tenantUserEntity.setUpdatedAt(Instant.now()); tenantUserEntity.setUpdatedAt(Instant.now());
this.entityManager.persist(tenantUserEntity); this.entityManager.persist(tenantUserEntity);
this.eventBroker.emit(new UserAddedToTenantEvent(tenantUserEntity.getUserId(), tenantUserEntity.getTenantId()));
} }
this.entityManager.flush(); this.entityManager.flush();
@ -681,6 +686,8 @@ public class UserServiceImpl implements UserService {
this.syncKeycloakRoles(newUser.getId()); this.syncKeycloakRoles(newUser.getId());
} }
this.eventBroker.emit(new UserTouchedEvent(newUser.getId()));
this.eventBroker.emit(new UserTouchedEvent(userToBeMerge.getId()));
} }
private void syncKeycloakRoles(UUID userId) throws InvalidApplicationException { private void syncKeycloakRoles(UUID userId) throws InvalidApplicationException {
@ -700,6 +707,8 @@ public class UserServiceImpl implements UserService {
if (!this.conventionService.isNullOrEmpty(tenantCode)) this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), tenantCode, userRole.getRole()); if (!this.conventionService.isNullOrEmpty(tenantCode)) this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), tenantCode, userRole.getRole());
} }
} }
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredential.getId(), userCredential.getExternalId()));
} }
} finally { } finally {
@ -714,6 +723,8 @@ public class UserServiceImpl implements UserService {
for (UserCredentialEntity userCredential : userCredentials) { for (UserCredentialEntity userCredential : userCredentials) {
userCredential.setUserId(newUser.getId()); userCredential.setUserId(newUser.getId());
this.entityManager.merge(userCredential); this.entityManager.merge(userCredential);
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredential.getId(), userCredential.getExternalId()));
} }
List<UserContactInfoEntity> userContacts = this.queryFactory.query(UserContactInfoQuery.class).userIds(oldUser.getId()).collect(); List<UserContactInfoEntity> userContacts = this.queryFactory.query(UserContactInfoQuery.class).userIds(oldUser.getId()).collect();
@ -748,8 +759,10 @@ public class UserServiceImpl implements UserService {
if (newTenantUsers.stream().anyMatch(x -> Objects.equals(x.getTenantId(), userTenantUser.getTenantId()))) { if (newTenantUsers.stream().anyMatch(x -> Objects.equals(x.getTenantId(), userTenantUser.getTenantId()))) {
tenantUsersToDelete.add(userTenantUser); tenantUsersToDelete.add(userTenantUser);
} else { } else {
this.eventBroker.emit(new UserRemovedFromTenantEvent(userTenantUser.getUserId(), userTenantUser.getTenantId()));
userTenantUser.setUserId(newUser.getId()); userTenantUser.setUserId(newUser.getId());
this.entityManager.merge(userTenantUser); this.entityManager.merge(userTenantUser);
this.eventBroker.emit(new UserAddedToTenantEvent(userTenantUser.getUserId(), userTenantUser.getTenantId()));
} }
} }
this.deleterFactory.deleter(TenantUserDeleter.class).delete(tenantUsersToDelete); this.deleterFactory.deleter(TenantUserDeleter.class).delete(tenantUsersToDelete);
@ -881,6 +894,9 @@ public class UserServiceImpl implements UserService {
this.keycloakService.removeFromAllGroups(userCredentialEntity.getExternalId()); this.keycloakService.removeFromAllGroups(userCredentialEntity.getExternalId());
this.addToDefaultUserGroups(userCredentialEntity.getExternalId()); this.addToDefaultUserGroups(userCredentialEntity.getExternalId());
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredentialEntity.getId(), userCredentialEntity.getExternalId()));
this.eventBroker.emit(new UserTouchedEvent(userCredentialEntity.getUserId()));
} }
private void addToDefaultUserGroups(String subjectId){ private void addToDefaultUserGroups(String subjectId){

View File

@ -28,6 +28,7 @@ import org.opencdmp.controllers.swagger.SwaggerHelpers;
import org.opencdmp.controllers.swagger.annotation.Swagger400; import org.opencdmp.controllers.swagger.annotation.Swagger400;
import org.opencdmp.controllers.swagger.annotation.Swagger404; import org.opencdmp.controllers.swagger.annotation.Swagger404;
import org.opencdmp.controllers.swagger.annotation.SwaggerErrorResponses; import org.opencdmp.controllers.swagger.annotation.SwaggerErrorResponses;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.model.DescriptionsToBeFinalized; import org.opencdmp.model.DescriptionsToBeFinalized;
import org.opencdmp.model.DmpUser; import org.opencdmp.model.DmpUser;
import org.opencdmp.model.DmpValidationResult; import org.opencdmp.model.DmpValidationResult;
@ -453,23 +454,40 @@ public class DmpController {
return model; return model;
} }
@PostMapping("json/import") @PostMapping("json/preprocessing")
@Operation(summary = "Import a plan from an json file") @Operation(summary = "preprocessing a plan from an json file")
@Transactional @Transactional
public Dmp importJson( public PreprocessingDmpModel preprocessing(
@RequestParam("file") MultipartFile file, @RequestParam("fileId") UUID fileId,
@RequestParam("label") String label, @RequestParam("repositoryId") String repositoryId
@RequestParam("repositoryId") String repositoryId, ) throws InvalidAlgorithmParameterException, JAXBException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
@RequestParam("format") String format, logger.debug(new MapLogEntry("preprocessing dmp" + Dmp.class.getSimpleName()).And("transformerId", repositoryId).And("fileId", fileId));
@Parameter(name = "fields", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fields
) throws InvalidAlgorithmParameterException, JAXBException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException {
logger.debug(new MapLogEntry("import json" + Dmp.class.getSimpleName()).And("transformerId", repositoryId).And("file", file).And("label", label));
Dmp model = this.dmpService.importJson(file, label, repositoryId, format, fields); PreprocessingDmpModel model = this.dmpService.preprocessingDmp(fileId, repositoryId);
this.auditService.track(AuditableAction.Dmp_Import, Map.ofEntries( this.auditService.track(AuditableAction.Dmp_Import, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("transformerId", repositoryId), new AbstractMap.SimpleEntry<String, Object>("transformerId", repositoryId),
new AbstractMap.SimpleEntry<String, Object>("file", file), new AbstractMap.SimpleEntry<String, Object>("fileId", fileId)
));
return model;
}
@PostMapping("json/import")
@Operation(summary = "Import a plan from an json file")
@ValidationFilterAnnotation(validator = DmpCommonModelConfig.DmpCommonModelConfigValidator.ValidatorName, argumentName = "model")
@Transactional
public Dmp importJson(
@RequestBody DmpCommonModelConfig dmpCommonModelConfig,
@Parameter(name = "fields", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fields
) throws InvalidAlgorithmParameterException, JAXBException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException {
logger.debug(new MapLogEntry("import json" + Dmp.class.getSimpleName()).And("transformerId", dmpCommonModelConfig.getRepositoryId()).And("file id", dmpCommonModelConfig.getFileId()).And("label", dmpCommonModelConfig.getLabel()));
Dmp model = this.dmpService.importJson(dmpCommonModelConfig, fields);
this.auditService.track(AuditableAction.Dmp_Import, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("transformerId", dmpCommonModelConfig.getRepositoryId()),
new AbstractMap.SimpleEntry<String, Object>("file id", dmpCommonModelConfig.getFileId()),
new AbstractMap.SimpleEntry<String, Object>("fields", fields) new AbstractMap.SimpleEntry<String, Object>("fields", fields)
)); ));

View File

@ -1,8 +1,8 @@
package org.opencdmp.interceptors.tenant; package org.opencdmp.interceptors.tenant;
import gr.cite.tools.cache.CacheService;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.event.TenantTouchedEvent; import org.opencdmp.event.TenantTouchedEvent;
import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -26,7 +26,7 @@ public class TenantByCodeCacheService extends CacheService<TenantByCodeCacheServ
private String tenantCode; private String tenantCode;
public String getTenantCode() { public String getTenantCode() {
return tenantCode; return this.tenantCode;
} }
public void setTenantCode(String tenantCode) { public void setTenantCode(String tenantCode) {
@ -36,7 +36,7 @@ public class TenantByCodeCacheService extends CacheService<TenantByCodeCacheServ
private UUID tenantId; private UUID tenantId;
public UUID getTenantId() { public UUID getTenantId() {
return tenantId; return this.tenantId;
} }
public void setTenantId(UUID tenantId) { public void setTenantId(UUID tenantId) {
@ -56,8 +56,6 @@ public class TenantByCodeCacheService extends CacheService<TenantByCodeCacheServ
public void handleTenantTouchedEvent(TenantTouchedEvent event) { public void handleTenantTouchedEvent(TenantTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
this.evict(this.buildKey(event.getTenantCode())); this.evict(this.buildKey(event.getTenantCode()));
if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode()))
this.evict(this.buildKey(event.getPreviousTenantCode()));
} }
@Override @Override

View File

@ -1,8 +1,7 @@
package org.opencdmp.interceptors.tenant; package org.opencdmp.interceptors.tenant;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.event.TenantTouchedEvent;
import gr.cite.tools.cache.CacheService; import gr.cite.tools.cache.CacheService;
import org.opencdmp.event.TenantTouchedEvent;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -27,7 +26,7 @@ public class TenantByIdCacheService extends CacheService<TenantByIdCacheService.
private String tenantCode; private String tenantCode;
public String getTenantCode() { public String getTenantCode() {
return tenantCode; return this.tenantCode;
} }
public void setTenantCode(String tenantCode) { public void setTenantCode(String tenantCode) {
@ -37,7 +36,7 @@ public class TenantByIdCacheService extends CacheService<TenantByIdCacheService.
private UUID tenantId; private UUID tenantId;
public UUID getTenantId() { public UUID getTenantId() {
return tenantId; return this.tenantId;
} }
public void setTenantId(UUID tenantId) { public void setTenantId(UUID tenantId) {
@ -45,17 +44,15 @@ public class TenantByIdCacheService extends CacheService<TenantByIdCacheService.
} }
} }
private final ConventionService conventionService;
@Autowired @Autowired
public TenantByIdCacheService(TenantByIdCacheOptions options, ConventionService conventionService) { public TenantByIdCacheService(TenantByIdCacheOptions options) {
super(options); super(options);
this.conventionService = conventionService;
} }
@EventListener @EventListener
public void handleTenantTouchedEvent(TenantTouchedEvent event) { public void handleTenantTouchedEvent(TenantTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) if (event.getTenantId() != null)
this.evict(this.buildKey(event.getTenantId())); this.evict(this.buildKey(event.getTenantId()));
} }

View File

@ -1,8 +1,10 @@
package org.opencdmp.interceptors.user; package org.opencdmp.interceptors.user;
import org.opencdmp.convention.ConventionService;
import gr.cite.tools.cache.CacheService; import gr.cite.tools.cache.CacheService;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.event.UserCredentialTouchedEvent;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashMap; import java.util.HashMap;
@ -12,6 +14,8 @@ import java.util.UUID;
@Service @Service
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> { public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
private final ConventionService conventionService;
public static class UserInterceptorCacheValue { public static class UserInterceptorCacheValue {
public UserInterceptorCacheValue() { public UserInterceptorCacheValue() {
@ -24,7 +28,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
public String getSubjectId() { public String getSubjectId() {
return subjectId; return this.subjectId;
} }
public void setSubjectId(String subjectId) { public void setSubjectId(String subjectId) {
@ -38,7 +42,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
private List<String> externalProviderNames; private List<String> externalProviderNames;
public UUID getUserId() { public UUID getUserId() {
return userId; return this.userId;
} }
public void setUserId(UUID userId) { public void setUserId(UUID userId) {
@ -46,7 +50,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
} }
public List<String> getRoles() { public List<String> getRoles() {
return roles; return this.roles;
} }
public void setRoles(List<String> roles) { public void setRoles(List<String> roles) {
@ -54,7 +58,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
} }
public String getProviderEmail() { public String getProviderEmail() {
return providerEmail; return this.providerEmail;
} }
public void setProviderEmail(String providerEmail) { public void setProviderEmail(String providerEmail) {
@ -62,7 +66,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
} }
public List<String> getExternalProviderNames() { public List<String> getExternalProviderNames() {
return externalProviderNames; return this.externalProviderNames;
} }
public void setExternalProviderNames(List<String> externalProviderNames) { public void setExternalProviderNames(List<String> externalProviderNames) {
@ -70,10 +74,17 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
} }
} }
@EventListener
public void handleTenantTouchedEvent(UserCredentialTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getSubjectId()))
this.evict(this.buildKey(event.getSubjectId()));
}
@Autowired @Autowired
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) { public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
super(options); super(options);
this.conventionService = conventionService;
} }
@Override @Override

View File

@ -43,7 +43,7 @@ cache:
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 30 expireAfterWriteSeconds: 20
- names: [ "fileTransformerConfigById" ] - names: [ "fileTransformerConfigById" ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
@ -67,25 +67,25 @@ cache:
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 30 expireAfterWriteSeconds: 20
- names: [ tenantById ] - names: [ tenantById ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 60 expireAfterWriteSeconds: 20
- names: [ userAllowedTenant ] - names: [ userAllowedTenant ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 60 expireAfterWriteSeconds: 20
- names: [ userTenantRoles ] - names: [ userTenantRoles ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 60 expireAfterWriteSeconds: 20
mapCaches: mapCaches:
userBySubjectId: userBySubjectId:
name: userBySubjectId name: userBySubjectId

View File

@ -677,6 +677,11 @@ permissions:
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
BrowseExternalReference:
roles: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: true
EditReference: EditReference:
roles: roles:
- Admin - Admin

View File

@ -0,0 +1,14 @@
import { Guid } from "@common/types/guid";
//preprocessing
export interface PreprocessingDescriptionModel {
id: string;
label: string;
}
// rda config
export interface DescriptionCommonModelConfig {
id: string;
sectionId: Guid;
templateId: Guid;
}

View File

@ -0,0 +1,18 @@
import { Guid } from "@common/types/guid";
import { DescriptionCommonModelConfig, PreprocessingDescriptionModel } from "../description/description-import";
// preprocessing
export interface PreprocessingDmpModel {
label: string;
blueprintId: Guid;
preprocessingDescriptionModels: PreprocessingDescriptionModel[];
}
// rda config
export interface DmpCommonModelConfig {
fileId: Guid;
label: string;
blueprintId: Guid;
repositoryId: string;
descriptions: DescriptionCommonModelConfig[];
}

View File

@ -1,7 +1,7 @@
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { IsActive } from '@app/core/common/enum/is-active.enum'; import { IsActive } from '@app/core/common/enum/is-active.enum';
import { DmpBlueprint, DmpBlueprintDefinitionSection, DmpBlueprintPersist, NewVersionDmpBlueprintPersist } from '@app/core/model/dmp-blueprint/dmp-blueprint'; import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection, DmpBlueprintPersist, NewVersionDmpBlueprintPersist } from '@app/core/model/dmp-blueprint/dmp-blueprint';
import { DmpBlueprintLookup } from '@app/core/query/dmp-blueprint.lookup'; import { DmpBlueprintLookup } from '@app/core/query/dmp-blueprint.lookup';
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
@ -18,13 +18,15 @@ import { BaseHttpV2Service } from '../http/base-http-v2.service';
import { DmpBlueprintStatus } from '@app/core/common/enum/dmp-blueprint-status'; import { DmpBlueprintStatus } from '@app/core/common/enum/dmp-blueprint-status';
import { error } from 'console'; import { error } from 'console';
import { DmpBlueprintVersionStatus } from '@app/core/common/enum/dmp-blueprint-version-status'; import { DmpBlueprintVersionStatus } from '@app/core/common/enum/dmp-blueprint-version-status';
import { TranslateService } from '@ngx-translate/core';
@Injectable() @Injectable()
export class DmpBlueprintService { export class DmpBlueprintService {
private headers = new HttpHeaders(); private headers = new HttpHeaders();
constructor(private http: BaseHttpV2Service, private httpClient: HttpClient, private configurationService: ConfigurationService, private filterService: FilterService) { constructor(private http: BaseHttpV2Service, private httpClient: HttpClient, private configurationService: ConfigurationService, private filterService: FilterService, private language: TranslateService,
) {
} }
private get apiBase(): string { return `${this.configurationService.server}dmp-blueprint`; } private get apiBase(): string { return `${this.configurationService.server}dmp-blueprint`; }
@ -141,6 +143,41 @@ export class DmpBlueprintService {
return lookup; return lookup;
} }
// Finalized Blueprint with definitions Single AutoComplete
singleAutocompleteBlueprintConfiguration: SingleAutoCompleteConfiguration = {
initialItems: (data?: any) => this.query(this.buildAutocompleteWithDefinitonLookup(null, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteWithDefinitonLookup(searchQuery, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteWithDefinitonLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
displayFn: (item: DmpBlueprint) => item.label,
subtitleFn: (item: DmpBlueprint) => this.language.instant('DMP-EDITOR.FIELDS.DMP-BLUEPRINT-VERSION') + ' '+ item.version,
titleFn: (item: DmpBlueprint) => item.label,
valueAssign: (item: DmpBlueprint) => item.id,
};
public buildAutocompleteWithDefinitonLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpBlueprintStatus[]): DmpBlueprintLookup {
const lookup: DmpBlueprintLookup = new DmpBlueprintLookup();
lookup.page = { size: 100, offset: 0 };
if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; }
if (ids && ids.length > 0) { lookup.ids = ids; }
lookup.isActive = [IsActive.Active];
lookup.statuses = statuses;
lookup.project = {
fields: [
nameof<DmpBlueprint>(x => x.id),
nameof<DmpBlueprint>(x => x.label),
nameof<DmpBlueprint>(x => x.version),
[nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.id)].join('.'),
[nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.label)].join('.'),
[nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.hasTemplates)].join('.'),
[nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.descriptionTemplates), nameof<DescriptionTemplatesInSection>(x => x.descriptionTemplateGroupId)].join('.'),
]
};
lookup.order = { items: [nameof<DmpBlueprint>(x => x.label)] };
lookup.versionStatuses = [DmpBlueprintVersionStatus.Previous, DmpBlueprintVersionStatus.Current];
if (like) { lookup.like = this.filterService.transformLike(like); }
return lookup;
}
// //
// //
// UI Helpers // UI Helpers

View File

@ -20,6 +20,7 @@ import { AuthService } from '../auth/auth.service';
import { ConfigurationService } from '../configuration/configuration.service'; import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service'; import { BaseHttpV2Service } from '../http/base-http-v2.service';
import { DmpValidationResult } from '@app/ui/dmp/dmp-finalize-dialog/dmp-finalize-dialog.component'; import { DmpValidationResult } from '@app/ui/dmp/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { DmpCommonModelConfig, PreprocessingDmpModel } from '@app/core/model/dmp/dmp-import';
@Injectable() @Injectable()
export class DmpService { export class DmpService {
@ -197,26 +198,25 @@ export class DmpService {
catchError((error: any) => throwError(error)));; catchError((error: any) => throwError(error)));;
} }
uploadJson(file: File, label: string, repositoryId: string, format: string, reqFields: string[] = []): Observable<Dmp> { preprocessingDmp(fileId: Guid, repositoryId: string): Observable<PreprocessingDmpModel> {
const url = `${this.apiBase}/json/import`; const url = `${this.apiBase}/json/preprocessing`;
const params = new BaseHttpParams(); const params = new BaseHttpParams();
params.interceptorContext = { params.interceptorContext = {
excludedInterceptors: [InterceptorType.JSONContentType] excludedInterceptors: [InterceptorType.JSONContentType]
}; };
const formData = new FormData(); const formData = new FormData();
formData.append('file', file); formData.append('fileId', fileId.toString());
formData.append('label', label);
formData.append('repositoryId', repositoryId); formData.append('repositoryId', repositoryId);
formData.append('format', format);
if (reqFields.length > 0){ return this.http.post<PreprocessingDmpModel>(url, formData, { params: params }).pipe(catchError((error: any) => throwError(error)));
for (var i = 0; i < reqFields.length; i++) {
formData.append('field[]', reqFields[i]);
}
} }
return this.http.post<Dmp>(url, formData, { params: params }).pipe(catchError((error: any) => throwError(error))); uploadJson(item: DmpCommonModelConfig, reqFields: string[] = []): Observable<Dmp> {
const url = `${this.apiBase}/json/import`;
return this.http.post<Dmp>(url, item).pipe(catchError((error: any) => throwError(error)));
} }
// //

View File

@ -79,8 +79,8 @@ export class StartNewDmpDialogComponent extends BaseComponent {
}, },
(error) => this.onCallbackImportFail(error.error) (error) => this.onCallbackImportFail(error.error)
); );
} else if (file?.type.includes('/json')){ } else if (file?.type.includes('/json') && result.dmpCommonModelConfig){
this.dmpService.uploadJson(result.fileList[0], result.dmpTitle, 'rda-file-transformer', 'json') this.dmpService.uploadJson(result.dmpCommonModelConfig)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe( .subscribe(
(complete) => { (complete) => {

View File

@ -0,0 +1,131 @@
import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
import { BackendErrorValidator } from "@common/forms/validation/custom-validator";
import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model";
import { Validation, ValidationContext } from "@common/forms/validation/validation-context";
import { Guid } from "@common/types/guid";
import { DmpCommonModelConfig, PreprocessingDmpModel } from "@app/core/model/dmp/dmp-import";
import { DescriptionCommonModelConfig, PreprocessingDescriptionModel } from "@app/core/model/description/description-import";
export class DmpImportRdaConfigEditorModel implements DmpCommonModelConfig{
fileId: Guid;
label: string;
blueprintId: Guid;
repositoryId: string = 'rda-file-transformer';
descriptions: DescriptionImportRdaConfigEditorModel[] = [];
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
constructor() { }
fromModel(item: PreprocessingDmpModel, fileId: Guid): DmpImportRdaConfigEditorModel {
this.fileId = fileId;
if (item){
this.label = item.label + '.json';
if (item.preprocessingDescriptionModels?.length > 0) {
item.preprocessingDescriptionModels.forEach(x => {
this.descriptions.push(new DescriptionImportRdaConfigEditorModel(this.validationErrorModel).fromModel(x));
})
}
}
return this;
}
buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup {
if (context == null) { context = this.createValidationContext(); }
return this.formBuilder.group({
fileId: [{ value: this.fileId, disabled: disabled }, context.getValidation('fileId').validators],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators],
blueprintId: [{ value: this.blueprintId, disabled: disabled }, context.getValidation('blueprintId').validators],
repositoryId: [{ value: this.repositoryId, disabled: disabled }, context.getValidation('repositoryId').validators],
descriptions: this.formBuilder.array(
(this.descriptions ?? []).map(
(item, index) => item.buildForm({
rootPath: `descriptions[${index}].`,
disabled: disabled
})
), context.getValidation('descriptions').validators
),
});
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
const baseValidationArray: Validation[] = new Array<Validation>();
baseValidationArray.push({ key: 'fileId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'fileId')] });
baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
baseValidationArray.push({ key: 'blueprintId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'blueprintId')] });
baseValidationArray.push({ key: 'repositoryId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'repositoryId')] });
baseValidationArray.push({ key: 'descriptions', validators: [BackendErrorValidator(this.validationErrorModel, 'descriptions')] });
baseContext.validation = baseValidationArray;
return baseContext;
}
}
export class DescriptionImportRdaConfigEditorModel implements DescriptionCommonModelConfig {
id: string;
sectionId: Guid;
templateId: Guid;
label: string;
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
constructor(
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel()
) { }
fromModel(item: PreprocessingDescriptionModel): DescriptionImportRdaConfigEditorModel {
if (item) {
this.id = item.id;
this.label = item.label;
}
return this;
}
buildForm(params?: {
context?: ValidationContext,
disabled?: boolean,
rootPath?: string
}): UntypedFormGroup {
let { context = null, disabled = false, rootPath } = params ?? {}
if (context == null) {
context = DescriptionImportRdaConfigEditorModel.createValidationContext({
validationErrorModel: this.validationErrorModel,
rootPath
});
}
return this.formBuilder.group({
id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
sectionId: [{ value: this.sectionId, disabled: disabled }, context.getValidation('sectionId').validators],
templateId: [{ value: this.templateId, disabled: disabled }, context.getValidation('templateId').validators],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators],
});
}
static createValidationContext(params: {
rootPath?: string,
validationErrorModel: ValidationErrorModel
}): ValidationContext {
const { rootPath = '', validationErrorModel } = params;
const baseContext: ValidationContext = new ValidationContext();
const baseValidationArray: Validation[] = new Array<Validation>();
baseValidationArray.push({ key: 'id', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}id`)] });
baseValidationArray.push({ key: 'sectionId', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}descriptionId`)] });
baseValidationArray.push({ key: 'templateId', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}blueprintSectionId`)] });
baseValidationArray.push({ key: 'label', validators: [] });
baseContext.validation = baseValidationArray;
return baseContext;
}
}

View File

@ -9,8 +9,8 @@
</div> </div>
<div class=""> <div class="">
<div class="upload-form col-12 pr-0 pl-0"> <div class="upload-form col-12 pr-0 pl-0">
<mat-form-field class="w-100"> <mat-form-field class="w-100" *ngIf="files?.length == 0 || files[0].type.includes('/xml')">
<input class="uploadInput" [(ngModel)]="dmpTitle" matInput placeholder="{{'DMP-UPLOAD.PLACEHOLDER' | translate}}" name="uploadFileInput"> <input [(ngModel)]="dmpTitle" matInput placeholder="{{'DMP-UPLOAD.PLACEHOLDER' | translate}}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-12 pr-0 pl-0"> <div class="col-12 pr-0 pl-0">
@ -30,14 +30,42 @@
<input class="hidden" #fileInput type="file" onClick="this.form.reset()" (change)="uploadFile($event)" accept="text/xml, application/json"> <input class="hidden" #fileInput type="file" onClick="this.form.reset()" (change)="uploadFile($event)" accept="text/xml, application/json">
</form> </form>
</div> </div>
<!-- <div class="upload-form col-sm-12 col-md-12"> <div class="upload-form col-12 pr-0 pl-0" *ngIf="formGroup == null && files.length > 0 && files[0].type.includes('/json')">
<mat-form-field> {{ 'DMP-UPLOAD.ANALYZING-FILE' | translate }}
<mat-label>{{'DMP-EDITOR.FIELDS.DATASET-TEMPLATES' | translate}}</mat-label> <b class="fa fa-spinner fa-spin" ></b>
<app-multiple-auto-complete [(ngModel)]="dmpBlueprints" [configuration]="profilesAutoCompleteConfiguration" (optionActionClicked)="onPreviewTemplate($event)"> </div>
<app-multiple-auto-complete required='true' [(ngModel)]="dmpBlueprints" placeholder="{{'DMP-EDITOR.FIELDS.DATASET-TEMPLATES' | translate}}" [configuration]="profilesAutoCompleteConfiguration" (optionActionClicked)="onPreviewTemplate($event)"> <div class="upload-form col-12 pr-0 pl-0" *ngIf="formGroup && files.length > 0 && files[0].type.includes('/json')">
</app-multiple-auto-complete> <mat-form-field class="w-100">
<input [formControl]="formGroup.get('label')" matInput required="true" placeholder="{{'DMP-UPLOAD.PLACEHOLDER' | translate}}">
</mat-form-field> </mat-form-field>
</div> --> <mat-form-field class="w-100">
<app-single-auto-complete [required]="true" [formControl]="formGroup.get('blueprintId')" placeholder="{{'DMP-UPLOAD.FIELDS.BLUEPRINT-PLACEHOLDER' | translate}}" [configuration]="dmpBlueprintService.singleAutocompleteBlueprintConfiguration" (optionSelected)="selectedBlueprintChanged($event)">
</app-single-auto-complete>
</mat-form-field>
<ng-container *ngIf="formGroup.get('blueprintId').value">
<div *ngFor="let description of formGroup.get('descriptions').controls; let descriptionIndex=index;" class="row mb-3">
<span *ngIf="description.get('label').value" style="font-size: 1rem;">
{{ description.get('label').value }}
</span>
<mat-form-field class="w-100">
<mat-label>{{'DMP-UPLOAD.FIELDS.DESCRIPTION-TEMPLATE' | translate}}</mat-label>
<app-single-auto-complete required="true" placeholder="{{'DMP-UPLOAD.FIELDS.DESCRIPTION-TEMPLATE-PLACHOLDER' | translate}}" [formControl]="description.get('templateId')" [configuration]="descriptionTemplateSingleAutocompleteConfiguration"></app-single-auto-complete>
<mat-error *ngIf="description.get('templateId').hasError('backendError')">{{description.get('templateId').getError('backendError').message}}</mat-error>
<mat-error *ngIf="description.get('templateId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="w-100">
<mat-label>{{'DMP-UPLOAD.FIELDS.SECTION' | translate}}</mat-label>
<mat-select [formControl]="description.get('sectionId')" placeholder="{{'DMP-UPLOAD.FIELDS.SECTION-PLACEHOLDER' | translate}}">
<mat-option *ngFor="let section of selectedBlueprintSections" [value]="section.id">
<span style="font-size: 1rem;">
{{ section.label }}
</span>
</mat-option>
</mat-select>
</mat-form-field>
</div>
</ng-container>
</div>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div></div> <div></div>
@ -46,7 +74,7 @@
<button mat-button type="button" class="cancel-btn" (click)="cancel()">{{'DMP-UPLOAD.ACTIONS.CANCEL' | translate}}</button> <button mat-button type="button" class="cancel-btn" (click)="cancel()">{{'DMP-UPLOAD.ACTIONS.CANCEL' | translate}}</button>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<button mat-button type="button" (click)="confirm()" [disabled]="data.fileList.length === 0 || files.length === 0" class="next-btn">{{'DMP-UPLOAD.ACTIONS.IMPORT' | translate}}</button> <button mat-button type="button" (click)="confirm()" [disabled]="disableConfirmButton()" class="next-btn">{{'DMP-UPLOAD.ACTIONS.IMPORT' | translate}}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,12 +2,22 @@ import { HttpClient } from '@angular/common/http';
import { Component, Inject } from '@angular/core'; import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { DescriptionTemplate } from '@app/core/model/description-template/description-template'; import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
import { DmpBlueprint, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
import { DmpBlueprintService } from '@app/core/services/dmp/dmp-blueprint.service';
import { DmpService } from '@app/core/services/dmp/dmp.service'; import { DmpService } from '@app/core/services/dmp/dmp.service';
import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service';
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { Observable } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators';
import { map } from 'rxjs/operators'; import { DmpImportRdaConfigEditorModel } from './dmp-common-model-config.editor.model';
import { UntypedFormArray, UntypedFormGroup } from '@angular/forms';
import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service';
import { FormService } from '@common/forms/form-service';
import { DmpCommonModelConfig } from '@app/core/model/dmp/dmp-import';
import { StorageFileService } from '@app/core/services/storage-file/storage-file.service';
import { IsActive } from '@notification-service/core/enum/is-active.enum';
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'dmp-upload-dialog', selector: 'dmp-upload-dialog',
@ -18,13 +28,17 @@ export class DmpUploadDialogComponent extends BaseComponent {
dmpTitle: string; dmpTitle: string;
dmpBlueprints: any[] = []; dmpBlueprints: any[] = [];
files: File[] = []; files: File[] = [];
selectedBlueprintSections: DmpBlueprintDefinitionSection[];
formGroup: UntypedFormGroup;
profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { descriptionTemplateSingleAutocompleteConfiguration: SingleAutoCompleteConfiguration = {
filterFn: this.filterProfiles.bind(this), initialItems: (data?: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active])).pipe(map(x => x.items)),
initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), filterFn: (searchQuery: string, data?: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active], searchQuery)).pipe(map(x => x.items)),
displayFn: (item) => item['label'], getSelectedItem: (selectedItem: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, [selectedItem])).pipe(map(x => x.items[0])),
titleFn: (item) => item['label'], displayFn: (item: DescriptionTemplate) => item.label,
subtitleFn: (item) => item['description'], titleFn: (item: DescriptionTemplate) => item.label,
subtitleFn: (item: DescriptionTemplate) => item.description,
valueAssign: (item: DescriptionTemplate) => item.id,
popupItemActionIcon: 'visibility' popupItemActionIcon: 'visibility'
}; };
@ -35,6 +49,13 @@ export class DmpUploadDialogComponent extends BaseComponent {
private dialog: MatDialog, private dialog: MatDialog,
private httpClient: HttpClient, private httpClient: HttpClient,
private analyticsService: AnalyticsService, private analyticsService: AnalyticsService,
private formService: FormService,
public descriptionTemplateService: DescriptionTemplateService,
public dmpBlueprintService: DmpBlueprintService,
private dmpService: DmpService,
private storageFileStorage: StorageFileService,
private uiNotificationService: UiNotificationService,
private language: TranslateService,
@Inject(MAT_DIALOG_DATA) public data: any, @Inject(MAT_DIALOG_DATA) public data: any,
) { ) {
@ -58,10 +79,28 @@ export class DmpUploadDialogComponent extends BaseComponent {
this.data.success = true; this.data.success = true;
this.data.dmpTitle = this.dmpTitle; this.data.dmpTitle = this.dmpTitle;
this.data.dmpBlueprints = this.dmpBlueprints; this.data.dmpBlueprints = this.dmpBlueprints;
if (this.files.length > 0 && this.files[0].type.includes('/json') && this.formGroup){
this.formService.removeAllBackEndErrors(this.formGroup);
this.formService.touchAllFormFields(this.formGroup);
if (this.formGroup.valid){
this.data.dmpCommonModelConfig = this.formService.getValue(this.formGroup.value) as DmpCommonModelConfig;
this.data.dmpCommonModelConfig.file = this.files[0];
} else {
return;
}
}
this.dialogRef.close(this.data); this.dialogRef.close(this.data);
} }
disableConfirmButton(){
if (this.data.fileList.length === 0 || this.files.length === 0) return true;
if (this.files.length > 0 && this.files[0].type.includes('/json') && this.formGroup == null) return true;
return false;
}
uploadFile(event) { uploadFile(event) {
this.formGroup = null;
const fileList: FileList = event.target.files const fileList: FileList = event.target.files
this.data.fileList = fileList; this.data.fileList = fileList;
if (this.data.fileList.length > 0) { if (this.data.fileList.length > 0) {
@ -71,6 +110,28 @@ export class DmpUploadDialogComponent extends BaseComponent {
this.files.splice(0, 1); this.files.splice(0, 1);
} }
this.files.push(...event.target.files); this.files.push(...event.target.files);
if (this.files.length > 0 && this.files[0].type.includes('/json')){
this.storageFileStorage.uploadTempFiles(fileList[0])
.pipe(takeUntil(this._destroyed))
.subscribe(
(storageFile) => {
if (storageFile.length >0 ){
this.dmpService.preprocessingDmp(storageFile[0].id, 'rda-file-transformer')
.pipe(takeUntil(this._destroyed))
.subscribe(
(preprocessingData) => {
this.formGroup = new DmpImportRdaConfigEditorModel().fromModel(preprocessingData, storageFile[0].id,).buildForm();
},
(error) => this.onCallbackEror(error.error)
);
}
},
(error) => this.onCallbackEror(error.error)
);
}
} }
selectFile(event) { selectFile(event) {
@ -88,19 +149,25 @@ export class DmpUploadDialogComponent extends BaseComponent {
onRemove(event) { onRemove(event) {
this.files.splice(0, 1); this.files.splice(0, 1);
this.dmpTitle = null; this.dmpTitle = null;
this.formGroup = null;
} }
filterProfiles(value: string): Observable<DescriptionTemplate[]> { selectedBlueprintChanged(item: DmpBlueprint): void{
// TODO refactor this.selectedBlueprintSections = item.definition?.sections?.filter(x => x.hasTemplates) || null;
// const request = new DataTableRequest<DatasetProfileCriteria>(null, null, { fields: ['+label'] }); if (this.formGroup){
// const criteria = new DatasetProfileCriteria(); const descriptionsFormArray = this.formGroup.get('descriptions') as UntypedFormArray;
// criteria.like = value; descriptionsFormArray.controls.forEach( control =>{
// request.criteria = criteria; control.get('sectionId').patchValue(null);
// return this._service.searchDmpBlueprints(request); })
return null; }
} }
hasFile(): boolean { hasFile(): boolean {
return this.files && this.files.length > 0; return this.files && this.files.length > 0;
} }
private onCallbackEror(error: any) {
this.uiNotificationService.snackBarNotification(this.language.instant(error.error), SnackBarNotificationLevel.Error);
this.close();
}
} }

View File

@ -4,12 +4,16 @@ import { CommonFormsModule } from '@common/forms/common-forms.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { NgxDropzoneModule } from 'ngx-dropzone'; import { NgxDropzoneModule } from 'ngx-dropzone';
import { DmpUploadDialogComponent } from './dmp-upload-dialog.component'; import { DmpUploadDialogComponent } from './dmp-upload-dialog.component';
import { ReactiveFormsModule } from '@angular/forms';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
@NgModule({ @NgModule({
imports: [ imports: [
CommonUiModule, CommonUiModule,
CommonFormsModule, CommonFormsModule,
FormattingModule, FormattingModule,
ReactiveFormsModule,
AutoCompleteModule,
NgxDropzoneModule NgxDropzoneModule
], ],
declarations: [ declarations: [

View File

@ -699,6 +699,14 @@
"DMP-UPLOAD": { "DMP-UPLOAD": {
"TITLE": "Import Plan", "TITLE": "Import Plan",
"UPLOAD-SUCCESS": "Import was Successful", "UPLOAD-SUCCESS": "Import was Successful",
"ANALYZING-FILE": "Analyzing file",
"FIELDS": {
"BLUEPRINT-PLACEHOLDER": "Select Plan Blueprint",
"DESCRIPTION-TEMPLATE": "Description Template",
"DESCRIPTION-TEMPLATE-PLACHOLDER": "Select description template",
"SECTION": "Plan Section",
"SECTION-PLACEHOLDER": "Select plan section"
},
"ACTIONS": { "ACTIONS": {
"IMPORT": "Import", "IMPORT": "Import",
"CANCEL": "Cancel" "CANCEL": "Cancel"

View File

@ -1,4 +1,4 @@
import { AfterContentChecked, Directive } from "@angular/core"; import { AfterContentChecked, Directive, Optional } from "@angular/core";
import { AbstractControl } from "@angular/forms"; import { AbstractControl } from "@angular/forms";
import { MatFormField } from "@angular/material/form-field"; import { MatFormField } from "@angular/material/form-field";
import { MatInput } from "@angular/material/input"; import { MatInput } from "@angular/material/input";
@ -15,9 +15,10 @@ import { MarkedValidatorFn } from "./validation/custom-validator";
}) })
export class ReactiveAsteriskDirective implements AfterContentChecked { export class ReactiveAsteriskDirective implements AfterContentChecked {
private readonly requiredValidatornames = ['RequiredWithVisibilityRulesValidator', 'required']; private readonly requiredValidatornames = ['RequiredWithVisibilityRulesValidator', 'required'];
constructor(private matFormField: MatFormField) { } constructor(@Optional() private matFormField: MatFormField) { }
ngAfterContentChecked() { ngAfterContentChecked() {
if (!this.matFormField) return;
const ctrl = this.matFormField._control; const ctrl = this.matFormField._control;
const abstractControl = ctrl?.ngControl?.control; const abstractControl = ctrl?.ngControl?.control;
const validators = (abstractControl as AbstractControl & { _rawValidators: MarkedValidatorFn[] })?._rawValidators; const validators = (abstractControl as AbstractControl & { _rawValidators: MarkedValidatorFn[] })?._rawValidators;

View File

@ -56,8 +56,6 @@ public class TenantByCodeCacheService extends CacheService<TenantByCodeCacheServ
public void handleTenantTouchedEvent(TenantTouchedEvent event) { public void handleTenantTouchedEvent(TenantTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
this.evict(this.buildKey(event.getTenantCode())); this.evict(this.buildKey(event.getTenantCode()));
if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode()))
this.evict(this.buildKey(event.getPreviousTenantCode()));
} }
@Override @Override

View File

@ -55,7 +55,7 @@ public class TenantByIdCacheService extends CacheService<TenantByIdCacheService.
@EventListener @EventListener
public void handleTenantTouchedEvent(TenantTouchedEvent event) { public void handleTenantTouchedEvent(TenantTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode())) if (event.getTenantId() != null)
this.evict(this.buildKey(event.getTenantId())); this.evict(this.buildKey(event.getTenantId()));
} }

View File

@ -1,8 +1,10 @@
package gr.cite.notification.web.scope.user; package gr.cite.notification.web.scope.user;
import gr.cite.notification.convention.ConventionService; import gr.cite.notification.convention.ConventionService;
import gr.cite.notification.event.UserCredentialTouchedEvent;
import gr.cite.tools.cache.CacheService; import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashMap; import java.util.HashMap;
@ -10,6 +12,7 @@ import java.util.UUID;
@Service @Service
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> { public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
private final ConventionService conventionService;
public static class UserInterceptorCacheValue { public static class UserInterceptorCacheValue {
@ -42,10 +45,17 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
} }
} }
@EventListener
public void handleTenantTouchedEvent(UserCredentialTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getSubjectId()))
this.evict(this.buildKey(event.getSubjectId()));
}
@Autowired @Autowired
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) { public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService1) {
super(options); super(options);
this.conventionService = conventionService1;
} }
@Override @Override

View File

@ -13,13 +13,13 @@ cache:
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 600 expireAfterWriteSeconds: 20
- names: [ tenantById ] - names: [ tenantById ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 600 expireAfterWriteSeconds: 20
- names: [ userBySubjectId ] - names: [ userBySubjectId ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
@ -31,13 +31,13 @@ cache:
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 300 expireAfterWriteSeconds: 20
- names: [ formattingUserProfile ] - names: [ formattingUserProfile ]
allowNullValues: true allowNullValues: true
initialCapacity: 100 initialCapacity: 100
maximumSize: 500 maximumSize: 500
enableRecordStats: false enableRecordStats: false
expireAfterWriteSeconds: 60 expireAfterWriteSeconds: 20
mapCaches: mapCaches:
apiKey: apiKey:
name: apikey name: apikey

View File

@ -37,4 +37,8 @@ public class EventBroker {
this.applicationEventPublisher.publishEvent(event); this.applicationEventPublisher.publishEvent(event);
} }
public void emit(UserCredentialTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}
} }

View File

@ -6,15 +6,13 @@ public class TenantTouchedEvent {
public TenantTouchedEvent() { public TenantTouchedEvent() {
} }
public TenantTouchedEvent(UUID tenantId, String tenantCode, String previousTenantCode) { public TenantTouchedEvent(UUID tenantId, String tenantCode) {
this.tenantId = tenantId; this.tenantId = tenantId;
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
this.previousTenantCode = previousTenantCode;
} }
private UUID tenantId; private UUID tenantId;
private String tenantCode; private String tenantCode;
private String previousTenantCode;
public UUID getTenantId() { public UUID getTenantId() {
return tenantId; return tenantId;
@ -31,12 +29,4 @@ public class TenantTouchedEvent {
public void setTenantCode(String tenantCode) { public void setTenantCode(String tenantCode) {
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
} }
public String getPreviousTenantCode() {
return previousTenantCode;
}
public void setPreviousTenantCode(String previousTenantCode) {
this.previousTenantCode = previousTenantCode;
}
} }

View File

@ -0,0 +1,33 @@
package gr.cite.notification.event;
import java.util.UUID;
public class UserCredentialTouchedEvent {
public UserCredentialTouchedEvent() {
}
public UserCredentialTouchedEvent(UUID id, String subjectId) {
this.id = id;
this.subjectId = subjectId;
}
private UUID id;
public UUID getId() {
return this.id;
}
public void setId(UUID id) {
this.id = id;
}
private String subjectId;
public String getSubjectId() {
return this.subjectId;
}
public void setSubjectId(String subjectId) {
this.subjectId = subjectId;
}
}

View File

@ -6,15 +6,11 @@ public class UserTouchedEvent {
public UserTouchedEvent() { public UserTouchedEvent() {
} }
public UserTouchedEvent(UUID userId, String subjectId, String previousSubjectId) { public UserTouchedEvent(UUID userId) {
this.userId = userId; this.userId = userId;
this.subjectId = subjectId;
this.previousSubjectId = previousSubjectId;
} }
private UUID userId; private UUID userId;
private String subjectId;
private String previousSubjectId;
public UUID getUserId() { public UUID getUserId() {
return userId; return userId;
@ -24,19 +20,4 @@ public class UserTouchedEvent {
this.userId = userId; this.userId = userId;
} }
public String getSubjectId() {
return subjectId;
}
public void setSubjectId(String subjectId) {
this.subjectId = subjectId;
}
public String getPreviousSubjectId() {
return previousSubjectId;
}
public void setPreviousSubjectId(String previousSubjectId) {
this.previousSubjectId = previousSubjectId;
}
} }

View File

@ -3,6 +3,9 @@ package gr.cite.notification.model.deleter;
import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.data.TenantEntity; import gr.cite.notification.data.TenantEntity;
import gr.cite.notification.data.TenantEntityManager; import gr.cite.notification.data.TenantEntityManager;
import gr.cite.notification.event.EventBroker;
import gr.cite.notification.event.TenantTouchedEvent;
import gr.cite.notification.event.UserRemovedFromTenantEvent;
import gr.cite.notification.query.TenantQuery; import gr.cite.notification.query.TenantQuery;
import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,17 +31,16 @@ public class TenantDeleter implements Deleter {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
protected final QueryFactory queryFactory; protected final QueryFactory queryFactory;
private final DeleterFactory deleterFactory; private final EventBroker eventBroker;
@Autowired @Autowired
public TenantDeleter( public TenantDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory, QueryFactory queryFactory, EventBroker eventBroker
DeleterFactory deleterFactory
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory; this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +71,7 @@ public class TenantDeleter implements Deleter {
logger.trace("updating item"); logger.trace("updating item");
this.entityManager.merge(item); this.entityManager.merge(item);
logger.trace("updated item"); logger.trace("updated item");
this.eventBroker.emit(new TenantTouchedEvent(item.getId(), item.getCode()));
} }
} }

View File

@ -3,6 +3,8 @@ package gr.cite.notification.model.deleter;
import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.data.TenantEntityManager; import gr.cite.notification.data.TenantEntityManager;
import gr.cite.notification.data.TenantUserEntity; import gr.cite.notification.data.TenantUserEntity;
import gr.cite.notification.event.EventBroker;
import gr.cite.notification.event.UserRemovedFromTenantEvent;
import gr.cite.notification.query.TenantUserQuery; import gr.cite.notification.query.TenantUserQuery;
import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,14 +30,16 @@ public class TenantUserDeleter implements Deleter {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final EventBroker eventBroker;
@Autowired @Autowired
public TenantUserDeleter( public TenantUserDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory QueryFactory queryFactory, EventBroker eventBroker
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.eventBroker = eventBroker;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -66,6 +70,7 @@ public class TenantUserDeleter implements Deleter {
logger.trace("updating item"); logger.trace("updating item");
this.entityManager.merge(item); this.entityManager.merge(item);
logger.trace("updated item"); logger.trace("updated item");
this.eventBroker.emit(new UserRemovedFromTenantEvent(item.getUserId(), item.getTenantId()));
} }
} }
} }

View File

@ -214,7 +214,7 @@ public class QueueInboxQuery extends QueryBase<QueueInboxEntity> {
queryContext.CriteriaBuilder.lessThanOrEqualTo(queryContext.Root.get(QueueInboxEntity._retryCount), this.retryThreshold))); queryContext.CriteriaBuilder.lessThanOrEqualTo(queryContext.Root.get(QueueInboxEntity._retryCount), this.retryThreshold)));
} }
if (predicates.size() > 0) { if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray); return queryContext.CriteriaBuilder.and(predicatesArray);
} else { } else {

View File

@ -8,6 +8,8 @@ import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.convention.ConventionService; import gr.cite.notification.convention.ConventionService;
import gr.cite.notification.data.TenantEntity; import gr.cite.notification.data.TenantEntity;
import gr.cite.notification.data.TenantEntityManager; import gr.cite.notification.data.TenantEntityManager;
import gr.cite.notification.event.EventBroker;
import gr.cite.notification.event.TenantTouchedEvent;
import gr.cite.notification.model.Tenant; import gr.cite.notification.model.Tenant;
import gr.cite.notification.model.builder.TenantBuilder; import gr.cite.notification.model.builder.TenantBuilder;
import gr.cite.notification.model.deleter.TenantDeleter; import gr.cite.notification.model.deleter.TenantDeleter;
@ -23,6 +25,8 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException; import javax.management.InvalidApplicationException;
@ -45,17 +49,21 @@ public class TenantServiceImpl implements TenantService {
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
private final BuilderFactory builderFactory; private final BuilderFactory builderFactory;
private final EventBroker eventBroker;
private final MessageSource messageSource;
public TenantServiceImpl(AuthorizationService authorizationService, public TenantServiceImpl(AuthorizationService authorizationService,
DeleterFactory deleterFactory, DeleterFactory deleterFactory,
ConventionService conventionService, ConventionService conventionService,
TenantEntityManager entityManager, TenantEntityManager entityManager,
BuilderFactory builderFactory) { BuilderFactory builderFactory, EventBroker eventBroker, MessageSource messageSource) {
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
this.conventionService = conventionService; this.conventionService = conventionService;
this.entityManager = entityManager; this.entityManager = entityManager;
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.eventBroker = eventBroker;
this.messageSource = messageSource;
} }
@Override @Override
@ -91,16 +99,21 @@ public class TenantServiceImpl implements TenantService {
this.entityManager.flush(); this.entityManager.flush();
this.eventBroker.emit(new TenantTouchedEvent(data.getId(), data.getCode()));
return this.builderFactory.builder(TenantBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, Tenant._id), data); return this.builderFactory.builder(TenantBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, Tenant._id), data);
} }
@Override @Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting Tenant: {}", id); logger.debug("deleting Tenant: {}", id);
this.authorizationService.authorizeForce(Permission.DeleteTenant); this.authorizationService.authorizeForce(Permission.DeleteTenant);
TenantEntity data = this.entityManager.find(TenantEntity.class, id);
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id)); this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id));
this.eventBroker.emit(new TenantTouchedEvent(data.getId(), data.getCode()));
} }
} }

View File

@ -10,6 +10,10 @@ import gr.cite.notification.common.scope.tenant.TenantScope;
import gr.cite.notification.common.types.user.AdditionalInfoEntity; import gr.cite.notification.common.types.user.AdditionalInfoEntity;
import gr.cite.notification.convention.ConventionService; import gr.cite.notification.convention.ConventionService;
import gr.cite.notification.data.*; import gr.cite.notification.data.*;
import gr.cite.notification.event.EventBroker;
import gr.cite.notification.event.UserAddedToTenantEvent;
import gr.cite.notification.event.UserCredentialTouchedEvent;
import gr.cite.notification.event.UserTouchedEvent;
import gr.cite.notification.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent; import gr.cite.notification.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent;
import gr.cite.notification.model.Tenant; import gr.cite.notification.model.Tenant;
import gr.cite.notification.model.User; import gr.cite.notification.model.User;
@ -63,6 +67,7 @@ public class UserServiceImpl implements UserService {
private final TenantScope tenantScope; private final TenantScope tenantScope;
private final MessageSource messageSource; private final MessageSource messageSource;
private final EventBroker eventBroker;
private final JsonHandlingService jsonHandlingService; private final JsonHandlingService jsonHandlingService;
@ -71,7 +76,7 @@ public class UserServiceImpl implements UserService {
DeleterFactory deleterFactory, DeleterFactory deleterFactory,
ConventionService conventionService, ConventionService conventionService,
TenantEntityManager entityManager, TenantEntityManager entityManager,
BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, EventBroker eventBroker,
JsonHandlingService jsonHandlingService) { JsonHandlingService jsonHandlingService) {
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
@ -81,6 +86,7 @@ public class UserServiceImpl implements UserService {
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.tenantScope = tenantScope; this.tenantScope = tenantScope;
this.messageSource = messageSource; this.messageSource = messageSource;
this.eventBroker = eventBroker;
this.jsonHandlingService = jsonHandlingService; this.jsonHandlingService = jsonHandlingService;
} }
@ -126,6 +132,7 @@ public class UserServiceImpl implements UserService {
this.persistTenantUser(model.getTenantUsers(), data.getId()); this.persistTenantUser(model.getTenantUsers(), data.getId());
this.entityManager.flush(); this.entityManager.flush();
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
return this.builderFactory.builder(UserBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, User._id), data); return this.builderFactory.builder(UserBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, User._id), data);
} }
@ -146,6 +153,7 @@ public class UserServiceImpl implements UserService {
this.authorizationService.authorizeForce(Permission.DeleteUser); this.authorizationService.authorizeForce(Permission.DeleteUser);
this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id)); this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id));
this.eventBroker.emit(new UserTouchedEvent(id));
} }
private void persistContactInfo(List<UserTouchedIntegrationEvent.UserContactInfo> models, UUID userId) throws InvalidApplicationException { private void persistContactInfo(List<UserTouchedIntegrationEvent.UserContactInfo> models, UUID userId) throws InvalidApplicationException {
@ -196,6 +204,7 @@ public class UserServiceImpl implements UserService {
data.setCreatedAt(Instant.now()); data.setCreatedAt(Instant.now());
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
entityManager.persist(data); entityManager.persist(data);
this.eventBroker.emit(new UserCredentialTouchedEvent(data.getId(), data.getExternalId()));
} }
updatedCreatedIds.add(data.getId()); updatedCreatedIds.add(data.getId());
} }
@ -233,6 +242,7 @@ public class UserServiceImpl implements UserService {
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
data.setIsActive(IsActive.Active); data.setIsActive(IsActive.Active);
entityManager.persist(data); entityManager.persist(data);
this.eventBroker.emit(new UserAddedToTenantEvent(data.getUserId(), data.getTenantId()));
} finally { } finally {
this.tenantScope.removeTempTenant(this.entityManager); this.tenantScope.removeTempTenant(this.entityManager);
} }