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) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
this.evict(this.buildKey(event.getTenantCode()));
if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode()))
this.evict(this.buildKey(event.getPreviousTenantCode()));
}
@Override

View File

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

View File

@ -1,8 +1,10 @@
package gr.cite.annotation.web.scope.user;
import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.event.UserCredentialTouchedEvent;
import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@ -10,6 +12,7 @@ import java.util.UUID;
@Service
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
private final ConventionService conventionService;
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
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService){
super(options);
this.conventionService = conventionService;
}
@Override

View File

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

View File

@ -34,4 +34,8 @@ public class EventBroker {
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(UUID tenantId, String tenantCode, String previousTenantCode) {
public TenantTouchedEvent(UUID tenantId, String tenantCode) {
this.tenantId = tenantId;
this.tenantCode = tenantCode;
this.previousTenantCode = previousTenantCode;
}
private UUID tenantId;
private String tenantCode;
private String previousTenantCode;
public UUID getTenantId() {
return tenantId;
@ -32,11 +30,4 @@ public class TenantTouchedEvent {
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(UUID userId, String subjectId, String previousSubjectId) {
public UserTouchedEvent(UUID userId) {
this.userId = userId;
this.subjectId = subjectId;
this.previousSubjectId = previousSubjectId;
}
private UUID userId;
private String subjectId;
private String previousSubjectId;
public UUID getUserId() {
return userId;
@ -24,19 +20,4 @@ public class UserTouchedEvent {
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.data.TenantEntity;
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.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,17 +30,16 @@ public class TenantDeleter implements Deleter {
private final TenantEntityManager entityManager;
protected final QueryFactory queryFactory;
private final DeleterFactory deleterFactory;
private final EventBroker eventBroker;
@Autowired
public TenantDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
QueryFactory queryFactory, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +70,7 @@ public class TenantDeleter implements Deleter {
logger.trace("updating item");
this.entityManager.merge(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.data.TenantEntityManager;
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.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,17 +30,15 @@ public class TenantUserDeleter implements Deleter {
private final TenantEntityManager entityManager;
private final QueryFactory queryFactory;
private final DeleterFactory deleterFactory;
private final EventBroker eventBroker;
@Autowired
public TenantUserDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
QueryFactory queryFactory, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +69,7 @@ public class TenantUserDeleter implements Deleter {
logger.trace("updating item");
this.entityManager.merge(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 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.annotation.authorization.AuthorizationFlags;
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.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
@ -45,17 +49,21 @@ public class TenantServiceImpl implements TenantService {
private final TenantEntityManager entityManager;
private final BuilderFactory builderFactory;
private final EventBroker eventBroker;
private final MessageSource messageSource;
public TenantServiceImpl(AuthorizationService authorizationService,
DeleterFactory deleterFactory,
ConventionService conventionService,
TenantEntityManager entityManager,
BuilderFactory builderFactory) {
BuilderFactory builderFactory, EventBroker eventBroker, MessageSource messageSource) {
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.conventionService = conventionService;
this.entityManager = entityManager;
this.builderFactory = builderFactory;
this.eventBroker = eventBroker;
this.messageSource = messageSource;
}
@Override
@ -91,16 +99,22 @@ public class TenantServiceImpl implements TenantService {
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);
}
@Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
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.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.convention.ConventionService;
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.model.Tenant;
import gr.cite.annotation.model.User;
@ -62,6 +66,7 @@ public class UserServiceImpl implements UserService {
private final TenantScope tenantScope;
private final MessageSource messageSource;
private final EventBroker eventBroker;
private final JsonHandlingService jsonHandlingService;
@ -70,7 +75,7 @@ public class UserServiceImpl implements UserService {
DeleterFactory deleterFactory,
ConventionService conventionService,
TenantEntityManager entityManager,
BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource,
BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, EventBroker eventBroker,
JsonHandlingService jsonHandlingService) {
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -80,6 +85,7 @@ public class UserServiceImpl implements UserService {
this.queryFactory = queryFactory;
this.tenantScope = tenantScope;
this.messageSource = messageSource;
this.eventBroker = eventBroker;
this.jsonHandlingService = jsonHandlingService;
}
@ -124,6 +130,7 @@ public class UserServiceImpl implements UserService {
this.persistTenantUser(model.getTenantUsers(), data.getId());
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);
}
@ -135,6 +142,7 @@ public class UserServiceImpl implements UserService {
this.authorizationService.authorizeForce(Permission.DeleteUser);
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 {
@ -155,6 +163,7 @@ public class UserServiceImpl implements UserService {
data.setUpdatedAt(Instant.now());
entityManager.persist(data);
}
this.eventBroker.emit(new UserCredentialTouchedEvent(data.getId(), data.getExternalId()));
updatedCreatedIds.add(data.getId());
}
}
@ -191,6 +200,7 @@ public class UserServiceImpl implements UserService {
data.setUpdatedAt(Instant.now());
data.setIsActive(IsActive.Active);
entityManager.persist(data);
this.eventBroker.emit(new UserAddedToTenantEvent(data.getUserId(), data.getTenantId()));
} finally {
this.tenantScope.removeTempTenant(this.entityManager);
}

View File

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

View File

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

View File

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

View File

@ -57,4 +57,8 @@ public class EventBroker {
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(UUID tenantId, String tenantCode, String previousTenantCode) {
public TenantTouchedEvent(UUID tenantId, String tenantCode) {
this.tenantId = tenantId;
this.tenantCode = tenantCode;
this.previousTenantCode = previousTenantCode;
}
private UUID tenantId;
private String tenantCode;
private String previousTenantCode;
public UUID getTenantId() {
return tenantId;
return this.tenantId;
}
public void setTenantId(UUID tenantId) {
@ -25,18 +23,11 @@ public class TenantTouchedEvent {
}
public String getTenantCode() {
return tenantCode;
return this.tenantCode;
}
public void setTenantCode(String 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;
public UUID getUserId() {
return userId;
return this.userId;
}
public void setUserId(UUID userId) {

View File

@ -1,15 +1,18 @@
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.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -24,7 +27,7 @@ import java.util.UUID;
import java.util.stream.Collectors;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TenantDeleter implements Deleter {
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 DeleterFactory deleterFactory;
private final EventBroker eventBroker;
@Autowired
public TenantDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -83,6 +88,7 @@ public class TenantDeleter implements Deleter {
logger.trace("updating item");
this.entityManager.merge(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;
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.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -22,23 +23,22 @@ import java.util.Optional;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TenantUserDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantUserDeleter.class));
private final TenantEntityManager entityManager;
private final QueryFactory queryFactory;
private final DeleterFactory deleterFactory;
private final EventBroker eventBroker;
@Autowired
public TenantUserDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
QueryFactory queryFactory, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +69,7 @@ public class TenantUserDeleter implements Deleter {
logger.trace("updating item");
this.entityManager.merge(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 org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserCredentialEntity;
import org.opencdmp.event.EventBroker;
import org.opencdmp.event.UserCredentialTouchedEvent;
import org.opencdmp.query.UserCredentialQuery;
import org.opencdmp.service.keycloak.KeycloakService;
import org.slf4j.LoggerFactory;
@ -28,16 +30,18 @@ public class UserCredentialDeleter implements Deleter {
protected final QueryFactory queryFactory;
private final KeycloakService keycloakService;
private final EventBroker eventBroker;
@Autowired
public UserCredentialDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory, KeycloakService keycloakService
QueryFactory queryFactory, KeycloakService keycloakService, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.keycloakService = keycloakService;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -67,6 +71,8 @@ public class UserCredentialDeleter implements Deleter {
logger.trace("deleted item");
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<>();
if (userId != null || usePublic) {
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
queryContext.CriteriaBuilder.in(queryContext.Root.get(ReferenceEntity._id)).value(this.queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(DmpReferenceEntity.class, UUID.class)
.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());
ReferenceEntity referenceEntity = this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(); //TODO: optimize
if (referenceEntity == null) referenceEntity = this.queryFactory.query(ReferenceQuery.class).references(model.getReference()).typeIds(referenceTypeEntity.getId()).sources(model.getSource()).first();
ReferenceEntity referenceEntity = model.getId() != null ? this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(): null; //TODO: optimize
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();
persist.setTypeId(referenceTypeEntity.getId());
if (referenceEntity == null) {
persist.setLabel(model.getLabel());
persist.setReference(model.getReference());
persist.setReference(!this.conventionService.isNullOrEmpty(model.getReference()) ? model.getReference() : UUID.randomUUID().toString());
persist.setSource("internal");
persist.setSourceType(ReferenceSourceType.Internal);
} else {

View File

@ -7,12 +7,12 @@ import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet;
import jakarta.xml.bind.JAXBException;
import org.opencdmp.commons.types.dmp.importexport.DmpImportExport;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.model.DmpUser;
import org.opencdmp.model.DmpValidationResult;
import org.opencdmp.model.dmp.Dmp;
import org.opencdmp.model.persist.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException;
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 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.event.DmpTouchedEvent;
import org.opencdmp.event.EventBroker;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.integrationevent.outbox.annotationentityremoval.AnnotationEntityRemovalIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
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.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException;
import javax.crypto.BadPaddingException;
@ -2051,16 +2051,19 @@ public class DmpServiceImpl implements DmpService {
//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 {
DmpModel model = this.fileTransformerService.importDmp(file, repositoryId, format);
public Dmp importJson(DmpCommonModelConfig dmpCommonModelConfig, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException {
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");
logger.debug(new MapLogEntry("import data").And("bytes", file.getBytes()).And("label", label).And("fields", fields));
DmpPersist persist = new DmpPersist();
persist.setLabel(label);
persist.setLabel(dmpCommonModelConfig.getLabel());
persist.setStatus(DmpStatus.Draft);
persist.setDescription(model.getDescription());
switch (model.getAccessType()) {
@ -2163,7 +2166,7 @@ public class DmpServiceImpl implements DmpService {
}
} else {
// 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);
ExtraFieldModel extraFieldModel = (ExtraFieldModel) field;
if (dmpBlueprintValueModel != null) dmpBlueprintValues.put(dmpBlueprintValueModel.getFieldId(), this.commonModelDmpBlueprintValueToPersist(dmpBlueprintValueModel, extraFieldModel));
@ -2204,18 +2207,21 @@ public class DmpServiceImpl implements DmpService {
private ReferencePersist commonDmpReferenceToReferencePersist(ReferenceModel model, ReferenceTypeEntity referenceTypeEntity) {
if (!referenceTypeEntity.getCode().equals(model.getType().getCode())) throw new MyApplicationException("Invalid reference for field " + model.getId());
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
if (referenceEntity == null) referenceEntity = this.queryFactory.query(ReferenceQuery.class).references(model.getReference()).typeIds(referenceTypeEntity.getId()).sources(model.getSource()).first();
ReferenceEntity referenceEntity = model.getId() != null ? this.queryFactory.query(ReferenceQuery.class).ids(model.getId()).first(): null; //TODO: optimize
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();
persist.setTypeId(referenceTypeEntity.getId());
if (referenceEntity == null) {
persist.setLabel(model.getLabel());
persist.setReference(model.getReference());
persist.setReference(!this.conventionService.isNullOrEmpty(model.getReference()) ? model.getReference() : UUID.randomUUID().toString());
persist.setSource("internal");
persist.setSourceType(ReferenceSourceType.Internal);
} else {

View File

@ -7,6 +7,10 @@ import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerClient;
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.springframework.core.ParameterizedTypeReference;
import org.springframework.web.reactive.function.client.WebClient;
@ -30,9 +34,9 @@ public class FileTransformerRepository implements FileTransformerClient {
}
@Override
public DmpModel importDmp(FileEnvelopeModel fileEnvelope) {
logger.debug(new MapLogEntry("importDmp").And("fileEnvelope", fileEnvelope));
return this.transformerClient.post().uri("/import/dmp").bodyValue(fileEnvelope)
public DmpModel importDmp(DmpImportModel dmpImportModel) {
logger.debug(new MapLogEntry("importDmp").And("fileEnvelope", dmpImportModel.getFile()));
return this.transformerClient.post().uri("/import/dmp").bodyValue(dmpImportModel)
.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
public DescriptionModel importDescription(FileEnvelopeModel fileEnvelope) {
logger.debug(new MapLogEntry("importDescription").And("fileEnvelope", fileEnvelope));
return this.transformerClient.post().uri("/import/description").bodyValue(fileEnvelope)
public DescriptionModel importDescription(DescriptionImportModel descriptionImportModel) {
logger.debug(new MapLogEntry("importDescription").And("fileEnvelope", descriptionImportModel.getFile()));
return this.transformerClient.post().uri("/import/description").bodyValue(descriptionImportModel)
.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();
}
@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 org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
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.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;
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;
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.oidc.filter.webflux.TokenExchangeCacheService;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeFilterFunction;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeModel;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.xml.bind.JAXBException;
import org.apache.commons.io.FilenameUtils;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.Permission;
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
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.dmpblueprint.DmpBlueprintModel;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.enums.IsActive;
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.tenantconfiguration.FileTransformerTenantConfigurationEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.StorageFileEntity;
import org.opencdmp.data.TenantConfigurationEntity;
import org.opencdmp.event.TenantConfigurationTouchedEvent;
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.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.dmpblueprint.DmpBlueprintCommonModelBuilder;
import org.opencdmp.model.description.Description;
import org.opencdmp.model.dmp.Dmp;
import org.opencdmp.model.dmpblueprint.DmpBlueprint;
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.tenantconfiguration.TenantConfiguration;
import org.opencdmp.query.DescriptionQuery;
import org.opencdmp.query.DmpQuery;
import org.opencdmp.query.TenantConfigurationQuery;
import org.opencdmp.query.*;
import org.opencdmp.service.encryption.EncryptionService;
import org.opencdmp.service.storage.StorageFileService;
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.event.EventListener;
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.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@ -64,6 +78,7 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class FileTransformerServiceImpl implements FileTransformerService {
@ -119,9 +134,12 @@ public class FileTransformerServiceImpl implements FileTransformerService {
exchangeFilterFunctions.add(tokenExchangeFilterFunction);
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
}).codecs(codecs -> codecs
.defaultCodecs()
.maxInMemorySize(source.getMaxInMemorySizeInBytes())
}).codecs(codecs -> {
codecs.defaultCodecs().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());
this.clients.put(repositoryIdByTenant, repository);
return repository;
@ -295,37 +313,105 @@ public class FileTransformerServiceImpl implements FileTransformerService {
}
@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);
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
FileTransformerRepository repository = this.getRepository(repositoryId);
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale()));
FileTransformerRepository repository = this.getRepository(dmpCommonModelConfig.getRepositoryId());
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());
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
String mimeType = URLConnection.guessContentTypeFromName(file.getOriginalFilename());
DmpBlueprintQuery dmpBlueprintQuery = this.queryFactory.query(DmpBlueprintQuery.class).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(dmpCommonModelConfig.getBlueprintId());
DmpBlueprintModel dmpBlueprintModel = this.builderFactory.builder(DmpBlueprintCommonModelBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(dmpBlueprintQuery.first());
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();
fileEnvelope.setFile(file.getBytes());
fileEnvelope.setFile(this.storageFileService.readAsBytesSafe(dmpCommonModelConfig.getFileId()));
fileEnvelope.setMimeType(mimeType);
fileEnvelope.setFilename(name + (extension.startsWith(".") ? "" : ".") + extension);
fileEnvelope.setFilename(originalFileName);
if (repository.getConfiguration() != null && repository.getConfiguration().isUseSharedStorage()){
StorageFilePersist storageFilePersist = new StorageFilePersist();
storageFilePersist.setName(name);
storageFilePersist.setExtension(extension);
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, 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());
}
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.data.*;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.*;
import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEvent;
import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEvent;
@ -81,6 +82,7 @@ public class TenantServiceImpl implements TenantService {
private final QueryFactory queryFactory;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final ClaimExtractor claimExtractor;
private final EventBroker eventBroker;
@Autowired
@ -91,7 +93,7 @@ public class TenantServiceImpl implements TenantService {
BuilderFactory builderFactory,
ConventionService conventionService,
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.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -108,6 +110,7 @@ public class TenantServiceImpl implements TenantService {
this.queryFactory = queryFactory;
this.currentPrincipalResolver = currentPrincipalResolver;
this.claimExtractor = claimExtractor;
this.eventBroker = eventBroker;
}
@Override
@ -155,6 +158,8 @@ public class TenantServiceImpl implements TenantService {
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);
}
@ -178,6 +183,7 @@ public class TenantServiceImpl implements TenantService {
tenantUserEntity.setCreatedAt(Instant.now());
tenantUserEntity.setUpdatedAt(Instant.now());
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);
if (userCredential == null) continue;
@ -193,12 +199,16 @@ public class TenantServiceImpl implements TenantService {
item.setCreatedAt(Instant.now());
this.entityManager.persist(item);
keycloakIdsToAddToTenantGroup.add(userCredential.getExternalId());
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredential.getId(), userCredential.getExternalId()));
}
this.entityManager.flush();
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
this.userTouchedIntegrationEventHandler.handle(userId);
this.eventBroker.emit(new UserTouchedEvent(userId));
}
this.entityManager.flush();
@ -214,6 +224,8 @@ public class TenantServiceImpl implements TenantService {
@Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
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);
@ -222,6 +234,8 @@ public class TenantServiceImpl implements TenantService {
TenantRemovalIntegrationEvent tenantRemovalIntegrationEvent = new TenantRemovalIntegrationEvent();
tenantRemovalIntegrationEvent.setId(id);
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.types.actionconfirmation.MergeAccountConfirmationEntity;
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.user.AdditionalInfoEntity;
import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity;
@ -41,8 +43,7 @@ import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.*;
import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.EventBroker;
import org.opencdmp.event.UserTouchedEvent;
import org.opencdmp.event.*;
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
@ -287,6 +288,8 @@ public class UserServiceImpl implements UserService {
this.entityManager.reloadTenantFilters();
}
this.userRemovalIntegrationEventHandler.handle(id);
this.eventBroker.emit(new UserTouchedEvent(id));
}
//endregion
@ -407,6 +410,8 @@ public class UserServiceImpl implements UserService {
tenantUserEntity.setCreatedAt(Instant.now());
tenantUserEntity.setUpdatedAt(Instant.now());
this.entityManager.persist(tenantUserEntity);
this.eventBroker.emit(new UserAddedToTenantEvent(tenantUserEntity.getUserId(), tenantUserEntity.getTenantId()));
}
this.entityManager.flush();
@ -680,7 +685,9 @@ public class UserServiceImpl implements UserService {
if (!newUser.getId().equals(userToBeMerge.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 {
@ -700,6 +707,8 @@ public class UserServiceImpl implements UserService {
if (!this.conventionService.isNullOrEmpty(tenantCode)) this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), tenantCode, userRole.getRole());
}
}
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredential.getId(), userCredential.getExternalId()));
}
} finally {
@ -714,6 +723,8 @@ public class UserServiceImpl implements UserService {
for (UserCredentialEntity userCredential : userCredentials) {
userCredential.setUserId(newUser.getId());
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();
@ -748,8 +759,10 @@ public class UserServiceImpl implements UserService {
if (newTenantUsers.stream().anyMatch(x -> Objects.equals(x.getTenantId(), userTenantUser.getTenantId()))) {
tenantUsersToDelete.add(userTenantUser);
} else {
this.eventBroker.emit(new UserRemovedFromTenantEvent(userTenantUser.getUserId(), userTenantUser.getTenantId()));
userTenantUser.setUserId(newUser.getId());
this.entityManager.merge(userTenantUser);
this.eventBroker.emit(new UserAddedToTenantEvent(userTenantUser.getUserId(), userTenantUser.getTenantId()));
}
}
this.deleterFactory.deleter(TenantUserDeleter.class).delete(tenantUsersToDelete);
@ -881,6 +894,9 @@ public class UserServiceImpl implements UserService {
this.keycloakService.removeFromAllGroups(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){

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.Swagger404;
import org.opencdmp.controllers.swagger.annotation.SwaggerErrorResponses;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingDmpModel;
import org.opencdmp.model.DescriptionsToBeFinalized;
import org.opencdmp.model.DmpUser;
import org.opencdmp.model.DmpValidationResult;
@ -453,23 +454,40 @@ public class DmpController {
return model;
}
@PostMapping("json/import")
@Operation(summary = "Import a plan from an json file")
@PostMapping("json/preprocessing")
@Operation(summary = "preprocessing a plan from an json file")
@Transactional
public Dmp importJson(
@RequestParam("file") MultipartFile file,
@RequestParam("label") String label,
@RequestParam("repositoryId") String repositoryId,
@RequestParam("format") String format,
@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));
public PreprocessingDmpModel preprocessing(
@RequestParam("fileId") UUID fileId,
@RequestParam("repositoryId") String repositoryId
) throws InvalidAlgorithmParameterException, JAXBException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("preprocessing dmp" + Dmp.class.getSimpleName()).And("transformerId", repositoryId).And("fileId", fileId));
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(
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)
));

View File

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

View File

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

View File

@ -1,8 +1,10 @@
package org.opencdmp.interceptors.user;
import org.opencdmp.convention.ConventionService;
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.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@ -12,6 +14,8 @@ import java.util.UUID;
@Service
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
private final ConventionService conventionService;
public static class UserInterceptorCacheValue {
public UserInterceptorCacheValue() {
@ -24,7 +28,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
public String getSubjectId() {
return subjectId;
return this.subjectId;
}
public void setSubjectId(String subjectId) {
@ -38,7 +42,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
private List<String> externalProviderNames;
public UUID getUserId() {
return userId;
return this.userId;
}
public void setUserId(UUID userId) {
@ -46,7 +50,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
}
public List<String> getRoles() {
return roles;
return this.roles;
}
public void setRoles(List<String> roles) {
@ -54,7 +58,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
}
public String getProviderEmail() {
return providerEmail;
return this.providerEmail;
}
public void setProviderEmail(String providerEmail) {
@ -62,7 +66,7 @@ public class UserInterceptorCacheService extends CacheService<UserInterceptorCac
}
public List<String> getExternalProviderNames() {
return externalProviderNames;
return this.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
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
super(options);
this.conventionService = conventionService;
}
@Override

View File

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

View File

@ -677,6 +677,11 @@ permissions:
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
BrowseExternalReference:
roles: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: true
EditReference:
roles:
- 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 { Injectable } from '@angular/core';
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 { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-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 { error } from 'console';
import { DmpBlueprintVersionStatus } from '@app/core/common/enum/dmp-blueprint-version-status';
import { TranslateService } from '@ngx-translate/core';
@Injectable()
export class DmpBlueprintService {
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`; }
@ -141,6 +143,41 @@ export class DmpBlueprintService {
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

View File

@ -20,6 +20,7 @@ import { AuthService } from '../auth/auth.service';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service';
import { DmpValidationResult } from '@app/ui/dmp/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { DmpCommonModelConfig, PreprocessingDmpModel } from '@app/core/model/dmp/dmp-import';
@Injectable()
export class DmpService {
@ -197,26 +198,25 @@ export class DmpService {
catchError((error: any) => throwError(error)));;
}
uploadJson(file: File, label: string, repositoryId: string, format: string, reqFields: string[] = []): Observable<Dmp> {
const url = `${this.apiBase}/json/import`;
preprocessingDmp(fileId: Guid, repositoryId: string): Observable<PreprocessingDmpModel> {
const url = `${this.apiBase}/json/preprocessing`;
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.JSONContentType]
};
const formData = new FormData();
formData.append('file', file);
formData.append('label', label);
formData.append('fileId', fileId.toString());
formData.append('repositoryId', repositoryId);
formData.append('format', format);
if (reqFields.length > 0){
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)));
return this.http.post<PreprocessingDmpModel>(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)
);
} else if (file?.type.includes('/json')){
this.dmpService.uploadJson(result.fileList[0], result.dmpTitle, 'rda-file-transformer', 'json')
} else if (file?.type.includes('/json') && result.dmpCommonModelConfig){
this.dmpService.uploadJson(result.dmpCommonModelConfig)
.pipe(takeUntil(this._destroyed))
.subscribe(
(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 class="">
<div class="upload-form col-12 pr-0 pl-0">
<mat-form-field class="w-100">
<input class="uploadInput" [(ngModel)]="dmpTitle" matInput placeholder="{{'DMP-UPLOAD.PLACEHOLDER' | translate}}" name="uploadFileInput">
<mat-form-field class="w-100" *ngIf="files?.length == 0 || files[0].type.includes('/xml')">
<input [(ngModel)]="dmpTitle" matInput placeholder="{{'DMP-UPLOAD.PLACEHOLDER' | translate}}">
</mat-form-field>
</div>
<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">
</form>
</div>
<!-- <div class="upload-form col-sm-12 col-md-12">
<mat-form-field>
<mat-label>{{'DMP-EDITOR.FIELDS.DATASET-TEMPLATES' | translate}}</mat-label>
<app-multiple-auto-complete [(ngModel)]="dmpBlueprints" [configuration]="profilesAutoCompleteConfiguration" (optionActionClicked)="onPreviewTemplate($event)">
<app-multiple-auto-complete required='true' [(ngModel)]="dmpBlueprints" placeholder="{{'DMP-EDITOR.FIELDS.DATASET-TEMPLATES' | translate}}" [configuration]="profilesAutoCompleteConfiguration" (optionActionClicked)="onPreviewTemplate($event)">
</app-multiple-auto-complete>
<div class="upload-form col-12 pr-0 pl-0" *ngIf="formGroup == null && files.length > 0 && files[0].type.includes('/json')">
{{ 'DMP-UPLOAD.ANALYZING-FILE' | translate }}
<b class="fa fa-spinner fa-spin" ></b>
</div>
<div class="upload-form col-12 pr-0 pl-0" *ngIf="formGroup && files.length > 0 && files[0].type.includes('/json')">
<mat-form-field class="w-100">
<input [formControl]="formGroup.get('label')" matInput required="true" placeholder="{{'DMP-UPLOAD.PLACEHOLDER' | translate}}">
</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 class="d-flex justify-content-between">
<div></div>
@ -46,7 +74,7 @@
<button mat-button type="button" class="cancel-btn" (click)="cancel()">{{'DMP-UPLOAD.ACTIONS.CANCEL' | translate}}</button>
</div>
<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>

View File

@ -2,12 +2,22 @@ import { HttpClient } from '@angular/common/http';
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
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 { 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 { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, takeUntil } 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({
selector: 'dmp-upload-dialog',
@ -18,13 +28,17 @@ export class DmpUploadDialogComponent extends BaseComponent {
dmpTitle: string;
dmpBlueprints: any[] = [];
files: File[] = [];
selectedBlueprintSections: DmpBlueprintDefinitionSection[];
formGroup: UntypedFormGroup;
profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = {
filterFn: this.filterProfiles.bind(this),
initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
displayFn: (item) => item['label'],
titleFn: (item) => item['label'],
subtitleFn: (item) => item['description'],
descriptionTemplateSingleAutocompleteConfiguration: SingleAutoCompleteConfiguration = {
initialItems: (data?: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active])).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active], searchQuery)).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, [selectedItem])).pipe(map(x => x.items[0])),
displayFn: (item: DescriptionTemplate) => item.label,
titleFn: (item: DescriptionTemplate) => item.label,
subtitleFn: (item: DescriptionTemplate) => item.description,
valueAssign: (item: DescriptionTemplate) => item.id,
popupItemActionIcon: 'visibility'
};
@ -35,6 +49,13 @@ export class DmpUploadDialogComponent extends BaseComponent {
private dialog: MatDialog,
private httpClient: HttpClient,
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,
) {
@ -58,10 +79,28 @@ export class DmpUploadDialogComponent extends BaseComponent {
this.data.success = true;
this.data.dmpTitle = this.dmpTitle;
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);
}
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) {
this.formGroup = null;
const fileList: FileList = event.target.files
this.data.fileList = fileList;
if (this.data.fileList.length > 0) {
@ -71,6 +110,28 @@ export class DmpUploadDialogComponent extends BaseComponent {
this.files.splice(0, 1);
}
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) {
@ -88,19 +149,25 @@ export class DmpUploadDialogComponent extends BaseComponent {
onRemove(event) {
this.files.splice(0, 1);
this.dmpTitle = null;
this.formGroup = null;
}
filterProfiles(value: string): Observable<DescriptionTemplate[]> {
// TODO refactor
// const request = new DataTableRequest<DatasetProfileCriteria>(null, null, { fields: ['+label'] });
// const criteria = new DatasetProfileCriteria();
// criteria.like = value;
// request.criteria = criteria;
// return this._service.searchDmpBlueprints(request);
return null;
selectedBlueprintChanged(item: DmpBlueprint): void{
this.selectedBlueprintSections = item.definition?.sections?.filter(x => x.hasTemplates) || null;
if (this.formGroup){
const descriptionsFormArray = this.formGroup.get('descriptions') as UntypedFormArray;
descriptionsFormArray.controls.forEach( control =>{
control.get('sectionId').patchValue(null);
})
}
}
hasFile(): boolean {
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 { NgxDropzoneModule } from 'ngx-dropzone';
import { DmpUploadDialogComponent } from './dmp-upload-dialog.component';
import { ReactiveFormsModule } from '@angular/forms';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
@NgModule({
imports: [
CommonUiModule,
CommonFormsModule,
FormattingModule,
ReactiveFormsModule,
AutoCompleteModule,
NgxDropzoneModule
],
declarations: [

View File

@ -699,6 +699,14 @@
"DMP-UPLOAD": {
"TITLE": "Import Plan",
"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": {
"IMPORT": "Import",
"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 { MatFormField } from "@angular/material/form-field";
import { MatInput } from "@angular/material/input";
@ -15,9 +15,10 @@ import { MarkedValidatorFn } from "./validation/custom-validator";
})
export class ReactiveAsteriskDirective implements AfterContentChecked {
private readonly requiredValidatornames = ['RequiredWithVisibilityRulesValidator', 'required'];
constructor(private matFormField: MatFormField) { }
constructor(@Optional() private matFormField: MatFormField) { }
ngAfterContentChecked() {
if (!this.matFormField) return;
const ctrl = this.matFormField._control;
const abstractControl = ctrl?.ngControl?.control;
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) {
if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
this.evict(this.buildKey(event.getTenantCode()));
if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode()))
this.evict(this.buildKey(event.getPreviousTenantCode()));
}
@Override

View File

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

View File

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

View File

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

View File

@ -37,4 +37,8 @@ public class EventBroker {
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(UUID tenantId, String tenantCode, String previousTenantCode) {
public TenantTouchedEvent(UUID tenantId, String tenantCode) {
this.tenantId = tenantId;
this.tenantCode = tenantCode;
this.previousTenantCode = previousTenantCode;
}
private UUID tenantId;
private String tenantCode;
private String previousTenantCode;
public UUID getTenantId() {
return tenantId;
@ -31,12 +29,4 @@ public class TenantTouchedEvent {
public void setTenantCode(String 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(UUID userId, String subjectId, String previousSubjectId) {
public UserTouchedEvent(UUID userId) {
this.userId = userId;
this.subjectId = subjectId;
this.previousSubjectId = previousSubjectId;
}
private UUID userId;
private String subjectId;
private String previousSubjectId;
public UUID getUserId() {
return userId;
@ -24,19 +20,4 @@ public class UserTouchedEvent {
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.data.TenantEntity;
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.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,17 +31,16 @@ public class TenantDeleter implements Deleter {
private final TenantEntityManager entityManager;
protected final QueryFactory queryFactory;
private final DeleterFactory deleterFactory;
private final EventBroker eventBroker;
@Autowired
public TenantDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
QueryFactory queryFactory, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -69,6 +71,7 @@ public class TenantDeleter implements Deleter {
logger.trace("updating item");
this.entityManager.merge(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.data.TenantEntityManager;
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.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
@ -28,14 +30,16 @@ public class TenantUserDeleter implements Deleter {
private final TenantEntityManager entityManager;
private final QueryFactory queryFactory;
private final EventBroker eventBroker;
@Autowired
public TenantUserDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory
QueryFactory queryFactory, EventBroker eventBroker
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.eventBroker = eventBroker;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -66,6 +70,7 @@ public class TenantUserDeleter implements Deleter {
logger.trace("updating item");
this.entityManager.merge(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)));
}
if (predicates.size() > 0) {
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {

View File

@ -8,6 +8,8 @@ import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.convention.ConventionService;
import gr.cite.notification.data.TenantEntity;
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.builder.TenantBuilder;
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.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
@ -45,17 +49,21 @@ public class TenantServiceImpl implements TenantService {
private final TenantEntityManager entityManager;
private final BuilderFactory builderFactory;
private final EventBroker eventBroker;
private final MessageSource messageSource;
public TenantServiceImpl(AuthorizationService authorizationService,
DeleterFactory deleterFactory,
ConventionService conventionService,
TenantEntityManager entityManager,
BuilderFactory builderFactory) {
BuilderFactory builderFactory, EventBroker eventBroker, MessageSource messageSource) {
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.conventionService = conventionService;
this.entityManager = entityManager;
this.builderFactory = builderFactory;
this.eventBroker = eventBroker;
this.messageSource = messageSource;
}
@Override
@ -91,16 +99,21 @@ public class TenantServiceImpl implements TenantService {
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);
}
@Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting Tenant: {}", id);
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.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.convention.ConventionService;
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.model.Tenant;
import gr.cite.notification.model.User;
@ -63,6 +67,7 @@ public class UserServiceImpl implements UserService {
private final TenantScope tenantScope;
private final MessageSource messageSource;
private final EventBroker eventBroker;
private final JsonHandlingService jsonHandlingService;
@ -71,7 +76,7 @@ public class UserServiceImpl implements UserService {
DeleterFactory deleterFactory,
ConventionService conventionService,
TenantEntityManager entityManager,
BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource,
BuilderFactory builderFactory, QueryFactory queryFactory, TenantScope tenantScope, MessageSource messageSource, EventBroker eventBroker,
JsonHandlingService jsonHandlingService) {
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -81,7 +86,8 @@ public class UserServiceImpl implements UserService {
this.queryFactory = queryFactory;
this.tenantScope = tenantScope;
this.messageSource = messageSource;
this.jsonHandlingService = jsonHandlingService;
this.eventBroker = eventBroker;
this.jsonHandlingService = jsonHandlingService;
}
@Override
@ -126,6 +132,7 @@ public class UserServiceImpl implements UserService {
this.persistTenantUser(model.getTenantUsers(), data.getId());
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);
}
@ -146,6 +153,7 @@ public class UserServiceImpl implements UserService {
this.authorizationService.authorizeForce(Permission.DeleteUser);
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 {
@ -196,6 +204,7 @@ public class UserServiceImpl implements UserService {
data.setCreatedAt(Instant.now());
data.setUpdatedAt(Instant.now());
entityManager.persist(data);
this.eventBroker.emit(new UserCredentialTouchedEvent(data.getId(), data.getExternalId()));
}
updatedCreatedIds.add(data.getId());
}
@ -233,6 +242,7 @@ public class UserServiceImpl implements UserService {
data.setUpdatedAt(Instant.now());
data.setIsActive(IsActive.Active);
entityManager.persist(data);
this.eventBroker.emit(new UserAddedToTenantEvent(data.getUserId(), data.getTenantId()));
} finally {
this.tenantScope.removeTempTenant(this.entityManager);
}