diff --git a/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java b/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java index 76a4465d9..907adb9f4 100644 --- a/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java +++ b/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java @@ -173,6 +173,8 @@ public class AuditableAction { public static final EventId TenantConfiguration_Persist = new EventId(270002, "TenantConfiguration_Persist"); public static final EventId TenantConfiguration_Delete = new EventId(270003, "TenantConfiguration_Delete"); public static final EventId TenantConfiguration_LookupByType = new EventId(270004, "TenantConfiguration_LookupByType"); + + public static final EventId Annotation_Created_Notify = new EventId(280000, "Annotation_Created_Notify"); diff --git a/backend/core/src/main/java/org/opencdmp/commons/enums/annotation/AnnotationProtectionType.java b/backend/core/src/main/java/org/opencdmp/commons/enums/annotation/AnnotationProtectionType.java new file mode 100644 index 000000000..cfbc79571 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/commons/enums/annotation/AnnotationProtectionType.java @@ -0,0 +1,31 @@ +package org.opencdmp.commons.enums.annotation; + +import com.fasterxml.jackson.annotation.JsonValue; +import org.opencdmp.commons.enums.EnumUtils; +import org.opencdmp.data.converters.enums.DatabaseEnum; + +import java.util.Map; + +public enum AnnotationProtectionType implements DatabaseEnum { + + Private((short) 0), + EntityAccessors((short) 1); + + private final Short value; + + AnnotationProtectionType(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(AnnotationProtectionType.class); + + public static AnnotationProtectionType of(Short i) { + return map.get(i); + } + +} diff --git a/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java b/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java index f434964f5..a4e6dc488 100644 --- a/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java +++ b/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java @@ -13,6 +13,7 @@ public class NotificationProperties { private UUID dmpFinalisedType; private UUID descriptionModifiedType; private UUID descriptionFinalisedType; + private UUID descriptionAnnotationCreated; private UUID mergeAccountConfirmationType; private UUID removeCredentialConfirmationType; private UUID dmpDepositType; @@ -133,4 +134,12 @@ public class NotificationProperties { public void setContactSupportEmail(String contactSupportEmail) { this.contactSupportEmail = contactSupportEmail; } + + public UUID getDescriptionAnnotationCreated() { + return descriptionAnnotationCreated; + } + + public void setDescriptionAnnotationCreated(UUID descriptionAnnotationCreated) { + this.descriptionAnnotationCreated = descriptionAnnotationCreated; + } } diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/AppRabbitConfigurer.java b/backend/core/src/main/java/org/opencdmp/integrationevent/AppRabbitConfigurer.java index 3d40f0a4d..5c27d6e3e 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/AppRabbitConfigurer.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/AppRabbitConfigurer.java @@ -9,6 +9,7 @@ import gr.cite.rabbitmq.consumer.InboxCreator; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; @@ -19,21 +20,23 @@ import java.util.List; @ConditionalOnProperty(prefix = "queue.rabbitmq", name = "listenerEnabled") public class AppRabbitConfigurer extends RabbitConfigurer { - private ApplicationContext applicationContext; + private final ApplicationContext applicationContext; + private final InboxProperties inboxProperties; - public AppRabbitConfigurer(ApplicationContext applicationContext) { + public AppRabbitConfigurer(ApplicationContext applicationContext, InboxProperties inboxProperties) { this.applicationContext = applicationContext; + this.inboxProperties = inboxProperties; } - // @Bean + @Bean public InboxBindings inboxBindingsCreator() { List bindingItems = new ArrayList<>(); - + bindingItems.addAll(this.inboxProperties.getAnnotationCreatedTopic()); return new InboxBindings(bindingItems); } - // @Bean + @Bean(name = "InboxCreator") public InboxCreator inboxCreator() { return (params) -> { InboxRepository inboxRepository = this.applicationContext.getBean(InboxRepository.class); diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxProperties.java b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxProperties.java index d5c29630a..db18d9bb5 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxProperties.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxProperties.java @@ -4,6 +4,8 @@ import jakarta.validation.constraints.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; +import java.util.List; + @Validated @ConfigurationProperties(prefix = "queue.task.listener.options") //@ConstructorBinding @@ -12,14 +14,19 @@ public class InboxProperties { @NotNull private final String exchange; + private final List annotationCreatedTopic; + public InboxProperties( - String exchange - ) { + String exchange, List annotationCreatedTopic) { this.exchange = exchange; + this.annotationCreatedTopic = annotationCreatedTopic; } public String getExchange() { return exchange; } + public List getAnnotationCreatedTopic() { + return annotationCreatedTopic; + } } diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxRepositoryImpl.java b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxRepositoryImpl.java index e6a003283..04828f1c1 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxRepositoryImpl.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/InboxRepositoryImpl.java @@ -15,6 +15,7 @@ import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.fake.FakeRequestScope; import org.opencdmp.data.QueueInboxEntity; import org.opencdmp.data.TenantEntityManager; +import org.opencdmp.integrationevent.inbox.annotationentitycreated.AnnotationEntityCreatedIntegrationEventHandler; import org.opencdmp.query.QueueInboxQuery; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; @@ -359,12 +360,12 @@ public class InboxRepositoryImpl implements InboxRepository { private EventProcessingStatus processMessage(QueueInboxEntity queueInboxMessage) { IntegrationEventHandler handler = null; logger.debug("Processing message with routing key '{}'", queueInboxMessage.getRoute()); -// if (this.routingKeyMatched(queueInboxMessage.getRoute(), this.inboxProperties.getTenantRemovalTopic())) -// handler = this.applicationContext.getBean(TenantRemovalIntegrationEventHandler.class); -// else { -// logger.error("No handler found for message routing key '{}'. Discarding.", queueInboxMessage.getRoute()); -// handler = null; -// } + if (this.routingKeyMatched(queueInboxMessage.getRoute(), this.inboxProperties.getAnnotationCreatedTopic())) + handler = this.applicationContext.getBean(AnnotationEntityCreatedIntegrationEventHandler.class); + else { + logger.error("No handler found for message routing key '{}'. Discarding.", queueInboxMessage.getRoute()); + handler = null; + } if (handler == null) return EventProcessingStatus.Discard; diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/IntegrationEventHandler.java b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/IntegrationEventHandler.java index 5ba093351..7afae8c53 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/IntegrationEventHandler.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/IntegrationEventHandler.java @@ -1,7 +1,9 @@ package org.opencdmp.integrationevent.inbox; +import javax.management.InvalidApplicationException; + public interface IntegrationEventHandler { - EventProcessingStatus handle(IntegrationEventProperties properties, String message); + EventProcessingStatus handle(IntegrationEventProperties properties, String message) throws InvalidApplicationException; } diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEvent.java b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEvent.java new file mode 100644 index 000000000..d90ac5bc9 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEvent.java @@ -0,0 +1,189 @@ +package org.opencdmp.integrationevent.inbox.annotationentitycreated; + +import gr.cite.tools.validation.ValidatorFactory; +import gr.cite.tools.validation.specification.Specification; +import org.opencdmp.commons.enums.annotation.AnnotationProtectionType; +import org.opencdmp.commons.validation.BaseValidator; +import org.opencdmp.convention.ConventionService; +import org.opencdmp.errorcode.ErrorThesaurusProperties; +import org.opencdmp.integrationevent.TrackedEvent; +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.time.Instant; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class AnnotationEntityCreatedIntegrationEvent extends TrackedEvent { + + private UUID id; + public static final String _id = "id"; + private UUID entityId; + public static final String _entityId = "entityId"; + + private String entityType; + public static final String _entityType = "entityType"; + + private String anchor; + public static final String _anchor = "anchor"; + + private String payload; + public static final String _payload = "payload"; + + private UUID subjectId; + public static final String _subjectId = "subjectId"; + + private UUID threadId; + public static final String _threadId = "threadId"; + + private UUID parentId; + public static final String _parentId = "parentId"; + + private AnnotationProtectionType protectionType; + public static final String _protectionType = "protectionType"; + + private Instant timeStamp; + public static final String _timeStamp = "timeStamp"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public UUID getEntityId() { + return entityId; + } + + public void setEntityId(UUID entityId) { + this.entityId = entityId; + } + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public String getAnchor() { + return anchor; + } + + public void setAnchor(String anchor) { + this.anchor = anchor; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public UUID getSubjectId() { + return subjectId; + } + + public void setSubjectId(UUID subjectId) { + this.subjectId = subjectId; + } + + public UUID getThreadId() { + return threadId; + } + + public void setThreadId(UUID threadId) { + this.threadId = threadId; + } + + public UUID getParentId() { + return parentId; + } + + public void setParentId(UUID parentId) { + this.parentId = parentId; + } + + public AnnotationProtectionType getProtectionType() { + return protectionType; + } + + public void setProtectionType(AnnotationProtectionType protectionType) { + this.protectionType = protectionType; + } + + public Instant getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(Instant timeStamp) { + this.timeStamp = timeStamp; + } + + @Component(AnnotationEntityCreatedIntegrationEventValidator.ValidatorName) + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class AnnotationEntityCreatedIntegrationEventValidator extends BaseValidator { + + public static final String ValidatorName = "AnnotationEntityCreatedIntegrationEventValidator"; + + private final MessageSource messageSource; + + private final ValidatorFactory validatorFactory; + + protected AnnotationEntityCreatedIntegrationEventValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) { + super(conventionService, errors); + this.messageSource = messageSource; + this.validatorFactory = validatorFactory; + } + + @Override + protected Class modelClass() { + return AnnotationEntityCreatedIntegrationEvent.class; + } + + @Override + protected List specifications(AnnotationEntityCreatedIntegrationEvent item) { + return Arrays.asList( + this.spec() + .must(() -> this.isValidGuid(item.getId())) + .failOn(AnnotationEntityCreatedIntegrationEvent._id).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityCreatedIntegrationEvent._id}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> this.isValidGuid(item.getSubjectId())) + .failOn(AnnotationEntityCreatedIntegrationEvent._subjectId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityCreatedIntegrationEvent._subjectId}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> !this.isNull(item.getEntityId())) + .failOn(AnnotationEntityCreatedIntegrationEvent._entityId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityCreatedIntegrationEvent._entityId}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> !this.isNull(item.getEntityId())) + .must(() -> this.isValidGuid(item.getEntityId())) + .failOn(AnnotationEntityCreatedIntegrationEvent._entityId).failWith(messageSource.getMessage("validation.invalidid", new Object[]{AnnotationEntityCreatedIntegrationEvent._entityId}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> !this.isEmpty(item.getEntityType())) + .failOn(AnnotationEntityCreatedIntegrationEvent._entityType).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityCreatedIntegrationEvent._entityType}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> !this.isEmpty(item.getPayload())) + .failOn(AnnotationEntityCreatedIntegrationEvent._payload).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityCreatedIntegrationEvent._payload}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> !this.isNull(item.getThreadId())) + .must(() -> this.isValidGuid(item.getThreadId())) + .failOn(AnnotationEntityCreatedIntegrationEvent._threadId).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{AnnotationEntityCreatedIntegrationEvent._threadId}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> !this.isNull(item.getParentId())) + .must(() -> this.isValidGuid(item.getParentId())) + .failOn(AnnotationEntityCreatedIntegrationEvent._parentId).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{AnnotationEntityCreatedIntegrationEvent._parentId}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> !this.isNull(item.getProtectionType())) + .failOn(AnnotationEntityCreatedIntegrationEvent._protectionType).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityCreatedIntegrationEvent._protectionType}, LocaleContextHolder.getLocale())) + ); + } + } +} diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEventHandler.java b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEventHandler.java new file mode 100644 index 000000000..f2446d5d5 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEventHandler.java @@ -0,0 +1,9 @@ +package org.opencdmp.integrationevent.inbox.annotationentitycreated; + +import org.opencdmp.integrationevent.inbox.IntegrationEventHandler; + +import javax.management.InvalidApplicationException; +import java.util.UUID; + +public interface AnnotationEntityCreatedIntegrationEventHandler extends IntegrationEventHandler { +} diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEventHandlerImpl.java b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..85e0f7b36 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/inbox/annotationentitycreated/AnnotationEntityCreatedIntegrationEventHandlerImpl.java @@ -0,0 +1,178 @@ +package org.opencdmp.integrationevent.inbox.annotationentitycreated; + +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorProperties; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.exception.MyValidationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.validation.ValidatorFactory; +import org.opencdmp.audit.AuditableAction; +import org.opencdmp.commons.JsonHandlingService; +import org.opencdmp.commons.enums.IsActive; +import org.opencdmp.commons.notification.NotificationProperties; +import org.opencdmp.commons.scope.tenant.TenantScope; +import org.opencdmp.commons.scope.user.UserScope; +import org.opencdmp.commons.types.notification.DataType; +import org.opencdmp.commons.types.notification.FieldInfo; +import org.opencdmp.commons.types.notification.NotificationFieldData; +import org.opencdmp.data.*; +import org.opencdmp.errorcode.ErrorThesaurusProperties; +import org.opencdmp.integrationevent.inbox.EventProcessingStatus; +import org.opencdmp.integrationevent.inbox.InboxPrincipal; +import org.opencdmp.integrationevent.inbox.IntegrationEventProperties; +import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent; +import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler; +import org.opencdmp.model.Tenant; +import org.opencdmp.model.description.Description; +import org.opencdmp.query.DescriptionQuery; +import org.opencdmp.query.DmpUserQuery; +import org.opencdmp.query.TenantQuery; +import org.opencdmp.query.UserQuery; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; + +import javax.management.InvalidApplicationException; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class AnnotationEntityCreatedIntegrationEventHandlerImpl implements AnnotationEntityCreatedIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntityCreatedIntegrationEventHandlerImpl.class)); + + private final QueryFactory queryFactory; + private final JsonHandlingService jsonHandlingService; + private final NotificationProperties notificationProperties; + private final TenantScope tenantScope; + private final NotifyIntegrationEventHandler notifyIntegrationEventHandler; + private final CurrentPrincipalResolver currentPrincipalResolver; + private final ClaimExtractorProperties claimExtractorProperties; + private final MessageSource messageSource; + private final UserScope userScope; + private final ErrorThesaurusProperties errors; + private final TenantEntityManager tenantEntityManager; + private final ValidatorFactory validatorFactory; + private final AuditService auditService; + + public AnnotationEntityCreatedIntegrationEventHandlerImpl(QueryFactory queryFactory, JsonHandlingService jsonHandlingService, NotificationProperties notificationProperties, TenantScope tenantScope, NotifyIntegrationEventHandler notifyIntegrationEventHandler, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractorProperties claimExtractorProperties, MessageSource messageSource, UserScope userScope, ErrorThesaurusProperties errors, TenantEntityManager tenantEntityManager, ValidatorFactory validatorFactory, AuditService auditService) { + this.queryFactory = queryFactory; + this.jsonHandlingService = jsonHandlingService; + this.notificationProperties = notificationProperties; + this.tenantScope = tenantScope; + this.notifyIntegrationEventHandler = notifyIntegrationEventHandler; + this.currentPrincipalResolver = currentPrincipalResolver; + this.claimExtractorProperties = claimExtractorProperties; + this.messageSource = messageSource; + this.userScope = userScope; + this.errors = errors; + this.tenantEntityManager = tenantEntityManager; + this.validatorFactory = validatorFactory; + this.auditService = auditService; + } + + @Override + public EventProcessingStatus handle(IntegrationEventProperties properties, String message) throws InvalidApplicationException { + AnnotationEntityCreatedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(AnnotationEntityCreatedIntegrationEvent.class, message); + if (event == null) + return EventProcessingStatus.Error; + + logger.debug("Handling {}", AnnotationEntityCreatedIntegrationEvent.class.getSimpleName()); + this.validatorFactory.validator(AnnotationEntityCreatedIntegrationEvent.AnnotationEntityCreatedIntegrationEventValidator.class).validateForce(event); + + EventProcessingStatus status = EventProcessingStatus.Success; + try { + + if (this.tenantScope.isMultitenant() && properties.getTenantId() != null) { + TenantEntity tenant = queryFactory.query(TenantQuery.class).disableTracking().ids(properties.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code)); + if (tenant == null) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } + this.tenantScope.setTempTenant(tenantEntityManager, properties.getTenantId(), tenant.getCode()); + } else if (this.tenantScope.isMultitenant()) { + this.tenantScope.setTempTenant(tenantEntityManager, null, this.tenantScope.getDefaultTenantCode()); + } + + currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties)); + this.sendNotification(event); + auditService.track(AuditableAction.Annotation_Created_Notify, Map.ofEntries( + new AbstractMap.SimpleEntry("model", event) + )); + + } catch (Exception ex) { + status = EventProcessingStatus.Error; + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } finally { + currentPrincipalResolver.pop(); + try { + tenantScope.removeTempTenant(this.tenantEntityManager); + this.tenantEntityManager.reloadTenantFilters(); + } catch (InvalidApplicationException e) { + } + } + + return status; + } + + private void sendNotification(AnnotationEntityCreatedIntegrationEvent event) throws InvalidApplicationException { + + DescriptionEntity descriptionEntity = this.queryFactory.query(DescriptionQuery.class).disableTracking().ids(event.getEntityId()).first(); + + if (descriptionEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{event.getEntityId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + List existingUsers = this.queryFactory.query(DmpUserQuery.class).disableTracking() + .dmpIds(descriptionEntity.getDmpId()) + .isActives(IsActive.Active) + .collect(); + + if (existingUsers == null || existingUsers.size() <= 1){ + return; + } + + UserEntity sender = this.queryFactory.query(UserQuery.class).disableTracking().ids(event.getSubjectId()).first(); + + if (sender == null) throw new MyApplicationException("Sender user not found"); + + for (DmpUserEntity dmpUser : existingUsers) { + if (!dmpUser.getUserId().equals(event.getSubjectId())){ + UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(dmpUser.getUserId()).first(); + if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getDmpInactiveUser().getCode(), this.errors.getDmpInactiveUser().getMessage()); + this.createAnnotationNotificationEvent(user, descriptionEntity, sender.getName()); + } + } + + } + + private void createAnnotationNotificationEvent(UserEntity user, DescriptionEntity description, String reasonName) throws InvalidApplicationException, InvalidApplicationException { + NotifyIntegrationEvent notifyIntegrationEvent = new NotifyIntegrationEvent(); + notifyIntegrationEvent.setUserId(user.getId()); + + notifyIntegrationEvent.setNotificationType(notificationProperties.getDescriptionAnnotationCreated()); + + NotificationFieldData data = new NotificationFieldData(); + List fieldInfoList = new ArrayList<>(); + fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName())); + fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, reasonName)); + fieldInfoList.add(new FieldInfo("{name}", DataType.String, description.getLabel())); + fieldInfoList.add(new FieldInfo("{id}", DataType.String, description.getId().toString())); + if(this.tenantScope.getTenantCode() != null && !this.tenantScope.getTenantCode().equals(this.tenantScope.getDefaultTenantCode())){ + fieldInfoList.add(new FieldInfo("{tenant-url-path}", DataType.String, String.format("/t/%s", this.tenantScope.getTenantCode()))); + } + data.setFields(fieldInfoList); + notifyIntegrationEvent.setData(this.jsonHandlingService.toJsonSafe(data)); + + this.notifyIntegrationEventHandler.handle(notifyIntegrationEvent); + } +} diff --git a/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java index 8e793f942..bf7c836a4 100644 --- a/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java @@ -345,15 +345,7 @@ public class DepositServiceImpl implements DepositService { private void createDmpDepositNotificationEvent(DmpEntity dmp, UserEntity user) throws InvalidApplicationException { NotifyIntegrationEvent event = new NotifyIntegrationEvent(); event.setUserId(user.getId()); - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).disableTracking().userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - if (query.count() == 0) return; - - List contactPairs = new ArrayList<>(); - contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); - NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); - event.setContactHint(this.jsonHandlingService.toJsonSafe(contactData)); event.setNotificationType(this.notificationProperties.getDmpDepositType()); NotificationFieldData data = new NotificationFieldData(); List fieldInfoList = new ArrayList<>(); diff --git a/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java index eb554aa54..ec1fcb363 100644 --- a/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java @@ -388,16 +388,6 @@ public class DescriptionServiceImpl implements DescriptionService { NotifyIntegrationEvent event = new NotifyIntegrationEvent(); event.setUserId(user.getId()); - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).disableTracking().userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - - if (query.count() == 0) throw new MyValidationException(this.errors.getDmpMissingUserContactInfo().getCode(), this.errors.getDmpMissingUserContactInfo().getMessage()); - - List contactPairs = new ArrayList<>(); - contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); - NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); - event.setContactHint(this.jsonHandlingService.toJsonSafe(contactData)); - this.applyNotificationType(description.getStatus(), event); NotificationFieldData data = new NotificationFieldData(); List fieldInfoList = new ArrayList<>(); diff --git a/backend/web/src/main/resources/config/notification-devel.yml b/backend/web/src/main/resources/config/notification-devel.yml index 9fcb3db83..91df5d19b 100644 --- a/backend/web/src/main/resources/config/notification-devel.yml +++ b/backend/web/src/main/resources/config/notification-devel.yml @@ -5,6 +5,7 @@ notification: dmpFinalisedType: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E descriptionModifiedType: 4FDBFA80-7A71-4A69-B854-67CBB70648F1 descriptionFinalisedType: 33790bad-94d4-488a-8ee2-7f6295ca18ea + descriptionAnnotationCreated: db1e99d2-a240-4e75-9bb2-ef25b234c1f0 mergeAccountConfirmationType: BFE68845-CB05-4C5A-A03D-29161A7C9660 removeCredentialConfirmationType: C9BC3F16-057E-4BBA-8A5F-36BD835E5604 dmpDepositType: 55736F7A-83AB-4190-AF43-9D031A6F9612 diff --git a/backend/web/src/main/resources/config/queue.yml b/backend/web/src/main/resources/config/queue.yml index 444ac0507..a3d217e24 100644 --- a/backend/web/src/main/resources/config/queue.yml +++ b/backend/web/src/main/resources/config/queue.yml @@ -54,6 +54,7 @@ queue: enable: true options: exchange: null + annotation-created-topic: annotation.created rabbitmq: enable: true interval-seconds: 3