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

This commit is contained in:
Efstratios Giannopoulos 2023-12-13 11:46:02 +02:00
commit 8eda8402ab
126 changed files with 4258 additions and 1967 deletions

View File

@ -0,0 +1,32 @@
package eu.eudat.commons.enums.notification;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.commons.enums.EnumUtils;
import eu.eudat.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum NotificationContactType implements DatabaseEnum<Short> {
EMAIL((short)0),
SLACK_BROADCAST((short)1),
SMS((short)2),
IN_APP((short)3);
private final Short value;
NotificationContactType(Short value) {
this.value = value;
}
@JsonValue
public Short getValue() {
return value;
}
private static final Map<Short, NotificationContactType> map = EnumUtils.getEnumValueMap(NotificationContactType.class);
public static NotificationContactType of(Short i) {
return map.get(i);
}
}

View File

@ -0,0 +1,33 @@
package eu.eudat.commons.enums.notification;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.commons.enums.EnumUtils;
import eu.eudat.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum NotificationNotifyState implements DatabaseEnum<Short> {
PENDING((short)0),
PROCESSING((short)1),
SUCCESSFUL((short)2),
ERROR((short)3),
OMITTED((short)4);
private final Short value;
NotificationNotifyState(Short value) {
this.value = value;
}
@JsonValue
public Short getValue() {
return value;
}
private static final Map<Short, NotificationNotifyState> map = EnumUtils.getEnumValueMap(NotificationNotifyState.class);
public static NotificationNotifyState of(Short i) {
return map.get(i);
}
}

View File

@ -0,0 +1,32 @@
package eu.eudat.commons.enums.notification;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.commons.enums.EnumUtils;
import eu.eudat.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum NotificationTrackingProcess implements DatabaseEnum<Short> {
PENDING((short)0),
PROCESSING((short)1),
COMPLETED((short)2),
ERROR((short)3),
OMITTED((short)4);
private final Short value;
NotificationTrackingProcess(Short value) {
this.value = value;
}
@JsonValue
public Short getValue() {
return value;
}
private static final Map<Short, NotificationTrackingProcess> map = EnumUtils.getEnumValueMap(NotificationTrackingProcess.class);
public static NotificationTrackingProcess of(Short i) {
return map.get(i);
}
}

View File

@ -0,0 +1,35 @@
package eu.eudat.commons.enums.notification;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.data.converters.enums.DatabaseEnum;
import eu.eudat.commons.enums.EnumUtils;
import java.util.Map;
public enum NotificationTrackingState implements DatabaseEnum<Short> {
UNDEFINED((short)0),
NA((short)1),
QUEUED((short)2),
SENT((short)3),
DELIVERED((short)4),
UNDELIVERED((short)5),
FAILED((short)6),
UNSENT((short)7);
private final Short value;
NotificationTrackingState(Short value) {
this.value = value;
}
@JsonValue
public Short getValue() {
return value;
}
private static final Map<Short, NotificationTrackingState> map = EnumUtils.getEnumValueMap(NotificationTrackingState.class);
public static NotificationTrackingState of(Short i) {
return map.get(i);
}
}

View File

@ -0,0 +1,36 @@
package eu.eudat.commons.types.notification;
public class Attachment {
private String fileRef, fileName, mimeType;
public Attachment(String fileRef, String fileName, String mimeType) {
this.fileRef = fileRef;
this.fileName = fileName;
this.mimeType = mimeType;
}
public String getFileRef() {
return fileRef;
}
public void setFileRef(String fileRef) {
this.fileRef = fileRef;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
}

View File

@ -0,0 +1,33 @@
package eu.eudat.commons.types.notification;
import eu.eudat.commons.enums.ContactInfoType;
public class ContactPair {
private ContactInfoType type;
private String Contact;
public ContactPair(ContactInfoType type, String contact) {
this.type = type;
Contact = contact;
}
public ContactPair() {
}
public ContactInfoType getType() {
return type;
}
public void setType(ContactInfoType type) {
this.type = type;
}
public String getContact() {
return Contact;
}
public void setContact(String contact) {
Contact = contact;
}
}

View File

@ -0,0 +1,42 @@
package eu.eudat.commons.types.notification;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.HashMap;
import java.util.Map;
public enum DataType {
Integer(0),
Decimal(1),
Double(2),
DateTime(3),
TimeSpan(4),
String(5);
private static final Map<Integer, DataType> values = new HashMap<>();
private final Integer mappedName;
//For jackson parsing (used by MVC)
@JsonValue
public Integer getMappedName() {
return mappedName;
}
static {
for (DataType e : values()) {
values.put(e.asInt(), e);
}
}
private DataType(int mappedName) {
this.mappedName = mappedName;
}
public Integer asInt() {
return this.mappedName;
}
public static DataType fromString(Integer value) {
return values.getOrDefault(value, Integer);
}
}

View File

@ -0,0 +1,40 @@
package eu.eudat.commons.types.notification;
public class FieldInfo {
private String key;
private DataType type;
private String value;
public FieldInfo(String key, DataType type, String value) {
this.key = key;
this.type = type;
this.value = value;
}
public FieldInfo() {
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public DataType getType() {
return type;
}
public void setType(DataType type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,31 @@
package eu.eudat.commons.types.notification;
import java.util.List;
import java.util.UUID;
public class InAppTrackingData {
private UUID inAppNotificationId;
private List<TrackingTrace> traces;
public InAppTrackingData(UUID inAppNotificationId, List<TrackingTrace> traces) {
this.inAppNotificationId = inAppNotificationId;
this.traces = traces;
}
public UUID getInAppNotificationId() {
return inAppNotificationId;
}
public void setInAppNotificationId(UUID inAppNotificationId) {
this.inAppNotificationId = inAppNotificationId;
}
public List<TrackingTrace> getTraces() {
return traces;
}
public void setTraces(List<TrackingTrace> traces) {
this.traces = traces;
}
}

View File

@ -0,0 +1,39 @@
package eu.eudat.commons.types.notification;
import java.util.List;
public class NotificationContactData {
private List<ContactPair> contacts;
private List<ContactPair> BCC;
private List<ContactPair> CC;
public NotificationContactData(List<ContactPair> contacts, List<ContactPair> BCC, List<ContactPair> CC) {
this.contacts = contacts;
this.BCC = BCC;
this.CC = CC;
}
public List<ContactPair> getContacts() {
return contacts;
}
public void setContacts(List<ContactPair> contacts) {
this.contacts = contacts;
}
public List<ContactPair> getBCC() {
return BCC;
}
public void setBCC(List<ContactPair> BCC) {
this.BCC = BCC;
}
public List<ContactPair> getCC() {
return CC;
}
public void setCC(List<ContactPair> CC) {
this.CC = CC;
}
}

View File

@ -0,0 +1,32 @@
package eu.eudat.commons.types.notification;
import java.util.List;
public class NotificationFieldData {
private List<FieldInfo> fields;
private List<Attachment> attachments;
public NotificationFieldData(List<FieldInfo> fields, List<Attachment> attachments) {
this.fields = fields;
this.attachments = attachments;
}
public NotificationFieldData() {
}
public List<FieldInfo> getFields() {
return fields;
}
public void setFields(List<FieldInfo> fields) {
this.fields = fields;
}
public List<Attachment> getAttachments() {
return attachments;
}
public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
}
}

View File

@ -0,0 +1,30 @@
package eu.eudat.commons.types.notification;
import java.util.List;
public class RouteTrackingData {
private String trackingId;
private List<TrackingTrace> traces;
public RouteTrackingData(String trackingId, List<TrackingTrace> traces) {
this.trackingId = trackingId;
this.traces = traces;
}
public String getTrackingId() {
return trackingId;
}
public void setTrackingId(String trackingId) {
this.trackingId = trackingId;
}
public List<TrackingTrace> getTraces() {
return traces;
}
public void setTraces(List<TrackingTrace> traces) {
this.traces = traces;
}
}

View File

@ -0,0 +1,30 @@
package eu.eudat.commons.types.notification;
import java.time.Instant;
public class TrackingTrace {
private Instant at;
private String data;
public TrackingTrace(Instant at, String data) {
this.at = at;
this.data = data;
}
public Instant getAt() {
return at;
}
public void setAt(Instant at) {
this.at = at;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

View File

@ -0,0 +1,20 @@
package eu.eudat.configurations.notification;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(NotificationProperties.class)
public class NotificationConfiguration {
private final NotificationProperties properties;
@Autowired
public NotificationConfiguration(NotificationProperties properties) {
this.properties = properties;
}
public NotificationProperties getProperties() {
return properties;
}
}

View File

@ -0,0 +1,89 @@
package eu.eudat.configurations.notification;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "notification")
public class NotificationProperties {
private String confirmation;
private String dataManagementPlan;
private String finalised;
private String mergeConfirmation;
private String modified;
private String modifiedFinalised;
private String publish;
private String template;
private String unlinkConfirmation;
public String getConfirmation() {
return confirmation;
}
public void setConfirmation(String confirmation) {
this.confirmation = confirmation;
}
public String getDataManagementPlan() {
return dataManagementPlan;
}
public void setDataManagementPlan(String dataManagementPlan) {
this.dataManagementPlan = dataManagementPlan;
}
public String getFinalised() {
return finalised;
}
public void setFinalised(String finalised) {
this.finalised = finalised;
}
public String getMergeConfirmation() {
return mergeConfirmation;
}
public void setMergeConfirmation(String mergeConfirmation) {
this.mergeConfirmation = mergeConfirmation;
}
public String getModified() {
return modified;
}
public void setModified(String modified) {
this.modified = modified;
}
public String getModifiedFinalised() {
return modifiedFinalised;
}
public void setModifiedFinalised(String modifiedFinalised) {
this.modifiedFinalised = modifiedFinalised;
}
public String getPublish() {
return publish;
}
public void setPublish(String publish) {
this.publish = publish;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
public String getUnlinkConfirmation() {
return unlinkConfirmation;
}
public void setUnlinkConfirmation(String unlinkConfirmation) {
this.unlinkConfirmation = unlinkConfirmation;
}
}

View File

@ -0,0 +1,177 @@
package eu.eudat.data;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.data.converters.enums.IsActiveConverter;
import gr.cite.queueinbox.entity.QueueInbox;
import gr.cite.queueinbox.entity.QueueInboxStatus;
import jakarta.persistence.*;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "\"QueueInbox\"")
public class QueueInboxEntity implements QueueInbox {
@Id
@Column(name = "\"id\"", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID id;
public final static String _id = "id";
@Column(name = "\"queue\"", nullable = false, length = 50)
private String queue;
public final static String _queue = "queue";
@Column(name = "\"exchange\"", nullable = false, length = 50)
private String exchange;
public final static String _exchange = "exchange";
@Column(name = "\"route\"", nullable = false, length = 50)
private String route;
public final static String _route = "route";
@Column(name = "\"application_id\"", nullable = false, length = 100)
private String applicationId;
public final static String _applicationId = "applicationId";
@Column(name = "\"message_id\"", columnDefinition = "uuid", nullable = false)
private UUID messageId;
public final static String _messageId = "messageId";
@Column(name = "\"message\"", columnDefinition = "json", nullable = false)
private String message;
public final static String _message = "message";
@Column(name = "\"retry_count\"", nullable = true)
private Integer retryCount;
public final static String _retryCount = "retryCount";
@Column(name = "\"tenant\"", columnDefinition = "uuid", nullable = true)
private UUID tenantId;
public final static String _tenantId = "tenantId";
@Column(name = "\"is_active\"", length = 20, nullable = false)
@Convert(converter = IsActiveConverter.class)
private IsActive isActive;
public final static String _isActive = "isActive";
//TODO: as integer
@Column(name = "\"status\"", length = 50, nullable = false)
@Enumerated(EnumType.STRING)
private QueueInboxStatus status;
public final static String _status = "status";
@Column(name = "\"created_at\"", nullable = false)
private Instant createdAt;
public final static String _createdAt = "createdAt";
@Column(name = "\"updated_at\"", nullable = false)
@Version
private Instant updatedAt;
public final static String _updatedAt = "updatedAt";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getExchange() {
return exchange;
}
public void setExchange(String exchange) {
this.exchange = exchange;
}
public String getRoute() {
return route;
}
public void setRoute(String route) {
this.route = route;
}
public UUID getMessageId() {
return messageId;
}
public void setMessageId(UUID messageId) {
this.messageId = messageId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public UUID getTenantId() {
return tenantId;
}
public void setTenantId(UUID tenantId) {
this.tenantId = tenantId;
}
public IsActive getIsActive() {
return isActive;
}
public void setIsActive(IsActive isActive) {
this.isActive = isActive;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
public String getQueue() {
return queue;
}
public void setQueue(String queue) {
this.queue = queue;
}
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
@Override
public Integer getRetryCount() {
return retryCount;
}
public void setRetryCount(Integer retryCount) {
this.retryCount = retryCount;
}
public QueueInboxStatus getStatus() {
return status;
}
public void setStatus(QueueInboxStatus status) {
this.status = status;
}
}

View File

@ -0,0 +1,175 @@
package eu.eudat.data;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.data.converters.enums.IsActiveConverter;
import gr.cite.queueoutbox.entity.QueueOutbox;
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
import jakarta.persistence.*;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "\"QueueOutbox\"")
public class QueueOutboxEntity implements QueueOutbox {
@Id
@Column(name = "\"id\"", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID id;
public final static String _id = "id";
@Column(name = "\"exchange\"", nullable = false, length = 50)
private String exchange;
public final static String _exchange = "exchange";
@Column(name = "\"route\"", length = 50)
private String route;
public final static String _route = "route";
@Column(name = "\"message_id\"", columnDefinition = "uuid", nullable = false)
private UUID messageId;
public final static String _messageId = "messageId";
@Column(name = "\"message\"", columnDefinition = "json", nullable = false)
private String message;
public final static String _message = "message";
//TODO: as integer
@Column(name = "\"notify_status\"", length = 20, nullable = false)
@Enumerated(EnumType.STRING)
private QueueOutboxNotifyStatus notifyStatus;
public final static String _notifyStatus = "notifyStatus";
@Column(name = "\"retry_count\"", nullable = false)
private int retryCount;
public final static String _retryCount = "retryCount";
@Column(name = "\"published_at\"", nullable = true)
private Instant publishedAt;
public final static String _publishedAt = "publishedAt";
@Column(name = "\"confirmed_at\"", nullable = true)
private Instant confirmedAt;
public final static String _confirmedAt = "confirmedAt";
@Column(name = "\"tenant\"", columnDefinition = "uuid", nullable = true)
private UUID tenantId;
public final static String _tenantId = "tenantId";
@Column(name = "\"is_active\"", length = 20, nullable = false)
@Convert(converter = IsActiveConverter.class)
private IsActive isActive;
public final static String _isActive = "isActive";
@Column(name = "\"created_at\"", nullable = false)
private Instant createdAt;
public final static String _createdAt = "createdAt";
@Column(name = "\"updated_at\"", nullable = false)
private Instant updatedAt;
public final static String _updatedAt = "updatedAt";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getExchange() {
return exchange;
}
public void setExchange(String exchange) {
this.exchange = exchange;
}
public String getRoute() {
return route;
}
public void setRoute(String route) {
this.route = route;
}
public UUID getMessageId() {
return messageId;
}
public void setMessageId(UUID messageId) {
this.messageId = messageId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public QueueOutboxNotifyStatus getNotifyStatus() {
return notifyStatus;
}
public void setNotifyStatus(QueueOutboxNotifyStatus notifyStatus) {
this.notifyStatus = notifyStatus;
}
public Integer getRetryCount() {
return retryCount;
}
public void setRetryCount(Integer retryCount) {
this.retryCount = retryCount;
}
public Instant getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(Instant publishedAt) {
this.publishedAt = publishedAt;
}
public Instant getConfirmedAt() {
return confirmedAt;
}
public void setConfirmedAt(Instant confirmedAt) {
this.confirmedAt = confirmedAt;
}
public UUID getTenantId() {
return tenantId;
}
public void setTenantId(UUID tenantId) {
this.tenantId = tenantId;
}
public IsActive getIsActive() {
return isActive;
}
public void setIsActive(IsActive isActive) {
this.isActive = isActive;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
}

View File

@ -0,0 +1,12 @@
package eu.eudat.data.converters.enums.notification;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.data.converters.enums.DatabaseEnumConverter;
import jakarta.persistence.Converter;
@Converter
public class NotificationContactTypeConverter extends DatabaseEnumConverter<NotificationContactType, Short> {
public NotificationContactType of(Short i) {
return NotificationContactType.of(i);
}
}

View File

@ -0,0 +1,12 @@
package eu.eudat.data.converters.enums.notification;
import eu.eudat.commons.enums.notification.NotificationNotifyState;
import eu.eudat.data.converters.enums.DatabaseEnumConverter;
import jakarta.persistence.Converter;
@Converter
public class NotificationNotifyStateConverter extends DatabaseEnumConverter<NotificationNotifyState, Short> {
public NotificationNotifyState of(Short i) {
return NotificationNotifyState.of(i);
}
}

View File

@ -0,0 +1,12 @@
package eu.eudat.data.converters.enums.notification;
import eu.eudat.commons.enums.notification.NotificationTrackingProcess;
import eu.eudat.data.converters.enums.DatabaseEnumConverter;
import jakarta.persistence.Converter;
@Converter
public class NotificationTrackingProcessConverter extends DatabaseEnumConverter<NotificationTrackingProcess, Short> {
public NotificationTrackingProcess of(Short i) {
return NotificationTrackingProcess.of(i);
}
}

View File

@ -0,0 +1,13 @@
package eu.eudat.data.converters.enums.notification;
import eu.eudat.commons.enums.notification.NotificationTrackingState;
import eu.eudat.data.converters.enums.DatabaseEnumConverter;
import jakarta.persistence.Converter;
@Converter
public class NotificationTrackingStateConverter extends DatabaseEnumConverter<NotificationTrackingState, Short> {
public NotificationTrackingState of(Short i) {
return NotificationTrackingState.of(i);
}
}

View File

@ -0,0 +1,225 @@
package eu.eudat.data.notification;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.enums.notification.NotificationNotifyState;
import eu.eudat.commons.enums.notification.NotificationTrackingProcess;
import eu.eudat.commons.enums.notification.NotificationTrackingState;
import eu.eudat.data.converters.enums.IsActiveConverter;
import eu.eudat.data.converters.enums.notification.NotificationContactTypeConverter;
import eu.eudat.data.converters.enums.notification.NotificationNotifyStateConverter;
import eu.eudat.data.converters.enums.notification.NotificationTrackingProcessConverter;
import eu.eudat.data.converters.enums.notification.NotificationTrackingStateConverter;
import eu.eudat.data.tenant.TenantScopedBaseEntity;
import jakarta.persistence.*;
import jakarta.persistence.Table;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "\"ntf_Notification\"")
public class NotificationEntity extends TenantScopedBaseEntity {
public static class Field {
public final static String _id = "id";
public static final String _userId = "userId";
public static final String _type = "type";
public static final String _contactTypeHint = "contactTypeHint";
public static final String _contactHint = "contactHint";
public final static String _notifiedAt = "notifiedAt";
public final static String _isActive = "isActive";
public final static String _createdAt = "createdAt";
public final static String _updatedAt = "updatedAt";
public final static String _data = "data";
public final static String _retryCount = "retryCount";
public final static String _notifyState = "notifyState";
public final static String _notifiedWith = "notifiedWith";
public final static String _trackingState = "trackingState";
public final static String _trackingProcess = "trackingProcess";
public final static String _trackingData = "trackingData";
}
@Id
@Column(name = "\"id\"", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID id;
@Column(name = "\"user\"", columnDefinition = "uuid")
private UUID userId;
@Column(name = "\"type\"", columnDefinition = "uuid", nullable = false)
private UUID type;
@Column(name = "\"contact_type_hint\"")
@Convert(converter = NotificationContactTypeConverter.class)
private NotificationContactType contactTypeHint;
@Column(name = "\"contact_hint\"")
private String contactHint;
@Column(name = "\"notify_state\"", nullable = false)
@Convert(converter = NotificationNotifyStateConverter.class)
private NotificationNotifyState notifyState;
@Column(name = "\"notified_with\"")
@Convert(converter = NotificationContactTypeConverter.class)
private NotificationContactType notifiedWith;
@Column(name = "\"notified_at\"")
private Instant notifiedAt;
@Column(name = "\"data\"")
private String data;
@Column(name = "\"retry_count\"")
private Integer retryCount;
@Column(name = "\"is_active\"", length = 20, nullable = false)
@Convert(converter = IsActiveConverter.class)
private IsActive isActive;
@Column(name = "\"created_at\"", nullable = false)
private Instant createdAt;
@Column(name = "\"updated_at\"", nullable = false)
private Instant updatedAt;
@Column(name = "\"tracking_state\"", nullable = false)
@Convert(converter = NotificationTrackingStateConverter.class)
private NotificationTrackingState trackingState;
@Column(name = "\"tracking_process\"", nullable = false)
@Convert(converter = NotificationTrackingProcessConverter.class)
private NotificationTrackingProcess trackingProcess;
@Column(name = "\"tracking_data\"")
private String trackingData;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public UUID getType() {
return type;
}
public void setType(UUID type) {
this.type = type;
}
public NotificationContactType getContactTypeHint() {
return contactTypeHint;
}
public void setContactTypeHint(NotificationContactType contactTypeHint) {
this.contactTypeHint = contactTypeHint;
}
public String getContactHint() {
return contactHint;
}
public void setContactHint(String contactHint) {
this.contactHint = contactHint;
}
public NotificationContactType getNotifiedWith() {
return notifiedWith;
}
public void setNotifiedWith(NotificationContactType notifiedWith) {
this.notifiedWith = notifiedWith;
}
public NotificationNotifyState getNotifyState() {
return notifyState;
}
public void setNotifyState(NotificationNotifyState notifyState) {
this.notifyState = notifyState;
}
public Instant getNotifiedAt() {
return notifiedAt;
}
public void setNotifiedAt(Instant notifiedAt) {
this.notifiedAt = notifiedAt;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Integer getRetryCount() {
return retryCount;
}
public void setRetryCount(Integer retryCount) {
this.retryCount = retryCount;
}
public IsActive getIsActive() {
return isActive;
}
public void setIsActive(IsActive isActive) {
this.isActive = isActive;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
public NotificationTrackingState getTrackingState() {
return trackingState;
}
public void setTrackingState(NotificationTrackingState trackingState) {
this.trackingState = trackingState;
}
public NotificationTrackingProcess getTrackingProcess() {
return trackingProcess;
}
public void setTrackingProcess(NotificationTrackingProcess trackingProcess) {
this.trackingProcess = trackingProcess;
}
public String getTrackingData() {
return trackingData;
}
public void setTrackingData(String trackingData) {
this.trackingData = trackingData;
}
}

View File

@ -0,0 +1,47 @@
package eu.eudat.integrationevent;
import eu.eudat.integrationevent.inbox.InboxProperties;
import eu.eudat.integrationevent.outbox.OutboxProperties;
import gr.cite.queueinbox.repository.InboxRepository;
import gr.cite.rabbitmq.RabbitConfigurer;
import gr.cite.rabbitmq.consumer.InboxBindings;
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;
import java.util.List;
@Configuration
@EnableConfigurationProperties({OutboxProperties.class, InboxProperties.class})
@ConditionalOnProperty(prefix = "queue.rabbitmq", name = "listenerEnabled")
public class AppRabbitConfigurer extends RabbitConfigurer {
private ApplicationContext applicationContext;
private InboxProperties inboxProperties;
public AppRabbitConfigurer(ApplicationContext applicationContext, InboxProperties inboxProperties) {
this.applicationContext = applicationContext;
this.inboxProperties = inboxProperties;
}
// @Bean
public InboxBindings inboxBindingsCreator() {
List<String> bindingItems = new ArrayList<>();
bindingItems.addAll(this.inboxProperties.getUserRemovalTopic());
bindingItems.addAll(this.inboxProperties.getUserTouchedTopic());
return new InboxBindings(bindingItems);
}
// @Bean
public InboxCreator inboxCreator() {
return (params) -> {
InboxRepository inboxRepository = this.applicationContext.getBean(InboxRepository.class);
return inboxRepository.create(params) != null;
};
}
}

View File

@ -0,0 +1,30 @@
package eu.eudat.integrationevent;
import eu.eudat.integrationevent.inbox.InboxProperties;
import eu.eudat.integrationevent.inbox.InboxRepositoryImpl;
import gr.cite.queueinbox.InboxConfigurer;
import gr.cite.queueinbox.repository.InboxRepository;
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;
@Configuration
@EnableConfigurationProperties({InboxProperties.class})
@ConditionalOnProperty(prefix = "queue.task.listener", name = "enable", matchIfMissing = false)
public class InboxIntegrationEventConfigurer extends InboxConfigurer {
private ApplicationContext applicationContext;
private InboxProperties inboxProperties;
public InboxIntegrationEventConfigurer(ApplicationContext applicationContext, InboxProperties inboxProperties) {
this.applicationContext = applicationContext;
this.inboxProperties = inboxProperties;
}
@Bean
public InboxRepository inboxRepositoryCreator() {
return new InboxRepositoryImpl(this.applicationContext, this.inboxProperties);
}
}

View File

@ -0,0 +1,20 @@
package eu.eudat.integrationevent;
import gr.cite.rabbitmq.IntegrationEventContext;
import java.util.UUID;
public class IntegrationEventContextImpl implements IntegrationEventContext {
private UUID tenant;
public IntegrationEventContextImpl() {
}
public UUID getTenant() {
return tenant;
}
public void setTenant(UUID tenant) {
this.tenant = tenant;
}
}

View File

@ -0,0 +1,69 @@
package eu.eudat.integrationevent;
import eu.eudat.integrationevent.outbox.OutboxProperties;
import eu.eudat.integrationevent.outbox.OutboxRepositoryImpl;
import gr.cite.queueoutbox.IntegrationEventContextCreator;
import gr.cite.queueoutbox.OutboxConfigurer;
import gr.cite.queueoutbox.repository.OutboxRepository;
import gr.cite.rabbitmq.IntegrationEventMessageConstants;
import gr.cite.rabbitmq.RabbitProperties;
import gr.cite.rabbitmq.broker.MessageHydrator;
import org.springframework.amqp.core.MessageProperties;
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.nio.charset.StandardCharsets;
import java.sql.Date;
import java.time.Instant;
import java.util.UUID;
@Configuration
@EnableConfigurationProperties({OutboxProperties.class})
@ConditionalOnProperty(prefix = "queue.task.publisher", name = "enable", matchIfMissing = false)
public class OutboxIntegrationEventConfigurer extends OutboxConfigurer {
private ApplicationContext applicationContext;
private OutboxProperties outboxProperties;
public OutboxIntegrationEventConfigurer(ApplicationContext applicationContext, OutboxProperties outboxProperties) {
this.applicationContext = applicationContext;
this.outboxProperties = outboxProperties;
}
@Bean
public MessageHydrator messageHydrator(RabbitProperties rabbitProperties) {
return (message, event, eventContext) -> {
MessageProperties messageProperties = message.getMessageProperties();
messageProperties.setAppId(rabbitProperties.getAppId());
messageProperties.setContentEncoding(StandardCharsets.UTF_8.displayName());
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
//messageProperties.setUserId(userContext.getCurrentUser().toString());
messageProperties.setTimestamp(Date.from(Instant.now()));
messageProperties.setMessageId(event.getMessageId().toString());
if (eventContext != null) {
UUID tenant = ((IntegrationEventContextImpl) eventContext).getTenant();
if (tenant != null) {
messageProperties.setHeader(IntegrationEventMessageConstants.TENANT, tenant);
}
}
return message;
};
}
@Bean
public IntegrationEventContextCreator integrationEventContextCreator() {
return (message) -> new IntegrationEventContextImpl();
}
@Bean
public OutboxRepository outboxRepositoryCreator() {
return new OutboxRepositoryImpl(this.applicationContext, this.outboxProperties);
}
}

View File

@ -0,0 +1,11 @@
package eu.eudat.integrationevent;
import eu.eudat.integrationevent.outbox.OutboxProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(OutboxProperties.class)
public class OutboxPropertiesConfiguration {
}

View File

@ -0,0 +1,18 @@
package eu.eudat.integrationevent;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class TrackedEvent {
public String trackingContextTag;
public String getTrackingContextTag() {
return trackingContextTag;
}
public void setTrackingContextTag(String trackingContextTag) {
this.trackingContextTag = trackingContextTag;
}
}

View File

@ -0,0 +1,5 @@
package eu.eudat.integrationevent.inbox;
public interface ConsistencyHandler<T extends ConsistencyPredicates> {
Boolean isConsistent(T consistencyPredicates);
}

View File

@ -0,0 +1,4 @@
package eu.eudat.integrationevent.inbox;
public interface ConsistencyPredicates {
}

View File

@ -0,0 +1,8 @@
package eu.eudat.integrationevent.inbox;
public enum EventProcessingStatus {
Error,
Success,
Postponed,
Discard
}

View File

@ -0,0 +1,56 @@
package eu.eudat.integrationevent.inbox;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import org.springframework.security.oauth2.core.ClaimAccessor;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class InboxPrincipal implements MyPrincipal, ClaimAccessor {
private Map<String, Object> claims;
private boolean isAuthenticated;
public InboxPrincipal(Boolean isAuthenticated, String name) {
this.claims = new HashMap<>();
this.put(JwtClaimNames.SUB, name);
this.isAuthenticated = isAuthenticated;
}
@Override
public Boolean isAuthenticated() {
return this.isAuthenticated;
}
@Override
public Map<String, Object> getClaims() {
return this.claims;
}
@Override
public List<String> getClaimAsStringList(String claim) {
if (claims == null) return null;
return this.getClaimAsStringList(claim);
}
@Override
public String getName() {
return this.getClaimAsString(JwtClaimNames.SUB);
}
public void put(String key, Object value) {
this.claims.put(key, value);
}
public static InboxPrincipal build(IntegrationEventProperties properties) {
InboxPrincipal inboxPrincipal = new InboxPrincipal(true, "IntegrationEventQueueAppId");
inboxPrincipal.put("client_id", properties.getAppId());
inboxPrincipal.put("active", "true");
inboxPrincipal.put("nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString());
inboxPrincipal.put("exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString());
return inboxPrincipal;
}
}

View File

@ -0,0 +1,42 @@
package eu.eudat.integrationevent.inbox;
import org.springframework.boot.context.properties.ConfigurationProperties;
//import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@Validated
@ConfigurationProperties(prefix = "queue.task.listener.options")
//@ConstructorBinding
public class InboxProperties {
@NotNull
private final String exchange;
@NotNull
private final List<String> userRemovalTopic;
@NotNull
private final List<String> userTouchedTopic;
public InboxProperties(
String exchange,
List<String> userRemovalTopic,
List<String> userTouchedTopic) {
this.exchange = exchange;
this.userRemovalTopic = userRemovalTopic;
this.userTouchedTopic = userTouchedTopic;
}
public List<String> getUserRemovalTopic() {
return userRemovalTopic;
}
public List<String> getUserTouchedTopic() {
return userTouchedTopic;
}
public String getExchange() {
return exchange;
}
}

View File

@ -0,0 +1,338 @@
package eu.eudat.integrationevent.inbox;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.fake.FakeRequestScope;
import eu.eudat.data.QueueInboxEntity;
import eu.eudat.integrationevent.TrackedEvent;
import eu.eudat.integrationevent.inbox.userremoval.UserRemovalIntegrationEventHandler;
import eu.eudat.integrationevent.inbox.usertouched.UserTouchedIntegrationEventHandler;
import eu.eudat.query.QueueInboxQuery;
import gr.cite.queueinbox.entity.QueueInbox;
import gr.cite.queueinbox.entity.QueueInboxStatus;
import gr.cite.queueinbox.repository.CandidateInfo;
import gr.cite.queueinbox.repository.InboxRepository;
import gr.cite.queueinbox.task.MessageOptions;
import gr.cite.rabbitmq.consumer.InboxCreatorParams;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import jakarta.persistence.*;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import java.time.Instant;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.function.Function;
public class InboxRepositoryImpl implements InboxRepository {
protected final ApplicationContext applicationContext;
private final Random random = new Random();
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(InboxRepositoryImpl.class));
private final JsonHandlingService jsonHandlingService;
private final InboxProperties inboxProperties;
public InboxRepositoryImpl(
ApplicationContext applicationContext,
InboxProperties inboxProperties
) {
this.applicationContext = applicationContext;
this.jsonHandlingService = this.applicationContext.getBean(JsonHandlingService.class);
this.inboxProperties = inboxProperties;
}
@Override
public CandidateInfo candidate(Instant lastCandidateCreationTimestamp, MessageOptions options) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
CandidateInfo candidate = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class)
.isActives(IsActive.Active)
.status(QueueInboxStatus.PENDING, QueueInboxStatus.ERROR)
.retryThreshold(options.getRetryThreashold())
.createdAfter(lastCandidateCreationTimestamp)
.ordering(new Ordering().addAscending(QueueInboxEntity._createdAt))
.first();
if (item != null) {
QueueInboxStatus prevState = item.getStatus();
item.setStatus(QueueInboxStatus.PROCESSING);
entityManager.merge(item);
entityManager.flush();
candidate = new CandidateInfo();
candidate.setId(item.getId());
candidate.setCreatedAt(item.getCreatedAt());
candidate.setPreviousState(prevState);
}
transaction.commit();
} catch (OptimisticLockException ex) {
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
this.logger.debug("Concurrency exception getting queue inbox. Skipping: {} ", ex.getMessage());
if (transaction != null) transaction.rollback();
candidate = null;
} catch (Exception ex) {
this.logger.error("Problem getting list of queue inbox. Skipping: {}", ex.getMessage(), ex);
if (transaction != null) transaction.rollback();
candidate = null;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem getting list of queue inbox. Skipping: {}", ex.getMessage(), ex);
}
return candidate;
}
@Override
public Boolean shouldOmit(CandidateInfo candidate, Function<QueueInbox, Boolean> shouldOmit) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first();
if (item == null) {
this.logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidate.getId());
} else {
if (shouldOmit.apply(item)) {
item.setStatus(QueueInboxStatus.OMITTED);
entityManager.merge(item);
entityManager.flush();
success = true;
}
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return success;
}
@Override
public boolean shouldWait(CandidateInfo candidate, Function<QueueInbox, Boolean> itIsTimeFunc) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first();
if (item.getRetryCount() != null && item.getRetryCount() >= 1) {
Boolean itIsTime = itIsTimeFunc.apply(item);
if (!itIsTime) {
item.setStatus(candidate.getPreviousState());
entityManager.merge(item);
entityManager.flush();
success = true;
}
success = !itIsTime;
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return success;
}
@Override
public QueueInbox create(InboxCreatorParams inboxCreatorParams) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
QueueInboxEntity queueMessage = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
queueMessage = this.createQueueInboxEntity(inboxCreatorParams);
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(queueMessage);
entityManager.flush();
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return queueMessage;
}
private QueueInboxEntity createQueueInboxEntity(InboxCreatorParams inboxCreatorParams) {
QueueInboxEntity queueMessage = new QueueInboxEntity();
queueMessage.setId(UUID.randomUUID());
queueMessage.setTenantId(null);
queueMessage.setExchange(this.inboxProperties.getExchange());
queueMessage.setRoute(inboxCreatorParams.getRoutingKey());
queueMessage.setQueue(inboxCreatorParams.getQueueName());
queueMessage.setApplicationId(inboxCreatorParams.getAppId());
queueMessage.setMessageId(UUID.fromString(inboxCreatorParams.getMessageId()));
queueMessage.setMessage(inboxCreatorParams.getMessageBody());
queueMessage.setIsActive(IsActive.Active);
queueMessage.setStatus(QueueInboxStatus.PENDING);
queueMessage.setRetryCount(0);
queueMessage.setCreatedAt(Instant.now());
return queueMessage;
}
@Override
public Boolean emit(CandidateInfo candidateInfo) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
QueueInboxEntity queueInboxMessage = queryFactory.query(QueueInboxQuery.class).ids(candidateInfo.getId()).first();
if (queueInboxMessage == null) {
this.logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidateInfo.getId());
} else {
EventProcessingStatus status = this.processMessage(queueInboxMessage.getRoute(), queueInboxMessage.getMessageId().toString(), queueInboxMessage.getApplicationId(), queueInboxMessage.getMessage());
switch (status) {
case Success: {
queueInboxMessage.setStatus(QueueInboxStatus.SUCCESSFUL);
break;
}
case Postponed: {
queueInboxMessage.setStatus(QueueInboxStatus.PARKED);
break;
}
case Error: {
queueInboxMessage.setStatus(QueueInboxStatus.ERROR);
queueInboxMessage.setRetryCount(queueInboxMessage.getRetryCount() != null ? queueInboxMessage.getRetryCount() + 1 : 0);
break;
}
case Discard:
default: {
queueInboxMessage.setStatus(QueueInboxStatus.DISCARD);
break;
}
}
success = status == EventProcessingStatus.Success;
entityManager.merge(queueInboxMessage);
entityManager.flush();
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return success;
}
private EventProcessingStatus processMessage(String routingKey, String messageId, String appId, String message) {
IntegrationEventHandler handler;
if (this.RoutingKeyMatched(routingKey, this.inboxProperties.getUserRemovalTopic())) handler = this.applicationContext.getBean(UserRemovalIntegrationEventHandler.class);
else if (this.RoutingKeyMatched(routingKey, this.inboxProperties.getUserTouchedTopic())) handler = this.applicationContext.getBean(UserTouchedIntegrationEventHandler.class);
else handler = null;
if (handler == null) return EventProcessingStatus.Discard;
IntegrationEventProperties properties = new IntegrationEventProperties();
properties.setAppId(appId);
properties.setMessageId(messageId);
TrackedEvent event = this.jsonHandlingService.fromJsonSafe(TrackedEvent.class, message);
// using (LogContext.PushProperty(this._logTrackingConfig.LogTrackingContextName, @event.TrackingContextTag))
// {
try {
return handler.handle(properties, message);
} catch (Exception ex) {
logger.error("problem handling event from routing key " + routingKey + ". Setting nack and continuing...", ex);
return EventProcessingStatus.Error;
}
// }
}
private Boolean RoutingKeyMatched(String routingKey, List<String> topics) {
if (topics == null || topics.size() == 0) return false;
return topics.stream().anyMatch(x -> x.equals(routingKey));
}
}

View File

@ -0,0 +1,5 @@
package eu.eudat.integrationevent.inbox;
public interface IntegrationEventHandler {
EventProcessingStatus handle(IntegrationEventProperties properties, String message);
}

View File

@ -0,0 +1,22 @@
package eu.eudat.integrationevent.inbox;
public class IntegrationEventProperties {
private String messageId;
private String appId;
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
}

View File

@ -0,0 +1,26 @@
package eu.eudat.integrationevent.inbox.userremoval;
import eu.eudat.integrationevent.inbox.ConsistencyHandler;
import eu.eudat.query.UserQuery;
import gr.cite.tools.data.query.QueryFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserRemovalConsistencyHandler implements ConsistencyHandler<UserRemovalConsistencyPredicates> {
private final QueryFactory queryFactory;
public UserRemovalConsistencyHandler(QueryFactory queryFactory) {
this.queryFactory = queryFactory;
}
@Override
public Boolean isConsistent(UserRemovalConsistencyPredicates consistencyPredicates) {
long count = this.queryFactory.query(UserQuery.class).ids(consistencyPredicates.getUserId()).count();
if (count == 0) return false;
return true;
}
}

View File

@ -0,0 +1,21 @@
package eu.eudat.integrationevent.inbox.userremoval;
import eu.eudat.integrationevent.inbox.ConsistencyPredicates;
import java.util.UUID;
public class UserRemovalConsistencyPredicates implements ConsistencyPredicates {
public UserRemovalConsistencyPredicates(UUID userId) {
this.userId = userId;
}
private UUID userId;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
}

View File

@ -0,0 +1,26 @@
package eu.eudat.integrationevent.inbox.userremoval;
import eu.eudat.integrationevent.TrackedEvent;
import java.util.UUID;
public class UserRemovalIntegrationEvent extends TrackedEvent {
private UUID userId;
private UUID tenant;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public UUID getTenant() {
return tenant;
}
public void setTenant(UUID tenant) {
this.tenant = tenant;
}
}

View File

@ -0,0 +1,6 @@
package eu.eudat.integrationevent.inbox.userremoval;
import eu.eudat.integrationevent.inbox.IntegrationEventHandler;
public interface UserRemovalIntegrationEventHandler extends IntegrationEventHandler {
}

View File

@ -0,0 +1,125 @@
package eu.eudat.integrationevent.inbox.userremoval;
import eu.eudat.audit.AuditableAction;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.fake.FakeRequestScope;
import eu.eudat.data.TenantEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.integrationevent.inbox.EventProcessingStatus;
import eu.eudat.integrationevent.inbox.InboxPrincipal;
import eu.eudat.integrationevent.inbox.IntegrationEventProperties;
import eu.eudat.query.TenantQuery;
import eu.eudat.service.user.UserService;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.logging.LoggerService;
import jakarta.persistence.*;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
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.AbstractMap;
import java.util.Map;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserRemovalIntegrationEventHandlerImpl implements UserRemovalIntegrationEventHandler {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserRemovalIntegrationEventHandlerImpl.class));
private final JsonHandlingService jsonHandlingService;
protected final ApplicationContext applicationContext;
private final ErrorThesaurusProperties errors;
private final MessageSource messageSource;
public UserRemovalIntegrationEventHandlerImpl(
JsonHandlingService jsonHandlingService,
ApplicationContext applicationContext,
ErrorThesaurusProperties errors,
MessageSource messageSource
) {
this.jsonHandlingService = jsonHandlingService;
this.applicationContext = applicationContext;
this.errors = errors;
this.messageSource = messageSource;
}
@Override
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
UserRemovalIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(UserRemovalIntegrationEvent.class, message);
if (event == null) return EventProcessingStatus.Error;
if (event.getUserId() == null) throw new MyValidationException(this.errors.getModelValidation().getCode(), "userId", messageSource.getMessage("Validation_Required", new Object[]{"userId"}, LocaleContextHolder.getLocale()));
EntityManager entityManager = null;
EntityTransaction transaction = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
// TenantScope scope = this.applicationContext.getBean(TenantScope.class);
// if (scope.isMultitenant() && event.getTenant() != null) {
// TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenant()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
// if (tenant == null) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
// }
// scope.setTenant(event.getTenant(), tenant.getCode());
// } else if (scope.isMultitenant()) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
// }
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
currentPrincipalResolver.push(InboxPrincipal.build(properties));
UserRemovalConsistencyHandler userRemovalConsistencyHandler = this.applicationContext.getBean(UserRemovalConsistencyHandler.class);
if (!(userRemovalConsistencyHandler.isConsistent(new UserRemovalConsistencyPredicates(event.getUserId())))) return EventProcessingStatus.Postponed;
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
try {
UserService userService = this.applicationContext.getBean(UserService.class);
userService.deleteAndSave(event.getUserId());
AuditService auditService = this.applicationContext.getBean(AuditService.class);
auditService.track(AuditableAction.User_Delete, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", event.getUserId())
));
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
} finally {
currentPrincipalResolver.pop();
}
transaction.commit();
} catch (OptimisticLockException ex) {
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
this.logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
if (transaction != null) transaction.rollback();
} catch (Exception ex) {
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
if (transaction != null) transaction.rollback();
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
}
return null;
}
}

View File

@ -0,0 +1,45 @@
package eu.eudat.integrationevent.inbox.usertouched;
import eu.eudat.integrationevent.TrackedEvent;
import java.util.UUID;
public class UserTouchedIntegrationEvent extends TrackedEvent {
private UUID id;
private UUID tenant;
private String firstName;
private String lastName;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getTenant() {
return tenant;
}
public void setTenant(UUID tenant) {
this.tenant = tenant;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

View File

@ -0,0 +1,6 @@
package eu.eudat.integrationevent.inbox.usertouched;
import eu.eudat.integrationevent.inbox.IntegrationEventHandler;
public interface UserTouchedIntegrationEventHandler extends IntegrationEventHandler {
}

View File

@ -0,0 +1,116 @@
package eu.eudat.integrationevent.inbox.usertouched;
import eu.eudat.audit.AuditableAction;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.fake.FakeRequestScope;
import eu.eudat.integrationevent.inbox.EventProcessingStatus;
import eu.eudat.integrationevent.inbox.InboxPrincipal;
import eu.eudat.integrationevent.inbox.IntegrationEventProperties;
import eu.eudat.service.user.UserService;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.validation.ValidationService;
import jakarta.persistence.*;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.AbstractMap;
import java.util.Map;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserTouchedIntegrationEventHandlerImpl implements UserTouchedIntegrationEventHandler {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserTouchedIntegrationEventHandlerImpl.class));
private final JsonHandlingService jsonHandlingService;
protected final ApplicationContext applicationContext;
public UserTouchedIntegrationEventHandlerImpl(
JsonHandlingService jsonHandlingService,
ApplicationContext applicationContext
) {
this.jsonHandlingService = jsonHandlingService;
this.applicationContext = applicationContext;
}
@Override
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
UserTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(UserTouchedIntegrationEvent.class, message);
if (event == null) return EventProcessingStatus.Error;
// UserTouchedIntegrationEventPersist model = new UserTouchedIntegrationEventPersist();
// model.setId(event.getId());
// model.setFirstName(event.getFirstName());
// model.setLastName(event.getLastName());
EntityManager entityManager = null;
EntityTransaction transaction = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
// TenantScope scope = this.applicationContext.getBean(TenantScope.class);
// if (scope.isMultitenant() && event.getTenant() != null) {
// TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenant()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
// if (tenant == null) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
// }
// scope.setTenant(event.getTenant(), tenant.getCode());
// } else if (scope.isMultitenant()) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
// }
//
// ValidationService validator = this.applicationContext.getBean(ValidationService.class);
// validator.validateForce(model);
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
currentPrincipalResolver.push(InboxPrincipal.build(properties));
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
try {
UserService userService = this.applicationContext.getBean(UserService.class);
// userService.persist(model, null);
AuditService auditService = this.applicationContext.getBean(AuditService.class);
auditService.track(AuditableAction.User_Persist, Map.ofEntries(
// new AbstractMap.SimpleEntry<String, Object>("model", model)
));
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
} finally {
currentPrincipalResolver.pop();
}
transaction.commit();
} catch (OptimisticLockException ex) {
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
this.logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
if (transaction != null) transaction.rollback();
} catch (Exception ex) {
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
if (transaction != null) transaction.rollback();
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
}
return null;
}
}

View File

@ -0,0 +1,27 @@
package eu.eudat.integrationevent.outbox;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import eu.eudat.integrationevent.TrackedEvent;
import gr.cite.rabbitmq.IntegrationEvent;
@JsonIgnoreProperties(ignoreUnknown = true)
public class OutboxIntegrationEvent extends IntegrationEvent {
public static final String FORGET_ME_COMPLETED = "FORGET_ME_COMPLETED";
public static final String NOTIFY = "NOTIFY";
public static final String TENANT_REACTIVATE = "TENANT_REACTIVATE";
public static final String TENANT_REMOVE = "TENANT_REMOVE";
public static final String TENANT_TOUCH = "TENANT_TOUCH";
public static final String TENANT_USER_INVITE = "TENANT_USER_INVITE";
public static final String WHAT_YOU_KNOW_ABOUT_ME_COMPLETED = "WHAT_YOU_KNOW_ABOUT_ME_COMPLETED";
public static final String GENERATE_FILE = "GENERATE_FILE";
private TrackedEvent event;
public TrackedEvent getEvent() {
return event;
}
public void setEvent(TrackedEvent event) {
this.event = event;
}
}

View File

@ -0,0 +1,89 @@
package eu.eudat.integrationevent.outbox;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotNull;
@Validated
@ConfigurationProperties(prefix = "queue.task.publisher.options")
//@ConstructorBinding
public class OutboxProperties {
@NotNull
private final String exchange;
@NotNull
private final String tenantTouchTopic;
@NotNull
private final String tenantRemovalTopic;
@NotNull
private final String tenantReactivationTopic;
@NotNull
private final String tenantUserInviteTopic;
@NotNull
private final String notifyTopic;
@NotNull
private final String forgetMeCompletedTopic;
@NotNull
private final String whatYouKnowAboutMeCompletedTopic;
@NotNull
private final String generateFileTopic;
public OutboxProperties(String exchange,
String tenantTouchTopic,
String tenantRemovalTopic,
String tenantReactivationTopic,
String tenantUserInviteTopic,
String notifyTopic,
String forgetMeCompletedTopic,
String whatYouKnowAboutMeCompletedTopic,
String generateFileTopic
) {
this.exchange = exchange;
this.tenantTouchTopic = tenantTouchTopic;
this.tenantRemovalTopic = tenantRemovalTopic;
this.tenantReactivationTopic = tenantReactivationTopic;
this.tenantUserInviteTopic = tenantUserInviteTopic;
this.notifyTopic = notifyTopic;
this.forgetMeCompletedTopic = forgetMeCompletedTopic;
this.whatYouKnowAboutMeCompletedTopic = whatYouKnowAboutMeCompletedTopic;
this.generateFileTopic = generateFileTopic;
}
public String getExchange() {
return exchange;
}
public String getTenantTouchTopic() {
return tenantTouchTopic;
}
public String getTenantRemovalTopic() {
return tenantRemovalTopic;
}
public String getTenantReactivationTopic() {
return tenantReactivationTopic;
}
public String getTenantUserInviteTopic() {
return tenantUserInviteTopic;
}
public String getNotifyTopic() {
return notifyTopic;
}
public String getForgetMeCompletedTopic() {
return forgetMeCompletedTopic;
}
public String getWhatYouKnowAboutMeCompletedTopic() {
return whatYouKnowAboutMeCompletedTopic;
}
public String getGenerateFileTopic() {
return generateFileTopic;
}
}

View File

@ -0,0 +1,428 @@
package eu.eudat.integrationevent.outbox;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.fake.FakeRequestScope;
import eu.eudat.data.QueueOutboxEntity;
import eu.eudat.query.QueueOutboxQuery;
import gr.cite.queueoutbox.entity.QueueOutbox;
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
import gr.cite.queueoutbox.repository.CandidateInfo;
import gr.cite.queueoutbox.repository.OutboxRepository;
import gr.cite.queueoutbox.task.MessageOptions;
import gr.cite.rabbitmq.IntegrationEvent;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.OptimisticLockException;
import java.time.Instant;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
public class OutboxRepositoryImpl implements OutboxRepository {
protected final ApplicationContext applicationContext;
private final Random random = new Random();
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(OutboxRepositoryImpl.class));
private final JsonHandlingService jsonHandlingService;
private final OutboxProperties outboxProperties;
public OutboxRepositoryImpl(
ApplicationContext applicationContext,
OutboxProperties outboxProperties
) {
this.applicationContext = applicationContext;
this.jsonHandlingService = this.applicationContext.getBean(JsonHandlingService.class);
this.outboxProperties = outboxProperties;
}
@Override
public CandidateInfo candidate(Instant lastCandidateCreationTimestamp, MessageOptions messageOptions, Function<QueueOutbox, Boolean> onConfirmTimeout) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
CandidateInfo candidate = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class)
.isActives(IsActive.Active)
.notifyStatus(QueueOutboxNotifyStatus.PENDING, QueueOutboxNotifyStatus.WAITING_CONFIRMATION, QueueOutboxNotifyStatus.ERROR)
.retryThreshold(messageOptions.getRetryThreashold())
.confirmTimeout(messageOptions.getConfirmTimeoutSeconds())
.createdAfter(lastCandidateCreationTimestamp)
.ordering(new Ordering().addAscending(QueueOutboxEntity._createdAt))
.first();
if (item != null) {
boolean confirmTimeout = onConfirmTimeout.apply(item);
QueueOutboxNotifyStatus prevState = item.getNotifyStatus();
item.setNotifyStatus(QueueOutboxNotifyStatus.PROCESSING);
entityManager.merge(item);
entityManager.flush();
candidate = new CandidateInfo();
candidate.setId(item.getId());
candidate.setCreatedAt(item.getCreatedAt());
candidate.setPreviousState(prevState);
}
transaction.commit();
} catch (OptimisticLockException ex) {
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
this.logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
if (transaction != null) transaction.rollback();
candidate = null;
} catch (Exception ex) {
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
if (transaction != null) transaction.rollback();
candidate = null;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
}
return candidate;
}
@Override
public Boolean shouldOmit(CandidateInfo candidate, Function<QueueOutbox, Boolean> shouldOmit) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidate.getId()).first();
if (item == null) {
this.logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidate.getId());
} else {
if (shouldOmit.apply(item)) {
item.setNotifyStatus(QueueOutboxNotifyStatus.OMITTED);
entityManager.merge(item);
entityManager.flush();
success = true;
}
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return success;
}
@Override
public Boolean shouldWait(CandidateInfo candidate, Function<QueueOutbox, Boolean> itIsTimeFunc) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidate.getId()).first();
if (item.getRetryCount() != null && item.getRetryCount() >= 1) {
Boolean itIsTime = itIsTimeFunc.apply(item);
if (!itIsTime) {
item.setNotifyStatus(candidate.getPreviousState());
entityManager.merge(item);
entityManager.flush();
success = true;
}
success = !itIsTime;
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return success;
}
@Override
public Boolean process(CandidateInfo candidateInfo, Boolean isAutoconfirmOnPublish, Function<QueueOutbox, Boolean> publish) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidateInfo.getId()).first();
if (item == null) {
this.logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidateInfo.getId());
} else {
success = publish.apply(item);
if (success) {
if (isAutoconfirmOnPublish) {
item.setNotifyStatus(QueueOutboxNotifyStatus.CONFIRMED);
item.setConfirmedAt(Instant.now());
} else {
item.setNotifyStatus(QueueOutboxNotifyStatus.WAITING_CONFIRMATION);
}
item.setPublishedAt(Instant.now());
} else {
item.setNotifyStatus(QueueOutboxNotifyStatus.ERROR);
item.setRetryCount(item.getRetryCount() != null ? item.getRetryCount() + 1 : 0);
item.setPublishedAt(null);
}
entityManager.merge(item);
entityManager.flush();
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return success;
}
@Override
public void handleConfirm(List<UUID> confirmedMessages) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
List<QueueOutboxEntity> queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(confirmedMessages).collect();
if (queueOutboxMessages == null) {
this.logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", confirmedMessages.stream().map(x -> x.toString()).collect(Collectors.toList())));
} else {
for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) {
queueOutboxMessage.setNotifyStatus(QueueOutboxNotifyStatus.CONFIRMED);
queueOutboxMessage.setConfirmedAt(Instant.now());
entityManager.merge(queueOutboxMessage);
}
entityManager.flush();
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
}
@Override
public void handleNack(List<UUID> nackedMessages) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
List<QueueOutboxEntity> queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(nackedMessages).collect();
if (queueOutboxMessages == null) {
this.logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", nackedMessages.stream().map(x -> x.toString()).collect(Collectors.toList())));
} else {
for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) {
queueOutboxMessage.setNotifyStatus(QueueOutboxNotifyStatus.ERROR);
queueOutboxMessage.setRetryCount(queueOutboxMessage.getRetryCount() != null ? queueOutboxMessage.getRetryCount() + 1 : 0);
entityManager.merge(queueOutboxMessage);
}
entityManager.flush();
}
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
}
@Override
public QueueOutbox create(IntegrationEvent item) {
EntityTransaction transaction = null;
EntityManager entityManager = null;
Boolean success = false;
QueueOutboxEntity queueMessage = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
try {
queueMessage = this.mapEvent((OutboxIntegrationEvent) item);
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(queueMessage);
entityManager.flush();
transaction.commit();
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) transaction.rollback();
success = false;
} finally {
if (entityManager != null) entityManager.close();
}
} catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
}
return queueMessage;
}
private QueueOutboxEntity mapEvent(OutboxIntegrationEvent event) {
String routingKey;
switch (event.getType()) {
case OutboxIntegrationEvent.TENANT_REACTIVATE: {
routingKey = this.outboxProperties.getTenantReactivationTopic();
break;
}
case OutboxIntegrationEvent.TENANT_REMOVE: {
routingKey = this.outboxProperties.getTenantRemovalTopic();
break;
}
case OutboxIntegrationEvent.TENANT_TOUCH: {
routingKey = this.outboxProperties.getTenantTouchTopic();
break;
}
case OutboxIntegrationEvent.TENANT_USER_INVITE: {
routingKey = this.outboxProperties.getTenantUserInviteTopic();
break;
}
case OutboxIntegrationEvent.FORGET_ME_COMPLETED: {
routingKey = this.outboxProperties.getForgetMeCompletedTopic();
break;
}
case OutboxIntegrationEvent.NOTIFY: {
routingKey = this.outboxProperties.getNotifyTopic();
break;
}
case OutboxIntegrationEvent.WHAT_YOU_KNOW_ABOUT_ME_COMPLETED: {
routingKey = this.outboxProperties.getWhatYouKnowAboutMeCompletedTopic();
break;
}
case OutboxIntegrationEvent.GENERATE_FILE: {
routingKey = this.outboxProperties.getGenerateFileTopic();
break;
}
default: {
logger.error("unrecognized outgoing integration event {}. Skipping...", event.getType());
return null;
}
}
UUID correlationId = UUID.randomUUID();
if (event.getEvent() != null) event.getEvent().setTrackingContextTag(correlationId.toString());
event.setMessage(this.jsonHandlingService.toJsonSafe(event.getEvent()));
//this._logTrackingService.Trace(correlationId.ToString(), $"Correlating current tracking context with new correlationId {correlationId}");
QueueOutboxEntity queueMessage = new QueueOutboxEntity();
queueMessage.setId(UUID.randomUUID());
queueMessage.setTenantId(null);
queueMessage.setExchange(this.outboxProperties.getExchange());
queueMessage.setRoute(routingKey);
queueMessage.setMessageId(event.getMessageId());
queueMessage.setMessage(this.jsonHandlingService.toJsonSafe(event));
queueMessage.setIsActive(IsActive.Active);
queueMessage.setNotifyStatus(QueueOutboxNotifyStatus.PENDING);
queueMessage.setRetryCount(0);
queueMessage.setCreatedAt(Instant.now());
queueMessage.setUpdatedAt(Instant.now());
return queueMessage;
}
}

View File

@ -0,0 +1,5 @@
package eu.eudat.integrationevent.outbox;
public interface OutboxService {
void publish(OutboxIntegrationEvent event);
}

View File

@ -0,0 +1,43 @@
package eu.eudat.integrationevent.outbox;
import eu.eudat.commons.JsonHandlingService;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
@Component
@RequestScope
public class OutboxServiceImpl implements OutboxService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(OutboxServiceImpl.class));
private final OutboxProperties config;
private final JsonHandlingService jsonHandlingService;
private final ApplicationEventPublisher eventPublisher;
public OutboxServiceImpl(
OutboxProperties config,
JsonHandlingService jsonHandlingService,
ApplicationEventPublisher eventPublisher
) {
this.config = config;
this.jsonHandlingService = jsonHandlingService;
this.eventPublisher = eventPublisher;
}
@Override
public void publish(OutboxIntegrationEvent event) {
try {
eventPublisher.publishEvent(event);
return;
} catch (Exception ex) {
logger.error(new MapLogEntry(String.format("Could not save message ", event.getMessage())).And("message", event.getMessage()).And("ex", ex));
//Still want to skip it from processing
return;
}
}
}

View File

@ -0,0 +1,74 @@
package eu.eudat.integrationevent.outbox.notification;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.enums.old.notification.NotificationType;
import eu.eudat.integrationevent.TrackedEvent;
import java.util.UUID;
public class NotificationIntegrationEvent extends TrackedEvent {
private UUID userId;
private UUID tenant;
private UUID notificationType;
private NotificationContactType contactTypeHint;
private String contactHint;
private String data;
private String provenanceRef;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public UUID getTenant() {
return tenant;
}
public void setTenant(UUID tenant) {
this.tenant = tenant;
}
public UUID getNotificationType() {
return notificationType;
}
public void setNotificationType(UUID notificationType) {
this.notificationType = notificationType;
}
public NotificationContactType getContactTypeHint() {
return contactTypeHint;
}
public void setContactTypeHint(NotificationContactType contactTypeHint) {
this.contactTypeHint = contactTypeHint;
}
public String getContactHint() {
return contactHint;
}
public void setContactHint(String contactHint) {
this.contactHint = contactHint;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getProvenanceRef() {
return provenanceRef;
}
public void setProvenanceRef(String provenanceRef) {
this.provenanceRef = provenanceRef;
}
}

View File

@ -0,0 +1,7 @@
package eu.eudat.integrationevent.outbox.notification;
import javax.management.InvalidApplicationException;
public interface NotificationIntegrationEventHandler {
void handle(NotificationIntegrationEvent event) throws InvalidApplicationException;
}

View File

@ -0,0 +1,106 @@
package eu.eudat.integrationevent.outbox.notification;
import eu.eudat.audit.AuditableAction;
import eu.eudat.commons.enums.ContactInfoType;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.enums.notification.NotificationNotifyState;
import eu.eudat.commons.enums.notification.NotificationTrackingProcess;
import eu.eudat.commons.enums.notification.NotificationTrackingState;
import eu.eudat.data.UserContactInfoEntity;
import eu.eudat.data.UserEntity;
import eu.eudat.integrationevent.outbox.OutboxIntegrationEvent;
import eu.eudat.integrationevent.outbox.OutboxService;
import eu.eudat.model.persist.notification.NotificationPersist;
import eu.eudat.query.UserContactInfoQuery;
import eu.eudat.query.UserQuery;
import eu.eudat.service.notification.NotificationService;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.validation.ValidationService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
@Component
@RequestScope
public class NotificationIntegrationEventHandlerImpl implements NotificationIntegrationEventHandler {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationIntegrationEventHandlerImpl.class));
private final NotificationService notificationService;
private final ValidationService validationService;
private final QueryFactory queryFactory;
private final AuditService auditService;
private final OutboxService outboxService;
@Autowired
public NotificationIntegrationEventHandlerImpl(
OutboxService outboxService,
NotificationService notificationService,
ValidationService validationService,
QueryFactory queryFactory,
AuditService auditService) {
this.outboxService = outboxService;
this.notificationService = notificationService;
this.validationService = validationService;
this.queryFactory = queryFactory;
this.auditService = auditService;
}
@Override
public void handle(NotificationIntegrationEvent event) throws InvalidApplicationException {
// OutboxIntegrationEvent message = new OutboxIntegrationEvent();
// message.setMessageId(UUID.randomUUID());
// message.setType(OutboxIntegrationEvent.NOTIFY);
// message.setEvent(event);
// this.outboxService.publish(message);
NotificationPersist persist = new NotificationPersist();
persist.setType(event.getNotificationType());
persist.setUserId(event.getUserId());
persist.setContactHint(event.getContactHint());
persist.setContactTypeHint(event.getContactTypeHint());
persist.setData(event.getData());
persist.setNotifyState(NotificationNotifyState.PENDING);
persist.setNotifiedWith(NotificationContactType.EMAIL);
persist.setRetryCount(0);
persist.setTrackingState(NotificationTrackingState.UNDEFINED);
persist.setTrackingProcess(NotificationTrackingProcess.PENDING);
persist.setTrackingData(null);
persist.setProvenanceRef(event.getProvenanceRef());
persist.setNotifiedAt(Instant.now());
//validationService.validateForce(persist);
if (isNotificationConsistent(persist)) {
notificationService.persist(persist, null);
auditService.track(AuditableAction.Notification_Persist, "notification_event", event);
}
}
private boolean isNotificationConsistent(NotificationPersist notification) {
switch (notification.getContactTypeHint()){
case IN_APP:{
if (notification.getUserId() == null) return false;
List<UserEntity> users = this.queryFactory.query(UserQuery.class).ids(notification.getUserId()).collect();
return users.size() > 0;
}
case EMAIL:{
if (notification.getContactHint() != null && !notification.getContactHint().isBlank()) return true;
if (notification.getUserId() == null) return false;
List<UserContactInfoEntity> userContactInfoEntities = this.queryFactory.query(UserContactInfoQuery.class).types(ContactInfoType.Email).userIds(notification.getUserId()).collect();
return userContactInfoEntities.size() > 0;
}
default:
throw new MyApplicationException("invalid type " + notification.getContactTypeHint());
}
}
}

View File

@ -0,0 +1,169 @@
package eu.eudat.model.persist.notification;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.enums.notification.NotificationNotifyState;
import eu.eudat.commons.enums.notification.NotificationTrackingProcess;
import eu.eudat.commons.enums.notification.NotificationTrackingState;
import eu.eudat.commons.validation.FieldNotNullIfOtherSet;
import eu.eudat.commons.validation.ValidId;
import jakarta.validation.constraints.NotNull;
import java.time.Instant;
import java.util.UUID;
@FieldNotNullIfOtherSet(message = "{validation.hashempty}")
public class NotificationPersist {
@ValidId(message = "{validation.invalidid}")
private UUID id;
@NotNull(message = "{validation.empty}")
private UUID userId;
private UUID type;
private NotificationContactType contactTypeHint;
private String contactHint;
private String data;
private NotificationNotifyState notifyState;
private NotificationContactType notifiedWith;
private Integer retryCount;
private NotificationTrackingState trackingState;
private NotificationTrackingProcess trackingProcess;
private String trackingData;
private String provenanceRef;
private Instant notifiedAt;
private String hash;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public UUID getType() {
return type;
}
public void setType(UUID type) {
this.type = type;
}
public NotificationContactType getContactTypeHint() {
return contactTypeHint;
}
public void setContactTypeHint(NotificationContactType contactTypeHint) {
this.contactTypeHint = contactTypeHint;
}
public String getContactHint() {
return contactHint;
}
public void setContactHint(String contactHint) {
this.contactHint = contactHint;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public NotificationNotifyState getNotifyState() {
return notifyState;
}
public void setNotifyState(NotificationNotifyState notifyState) {
this.notifyState = notifyState;
}
public NotificationContactType getNotifiedWith() {
return notifiedWith;
}
public void setNotifiedWith(NotificationContactType notifiedWith) {
this.notifiedWith = notifiedWith;
}
public Integer getRetryCount() {
return retryCount;
}
public void setRetryCount(Integer retryCount) {
this.retryCount = retryCount;
}
public NotificationTrackingState getTrackingState() {
return trackingState;
}
public void setTrackingState(NotificationTrackingState trackingState) {
this.trackingState = trackingState;
}
public NotificationTrackingProcess getTrackingProcess() {
return trackingProcess;
}
public void setTrackingProcess(NotificationTrackingProcess trackingProcess) {
this.trackingProcess = trackingProcess;
}
public String getTrackingData() {
return trackingData;
}
public void setTrackingData(String trackingData) {
this.trackingData = trackingData;
}
public String getProvenanceRef() {
return provenanceRef;
}
public void setProvenanceRef(String provenanceRef) {
this.provenanceRef = provenanceRef;
}
public Instant getNotifiedAt() {
return notifiedAt;
}
public void setNotifiedAt(Instant notifiedAt) {
this.notifiedAt = notifiedAt;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
}

View File

@ -0,0 +1,219 @@
package eu.eudat.query;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.data.QueueInboxEntity;
import gr.cite.queueinbox.entity.QueueInboxStatus;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryBase;
import gr.cite.tools.data.query.QueryContext;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class QueueInboxQuery extends QueryBase<QueueInboxEntity> {
private Collection<UUID> ids;
private Instant createdAfter;
private Collection<IsActive> isActives;
private Collection<String> exchanges;
private Collection<String> routes;
private Collection<QueueInboxStatus> status;
private Integer retryThreshold;
public QueueInboxQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public QueueInboxQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public QueueInboxQuery ids(List<UUID> value) {
this.ids = value;
return this;
}
public QueueInboxQuery isActives(IsActive value) {
this.isActives = List.of(value);
return this;
}
public QueueInboxQuery isActives(IsActive... value) {
this.isActives = Arrays.asList(value);
return this;
}
public QueueInboxQuery isActives(List<IsActive> value) {
this.isActives = value;
return this;
}
public QueueInboxQuery exchanges(String value) {
this.exchanges = List.of(value);
return this;
}
public QueueInboxQuery exchanges(String... value) {
this.exchanges = Arrays.asList(value);
return this;
}
public QueueInboxQuery exchanges(List<String> value) {
this.exchanges = value;
return this;
}
public QueueInboxQuery routes(String value) {
this.routes = List.of(value);
return this;
}
public QueueInboxQuery routes(String... value) {
this.routes = Arrays.asList(value);
return this;
}
public QueueInboxQuery routes(List<String> value) {
this.routes = value;
return this;
}
public QueueInboxQuery status(QueueInboxStatus value) {
this.status = List.of(value);
return this;
}
public QueueInboxQuery status(QueueInboxStatus... value) {
this.status = Arrays.asList(value);
return this;
}
public QueueInboxQuery status(List<QueueInboxStatus> value) {
this.status = value;
return this;
}
public QueueInboxQuery createdAfter(Instant value) {
this.createdAfter = value;
return this;
}
public QueueInboxQuery retryThreshold(Integer value) {
this.retryThreshold = value;
return this;
}
public QueueInboxQuery ordering(Ordering ordering) {
this.setOrder(ordering);
return this;
}
@Override
protected Class<QueueInboxEntity> entityClass() {
return QueueInboxEntity.class;
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.exchanges)
|| this.isEmpty(this.routes) || this.isEmpty(this.status);
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueInboxEntity._id));
for (UUID item : this.ids) inClause.value(item);
predicates.add(inClause);
}
if (this.createdAfter != null) {
predicates.add(queryContext.CriteriaBuilder.greaterThan(queryContext.Root.get(QueueInboxEntity._createdAt), this.createdAfter));
}
if (this.isActives != null) {
CriteriaBuilder.In<IsActive> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueInboxEntity._isActive));
for (IsActive item : this.isActives) inClause.value(item);
predicates.add(inClause);
}
if (this.exchanges != null) {
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueInboxEntity._exchange));
for (String item : this.exchanges) inClause.value(item);
predicates.add(inClause);
}
if (this.routes != null) {
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueInboxEntity._route));
for (String item : this.routes) inClause.value(item);
predicates.add(inClause);
}
if (this.status != null) {
CriteriaBuilder.In<QueueInboxStatus> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueInboxEntity._status));
for (QueueInboxStatus item : this.status) inClause.value(item);
predicates.add(inClause);
}
if (this.retryThreshold != null) {
predicates.add(queryContext.CriteriaBuilder.or(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(QueueInboxEntity._retryCount)),
queryContext.CriteriaBuilder.lessThanOrEqualTo(queryContext.Root.get(QueueInboxEntity._retryCount), this.retryThreshold)));
}
if (predicates.size() > 0) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected QueueInboxEntity convert(Tuple tuple, Set<String> columns) {
QueueInboxEntity item = new QueueInboxEntity();
item.setId(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._id, UUID.class));
item.setExchange(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._exchange, String.class));
item.setTenantId(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._tenantId, UUID.class));
item.setRoute(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._route, String.class));
item.setMessage(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._message, String.class));
item.setMessageId(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._messageId, UUID.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._createdAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._isActive, IsActive.class));
item.setStatus(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._status, QueueInboxStatus.class));
item.setRetryCount(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._retryCount, Integer.class));
item.setQueue(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._queue, String.class));
item.setApplicationId(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._applicationId, String.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, QueueInboxEntity._updatedAt, Instant.class));
return item;
}
@Override
protected String fieldNameOf(FieldResolver item) {
if (item.match(QueueInboxEntity._id)) return QueueInboxEntity._id;
else if (item.match(QueueInboxEntity._exchange)) return QueueInboxEntity._exchange;
else if (item.match(QueueInboxEntity._tenantId)) return QueueInboxEntity._tenantId;
else if (item.match(QueueInboxEntity._route)) return QueueInboxEntity._route;
else if (item.match(QueueInboxEntity._message)) return QueueInboxEntity._message;
else if (item.match(QueueInboxEntity._messageId)) return QueueInboxEntity._messageId;
else if (item.match(QueueInboxEntity._createdAt)) return QueueInboxEntity._createdAt;
else if (item.match(QueueInboxEntity._isActive)) return QueueInboxEntity._isActive;
else if (item.match(QueueInboxEntity._status)) return QueueInboxEntity._status;
else if (item.match(QueueInboxEntity._retryCount)) return QueueInboxEntity._retryCount;
else if (item.match(QueueInboxEntity._queue)) return QueueInboxEntity._queue;
else if (item.match(QueueInboxEntity._applicationId)) return QueueInboxEntity._applicationId;
else if (item.match(QueueInboxEntity._createdAt)) return QueueInboxEntity._createdAt;
else if (item.match(QueueInboxEntity._updatedAt)) return QueueInboxEntity._updatedAt;
else return null;
}
}

View File

@ -0,0 +1,236 @@
package eu.eudat.query;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.data.QueueOutboxEntity;
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryBase;
import gr.cite.tools.data.query.QueryContext;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import java.time.Instant;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class QueueOutboxQuery extends QueryBase<QueueOutboxEntity> {
private Collection<UUID> ids;
private Instant createdAfter;
private Collection<IsActive> isActives;
private Collection<String> exchanges;
private Collection<String> routes;
private Collection<QueueOutboxNotifyStatus> notifyStatus;
private Integer retryThreshold;
private Integer confirmTimeout;
public QueueOutboxQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public QueueOutboxQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public QueueOutboxQuery ids(List<UUID> value) {
this.ids = value;
return this;
}
public QueueOutboxQuery isActives(IsActive value) {
this.isActives = List.of(value);
return this;
}
public QueueOutboxQuery isActives(IsActive... value) {
this.isActives = Arrays.asList(value);
return this;
}
public QueueOutboxQuery isActives(List<IsActive> value) {
this.isActives = value;
return this;
}
public QueueOutboxQuery exchanges(String value) {
this.exchanges = List.of(value);
return this;
}
public QueueOutboxQuery exchanges(String... value) {
this.exchanges = Arrays.asList(value);
return this;
}
public QueueOutboxQuery exchanges(List<String> value) {
this.exchanges = value;
return this;
}
public QueueOutboxQuery routes(String value) {
this.routes = List.of(value);
return this;
}
public QueueOutboxQuery routes(String... value) {
this.routes = Arrays.asList(value);
return this;
}
public QueueOutboxQuery routes(List<String> value) {
this.routes = value;
return this;
}
public QueueOutboxQuery notifyStatus(QueueOutboxNotifyStatus value) {
this.notifyStatus = List.of(value);
return this;
}
public QueueOutboxQuery notifyStatus(QueueOutboxNotifyStatus... value) {
this.notifyStatus = Arrays.asList(value);
return this;
}
public QueueOutboxQuery notifyStatus(List<QueueOutboxNotifyStatus> value) {
this.notifyStatus = value;
return this;
}
public QueueOutboxQuery createdAfter(Instant value) {
this.createdAfter = value;
return this;
}
public QueueOutboxQuery retryThreshold(Integer value) {
this.retryThreshold = value;
return this;
}
public QueueOutboxQuery confirmTimeout(Integer value) {
this.confirmTimeout = value;
return this;
}
public QueueOutboxQuery ordering(Ordering ordering) {
this.setOrder(ordering);
return this;
}
@Override
protected Class<QueueOutboxEntity> entityClass() {
return QueueOutboxEntity.class;
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.exchanges)
|| this.isEmpty(this.routes) || this.isEmpty(this.notifyStatus);
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueOutboxEntity._id));
for (UUID item : this.ids) inClause.value(item);
predicates.add(inClause);
}
if (this.createdAfter != null) {
predicates.add(queryContext.CriteriaBuilder.greaterThan(queryContext.Root.get(QueueOutboxEntity._createdAt), this.createdAfter));
}
if (this.isActives != null) {
CriteriaBuilder.In<IsActive> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueOutboxEntity._isActive));
for (IsActive item : this.isActives) inClause.value(item);
predicates.add(inClause);
}
if (this.exchanges != null) {
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueOutboxEntity._exchange));
for (String item : this.exchanges) inClause.value(item);
predicates.add(inClause);
}
if (this.routes != null) {
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueOutboxEntity._route));
for (String item : this.routes) inClause.value(item);
predicates.add(inClause);
}
if (this.notifyStatus != null) {
CriteriaBuilder.In<QueueOutboxNotifyStatus> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(QueueOutboxEntity._notifyStatus));
for (QueueOutboxNotifyStatus item : this.notifyStatus) inClause.value(item);
predicates.add(inClause);
}
if (this.retryThreshold != null) {
predicates.add(queryContext.CriteriaBuilder.or(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(QueueOutboxEntity._retryCount)),
queryContext.CriteriaBuilder.lessThanOrEqualTo(queryContext.Root.get(QueueOutboxEntity._retryCount), this.retryThreshold)));
}
if (this.confirmTimeout != null) {
predicates.add(queryContext.CriteriaBuilder.or(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(QueueOutboxEntity._publishedAt)),
queryContext.CriteriaBuilder.and(
queryContext.CriteriaBuilder.isNotNull(queryContext.Root.get(QueueOutboxEntity._publishedAt)),
queryContext.CriteriaBuilder.isNull(queryContext.Root.get(QueueOutboxEntity._confirmedAt)),
queryContext.CriteriaBuilder.lessThan(queryContext.Root.get(QueueOutboxEntity._publishedAt), Instant.now().minusSeconds(this.confirmTimeout))
)
));
}
if (predicates.size() > 0) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected QueueOutboxEntity convert(Tuple tuple, Set<String> columns) {
QueueOutboxEntity item = new QueueOutboxEntity();
item.setId(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._id, UUID.class));
item.setExchange(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._exchange, String.class));
item.setTenantId(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._tenantId, UUID.class));
item.setRoute(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._route, String.class));
item.setMessage(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._message, String.class));
item.setMessageId(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._messageId, UUID.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._createdAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._isActive, IsActive.class));
item.setNotifyStatus(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._notifyStatus, QueueOutboxNotifyStatus.class));
item.setRetryCount(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._retryCount, Integer.class));
item.setPublishedAt(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._publishedAt, Instant.class));
item.setConfirmedAt(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._confirmedAt, Instant.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, QueueOutboxEntity._updatedAt, Instant.class));
return item;
}
@Override
protected String fieldNameOf(FieldResolver item) {
if (item.match(QueueOutboxEntity._id)) return QueueOutboxEntity._id;
else if (item.match(QueueOutboxEntity._exchange)) return QueueOutboxEntity._exchange;
else if (item.match(QueueOutboxEntity._tenantId)) return QueueOutboxEntity._tenantId;
else if (item.match(QueueOutboxEntity._route)) return QueueOutboxEntity._route;
else if (item.match(QueueOutboxEntity._message)) return QueueOutboxEntity._message;
else if (item.match(QueueOutboxEntity._messageId)) return QueueOutboxEntity._messageId;
else if (item.match(QueueOutboxEntity._createdAt)) return QueueOutboxEntity._createdAt;
else if (item.match(QueueOutboxEntity._isActive)) return QueueOutboxEntity._isActive;
else if (item.match(QueueOutboxEntity._notifyStatus)) return QueueOutboxEntity._notifyStatus;
else if (item.match(QueueOutboxEntity._retryCount)) return QueueOutboxEntity._retryCount;
else if (item.match(QueueOutboxEntity._publishedAt)) return QueueOutboxEntity._publishedAt;
else if (item.match(QueueOutboxEntity._confirmedAt)) return QueueOutboxEntity._confirmedAt;
else if (item.match(QueueOutboxEntity._createdAt)) return QueueOutboxEntity._createdAt;
else if (item.match(QueueOutboxEntity._updatedAt)) return QueueOutboxEntity._updatedAt;
else return null;
}
}

View File

@ -6,15 +6,21 @@ import eu.eudat.authorization.Permission;
import eu.eudat.commons.JsonHandlingService; import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.XmlHandlingService;
import eu.eudat.commons.enums.*; import eu.eudat.commons.enums.*;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.scope.tenant.TenantScope;
import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.descriptiontemplate.*; import eu.eudat.commons.types.descriptiontemplate.*;
import eu.eudat.commons.types.descriptiontemplate.fielddata.BaseFieldDataEntity; import eu.eudat.commons.types.descriptiontemplate.fielddata.BaseFieldDataEntity;
import eu.eudat.commons.types.descriptiontemplate.importexport.*; import eu.eudat.commons.types.descriptiontemplate.importexport.*;
import eu.eudat.commons.types.notification.*;
import eu.eudat.configurations.notification.NotificationProperties;
import eu.eudat.convention.ConventionService; import eu.eudat.convention.ConventionService;
import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.DescriptionTemplateEntity;
import eu.eudat.data.UserDescriptionTemplateEntity; import eu.eudat.data.UserDescriptionTemplateEntity;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEvent;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler;
import eu.eudat.model.DescriptionTemplate; import eu.eudat.model.DescriptionTemplate;
import eu.eudat.model.UserContactInfo; import eu.eudat.model.UserContactInfo;
import eu.eudat.model.builder.DescriptionTemplateBuilder; import eu.eudat.model.builder.DescriptionTemplateBuilder;
@ -34,8 +40,6 @@ import eu.eudat.query.UserContactInfoQuery;
import eu.eudat.query.UserDescriptionTemplateQuery; import eu.eudat.query.UserDescriptionTemplateQuery;
import eu.eudat.service.fielddatahelper.FieldDataHelperService; import eu.eudat.service.fielddatahelper.FieldDataHelperService;
import eu.eudat.service.fielddatahelper.FieldDataHelperServiceProvider; import eu.eudat.service.fielddatahelper.FieldDataHelperServiceProvider;
import eu.eudat.service.mail.MailService;
import eu.eudat.service.mail.SimpleMail;
import eu.eudat.service.responseutils.ResponseUtilsService; import eu.eudat.service.responseutils.ResponseUtilsService;
import eu.eudat.service.storage.StorageFileService; import eu.eudat.service.storage.StorageFileService;
import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.commons.web.authz.service.AuthorizationService;
@ -67,10 +71,7 @@ import org.xml.sax.SAXException;
import javax.management.InvalidApplicationException; import javax.management.InvalidApplicationException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
@ -100,11 +101,13 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final ErrorThesaurusProperties errors; private final ErrorThesaurusProperties errors;
private final ValidationService validationService; private final ValidationService validationService;
private final MailService mailService; private final TenantScope tenantScope;
private final Environment environment; private final Environment environment;
private final ResponseUtilsService responseUtilsService; private final ResponseUtilsService responseUtilsService;
private final StorageFileService storageFileService; private final StorageFileService storageFileService;
private final JsonHandlingService jsonHandlingService; private final JsonHandlingService jsonHandlingService;
private final NotificationIntegrationEventHandler eventHandler;
private final NotificationProperties notificationProperties;
@Autowired @Autowired
public DescriptionTemplateServiceImpl( public DescriptionTemplateServiceImpl(
@ -115,7 +118,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
ConventionService conventionService, ConventionService conventionService,
MessageSource messageSource, MessageSource messageSource,
XmlHandlingService xmlHandlingService, XmlHandlingService xmlHandlingService,
FieldDataHelperServiceProvider fieldDataHelperServiceProvider, QueryFactory queryFactory, ErrorThesaurusProperties errors, ValidationService validationService, MailService mailService, Environment environment, ResponseUtilsService responseUtilsService, StorageFileService storageFileService, JsonHandlingService jsonHandlingService) { FieldDataHelperServiceProvider fieldDataHelperServiceProvider, QueryFactory queryFactory, ErrorThesaurusProperties errors, ValidationService validationService, TenantScope tenantScope, Environment environment, ResponseUtilsService responseUtilsService, StorageFileService storageFileService, JsonHandlingService jsonHandlingService, NotificationIntegrationEventHandler eventHandler, NotificationProperties notificationProperties) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.userScope = userScope; this.userScope = userScope;
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
@ -128,11 +131,13 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.errors = errors; this.errors = errors;
this.validationService = validationService; this.validationService = validationService;
this.mailService = mailService; this.tenantScope = tenantScope;
this.environment = environment; this.environment = environment;
this.responseUtilsService = responseUtilsService; this.responseUtilsService = responseUtilsService;
this.storageFileService = storageFileService; this.storageFileService = storageFileService;
this.jsonHandlingService = jsonHandlingService; this.jsonHandlingService = jsonHandlingService;
this.eventHandler = eventHandler;
this.notificationProperties = notificationProperties;
} }
//region Persist //region Persist
@ -204,26 +209,32 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
this.deleterFactory.deleter(UserDescriptionTemplateDeleter.class).delete(toDelete); this.deleterFactory.deleter(UserDescriptionTemplateDeleter.class).delete(toDelete);
} }
private void sendJoinMail(UserDescriptionTemplateEntity userDatasetProfile) { private void sendJoinMail(UserDescriptionTemplateEntity userDatasetProfile) throws InvalidApplicationException {
SimpleMail mail = new SimpleMail(); NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setTenant(tenantScope.getTenant());
event.setUserId(userScope.getUserIdSafe());
UserEntity user = this.entityManager.find(UserEntity.class, userDatasetProfile.getUserId()); UserEntity user = this.entityManager.find(UserEntity.class, userDatasetProfile.getUserId());
DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).isActive(IsActive.Active).ids(userDatasetProfile.getDescriptionTemplateId()).first(); DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).isActive(IsActive.Active).ids(userDatasetProfile.getDescriptionTemplateId()).first();
mail.setSubject(environment.getProperty("admin.mail.subject").replace( "{templateName}", descriptionTemplate.getLabel()));
String content = this.mailService.getMailTemplateContent(environment.getProperty("email.dataset.template"));
content = content.replace("{recipient}", user.getName());
content = content.replace("{templateName}", descriptionTemplate.getLabel());
content = content.replace("{host}", this.environment.getProperty("dmp.domain"));
content = content.replace("{templateID}", descriptionTemplate.getId().toString());
mail.setContent(content);
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
mail.setTo(query.first().getValue());
try { List<ContactPair> contactPairs = new ArrayList<>();
this.mailService.sendSimpleMail(mail); contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue()));
} catch (Exception ex) { NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
logger.error(ex.getMessage(), ex); event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
} event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getTemplate()));
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
fieldInfoList.add(new FieldInfo("{templateName}", DataType.String, descriptionTemplate.getLabel()));
fieldInfoList.add(new FieldInfo("{host}", DataType.String, this.environment.getProperty("dmp.domain")));
fieldInfoList.add(new FieldInfo("{templateID}", DataType.String, descriptionTemplate.getId().toString()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
} }
private void addOwner(DescriptionTemplateEntity descriptionTemplateEntity) throws InvalidApplicationException { private void addOwner(DescriptionTemplateEntity descriptionTemplateEntity) throws InvalidApplicationException {

View File

@ -2,6 +2,6 @@ package eu.eudat.service.keycloak;
public enum KeycloakRole { public enum KeycloakRole {
Admin, DatasetTemplateEditor, Manager, User Admin, DescriptionTemplateEditor, Manager, User
} }

View File

@ -24,9 +24,8 @@ public class MyKeycloakAdminRestApi {
@Autowired @Autowired
public MyKeycloakAdminRestApi(KeycloakClientConfiguration configuration) { public MyKeycloakAdminRestApi(KeycloakClientConfiguration configuration) {
this.configuration = configuration; this.configuration = configuration;
try (Keycloak client = this.initClient()) { Keycloak client = this.initClient();
this.realm = client.realm(configuration.getProperties().getRealm()); this.realm = client.realm(configuration.getProperties().getRealm());
}
logger.info("Custom Keycloak client initialized. Keycloak serving from {}", configuration.getProperties().getServerUrl().replace("/auth", "").replaceAll("https?://", "")); logger.info("Custom Keycloak client initialized. Keycloak serving from {}", configuration.getProperties().getServerUrl().replace("/auth", "").replaceAll("https?://", ""));
} }

View File

@ -2,7 +2,6 @@ package eu.eudat.service.lock;
import eu.eudat.model.Lock; import eu.eudat.model.Lock;
import eu.eudat.model.persist.LockPersist; import eu.eudat.model.persist.LockPersist;
import eu.eudat.query.lookup.LockLookup;
import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException; import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.exception.MyNotFoundException;
@ -16,9 +15,9 @@ public interface LockService {
Lock persist(LockPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException; Lock persist(LockPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException;
boolean isLocked(LockLookup lookup) throws InvalidApplicationException; boolean isLocked(UUID target) throws InvalidApplicationException;
void unlock(LockLookup lookup) throws InvalidApplicationException; void unlock(UUID target) throws InvalidApplicationException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
} }

View File

@ -107,35 +107,32 @@ public class LockServiceImpl implements LockService {
return this.builderFactory.builder(LockBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Lock._id), data); return this.builderFactory.builder(LockBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Lock._id), data);
} }
public boolean isLocked(LockLookup lookup) throws InvalidApplicationException { public boolean isLocked(UUID target) throws InvalidApplicationException {
if (lookup !=null && lookup.getTargetIds() != null && lookup.getTargetIds().size() > 0){ LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(target);
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(lookup.getTargetIds()); if (query.count() == 1) {
if (query.count() == 1) { LockEntity lock = query.first();
LockEntity lock = query.firstAs(lookup.getProject()); if (lock.getLockedBy().equals(this.userScope.getUserId())) {
if (lock.getLockedBy().equals(this.userScope.getUserId())) { lock.setTouchedAt(Instant.now());
lock.setTouchedAt(Instant.now()); this.entityManager.merge(lock);
this.entityManager.merge(lock); this.entityManager.flush();
this.entityManager.flush(); return false;
return false;
}
return this.forceUnlock(lookup) > 0;
} else if (query.count() > 1) {
this.forceUnlock(lookup);
return this.isLocked(lookup);
} }
return false; return this.forceUnlock(target) > 0;
} else{ } else if (query.count() > 1) {
throw new InvalidApplicationException("Wrong LockLookup"); this.forceUnlock(target);
return this.isLocked(target);
} }
return false;
} }
private Long forceUnlock(LockLookup lookup) throws InvalidApplicationException { private Long forceUnlock(UUID target) throws InvalidApplicationException {
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(lookup.getTargetIds()); LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(target);
Long availableLocks = query.count(); Long availableLocks = query.count();
long deletedLocks = 0L; long deletedLocks = 0L;
if (availableLocks > 0) { if (availableLocks > 0) {
List<LockEntity> locks = query.collectAs(lookup.getProject()); List<LockEntity> locks = query.collect();
for (LockEntity lock : locks) { for (LockEntity lock : locks) {
if (new Date().getTime() - Date.from(lock.getTouchedAt()).getTime() > 120000) { if (new Date().getTime() - Date.from(lock.getTouchedAt()).getTime() > 120000) {
this.deleteAndSave(lock.getId()); this.deleteAndSave(lock.getId());
@ -155,17 +152,17 @@ public class LockServiceImpl implements LockService {
return availableLocks - deletedLocks; return availableLocks - deletedLocks;
} }
public void unlock(LockLookup lookup) throws InvalidApplicationException { public void unlock(UUID target) throws InvalidApplicationException {
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(lookup.getTargetIds()); LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(target);
if (query.count() == 1) { if (query.count() == 1) {
LockEntity lock = query.firstAs(lookup.getProject()); LockEntity lock = query.first();
if (!lock.getLockedBy().equals(this.userScope.getUserId())) { if (!lock.getLockedBy().equals(this.userScope.getUserId())) {
throw new InvalidApplicationException("Only the user who created that lock can delete it"); throw new InvalidApplicationException("Only the user who created that lock can delete it");
} }
this.deleteAndSave(lock.getId()); this.deleteAndSave(lock.getId());
} else if (query.count() > 1) { } else if (query.count() > 1) {
List<LockEntity> locks = query.collectAs(lookup.getProject()); List<LockEntity> locks = query.collect();
locks.stream().filter(lock -> lock.getLockedBy().equals(this.userScope.getUserIdSafe())).forEach(lock -> { locks.stream().filter(lock -> lock.getLockedBy().equals(this.userScope.getUserIdSafe())).forEach(lock -> {
try { try {
this.deleteAndSave(lock.getId()); this.deleteAndSave(lock.getId());

View File

@ -1,12 +0,0 @@
package eu.eudat.service.mail;
import jakarta.mail.MessagingException;
public interface MailService {
void sendSimpleMail(SimpleMail mail) throws MessagingException;
String getMailTemplateContent(String resourceTemplate);
String getMailTemplateSubject();
}

View File

@ -1,140 +0,0 @@
package eu.eudat.service.mail;
import jakarta.mail.BodyPart;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Service("mailService")
public class MailServiceImpl implements MailService {
private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);
private Environment env;
private JavaMailSender emailSender;
private ApplicationContext applicationContext;
@Autowired
public MailServiceImpl(Environment env, JavaMailSender emailSender, ApplicationContext applicationContext) {
this.env = env;
this.emailSender = emailSender;
this.applicationContext = applicationContext;
}
@Override
public void sendSimpleMail(SimpleMail mail) throws MessagingException {
List<String> imageSources = parseImages(mail.getContent());
List<String> cids = new ArrayList<>();
if (!imageSources.isEmpty()) {
for (int i = 0; i < imageSources.size(); i++) {
cids.add(UUID.randomUUID().toString());
}
mail.setContent(replaceImageSources(mail.getContent(), cids));
}
MimeMultipart content = new MimeMultipart("related");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(mail.getContent(), "text/html; charset=UTF-8");
content.addBodyPart(messageBodyPart);
if (!imageSources.isEmpty()) {
for (int i =0; i < imageSources.size(); i++) {
MimeBodyPart imagePart = new MimeBodyPart();
try {
imagePart.attachFile(applicationContext.getResource(imageSources.get(i)).getFile());
imagePart.setContentID("<" + cids.get(i) + ">");
imagePart.setDisposition(MimeBodyPart.INLINE);
content.addBodyPart(imagePart);
} catch (IOException | MessagingException e) {
logger.error(e.getMessage(), e);
}
}
}
MimeMessage message = this.emailSender.createMimeMessage();
message.setSubject(mail.getSubject());
message.setContent(content);
message.addRecipients(Message.RecipientType.TO, mail.getTo());
message.setFrom(env.getProperty("mail.from"));
this.emailSender.send(message);
}
public Environment getEnv() {
return env;
}
@Override
public String getMailTemplateContent(String resourceTemplate) {
Resource resource = applicationContext.getResource(resourceTemplate);
try {
InputStream inputStream = resource.getInputStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
inputStream.close();
return writer.toString();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return "";
}
@Override
public String getMailTemplateSubject() {
return env.getProperty("mail.subject");
}
private List<String> parseImages(String content) {
List<String> imagePaths = new ArrayList<>();
int lastIndex = 0;
while (lastIndex != -1) {
lastIndex = content.indexOf("img src=\"", lastIndex);
if (lastIndex != -1) {
String imagePath = content.substring(lastIndex + 9, content.indexOf("\"", lastIndex + 9));
if (!imagePath.contains("data:image/png;base64")) {
imagePaths.add(imagePath);
}
lastIndex++;
}
}
return imagePaths;
}
private String replaceImageSources(String content, List<String> cids) {
int lastIndex = 0;
int cidIndex = 0;
while (lastIndex != -1) {
lastIndex = content.indexOf("img src=\"", lastIndex);
if (lastIndex != -1) {
content = content.replace(content.substring(lastIndex + 9, content.indexOf("\"", lastIndex + 9)), "cid:" + cids.get(cidIndex));
lastIndex ++;
cidIndex ++;
}
}
return content;
}
}

View File

@ -1,51 +0,0 @@
package eu.eudat.service.mail;
public class SimpleMail {
private String from;
private String to;
private String subject;
private String content;
public SimpleMail() {
}
public SimpleMail(String from, String to, String subject, String content) {
this.from = from;
this.to = to;
this.subject = subject;
this.content = content;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -0,0 +1,16 @@
package eu.eudat.service.notification;
import eu.eudat.model.persist.notification.NotificationPersist;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet;
import javax.management.InvalidApplicationException;
public interface NotificationService{
void persist(NotificationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException;
}

View File

@ -0,0 +1,106 @@
package eu.eudat.service.notification;
import eu.eudat.authorization.Permission;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.TenantEntityManager;
import eu.eudat.data.notification.NotificationEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.model.persist.notification.NotificationPersist;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.context.annotation.RequestScope;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.UUID;
@Service
@RequestScope
public class NotificationServiceImpl implements NotificationService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationServiceImpl.class));
private final TenantEntityManager entityManager;
private final AuthorizationService authorizationService;
private final DeleterFactory deleterFactory;
private final BuilderFactory builderFactory;
private final ConventionService conventionService;
private final ErrorThesaurusProperties errors;
private final MessageSource messageSource;
@Autowired
public NotificationServiceImpl(
TenantEntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource
) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.builderFactory = builderFactory;
this.conventionService = conventionService;
this.errors = errors;
this.messageSource = messageSource;
}
@Override
public void persist(NotificationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting notification").And("model", model).And("fields", fields));
//this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
NotificationEntity data = null;
if (isUpdate) {
data = this.entityManager.find(NotificationEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), NotificationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
} else {
data = new NotificationEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
}
data.setNotifiedAt(model.getNotifiedAt());
data.setContactHint(model.getContactHint());
data.setContactTypeHint(model.getContactTypeHint());
data.setType(model.getType());
data.setUserId(model.getUserId());
data.setData(model.getData());
data.setNotifyState(model.getNotifyState());
data.setNotifiedWith(model.getNotifiedWith());
data.setRetryCount(model.getRetryCount());
data.setTrackingState(model.getTrackingState());
data.setTrackingProcess(model.getTrackingProcess());
data.setTrackingData(model.getTrackingData());
// data.setProvenanceRef(model.getProvenanceRef());
data.setUpdatedAt(Instant.now());
if (isUpdate) this.entityManager.merge(data);
else this.entityManager.persist(data);
this.entityManager.flush();
}
}

View File

@ -10,6 +10,7 @@ import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.user.AdditionalInfoEntity; import eu.eudat.commons.types.user.AdditionalInfoEntity;
import eu.eudat.convention.ConventionService; import eu.eudat.convention.ConventionService;
import eu.eudat.data.UserCredentialEntity;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.data.UserRoleEntity; import eu.eudat.data.UserRoleEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.errorcode.ErrorThesaurusProperties;
@ -23,6 +24,7 @@ import eu.eudat.model.deleter.UserRoleDeleter;
import eu.eudat.model.persist.UserAdditionalInfoPersist; import eu.eudat.model.persist.UserAdditionalInfoPersist;
import eu.eudat.model.persist.UserPersist; import eu.eudat.model.persist.UserPersist;
import eu.eudat.model.persist.UserRolePatchPersist; import eu.eudat.model.persist.UserRolePatchPersist;
import eu.eudat.query.UserCredentialQuery;
import eu.eudat.query.UserQuery; import eu.eudat.query.UserQuery;
import eu.eudat.query.UserRoleQuery; import eu.eudat.query.UserRoleQuery;
import eu.eudat.service.keycloak.KeycloakRole; import eu.eudat.service.keycloak.KeycloakRole;
@ -206,6 +208,14 @@ public class UserServiceImpl implements UserService {
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
List<UserCredentialEntity> userCredentials = this.queryFactory.query(UserCredentialQuery.class).userIds(data.getId()).collect();
if (userCredentials.isEmpty())
throw new MyApplicationException("Currently cannot update roles for this user");
if (userCredentials.getFirst().getExternalId() == null)
throw new MyApplicationException("Currently cannot update roles for this user");
UUID subjectId = UUID.fromString(userCredentials.getFirst().getExternalId());
List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(data.getId()).collect(); List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(data.getId()).collect();
List<UUID> foundIds = new ArrayList<>(); List<UUID> foundIds = new ArrayList<>();
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank()).distinct().toList()) { for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank()).distinct().toList()) {
@ -217,7 +227,7 @@ public class UserServiceImpl implements UserService {
item.setRole(roleName); item.setRole(roleName);
item.setCreatedAt(Instant.now()); item.setCreatedAt(Instant.now());
this.entityManager.persist(item); this.entityManager.persist(item);
this.keycloakService.addUserToGroup(data.getId(), KeycloakRole.valueOf(roleName)); this.keycloakService.addUserToGroup(subjectId, KeycloakRole.valueOf(roleName));
} }
foundIds.add(item.getId()); foundIds.add(item.getId());
} }
@ -225,7 +235,7 @@ public class UserServiceImpl implements UserService {
this.entityManager.flush(); this.entityManager.flush();
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList()); List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
toDelete.forEach(x -> this.keycloakService.removeUserFromGroup(data.getId(), KeycloakRole.valueOf(x.getRole()))); toDelete.forEach(x -> this.keycloakService.removeUserFromGroup(subjectId, KeycloakRole.valueOf(x.getRole())));
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete); this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
this.entityManager.flush(); this.entityManager.flush();

View File

@ -52,7 +52,7 @@ notification:
body-path: classpath:notification_templates/Confirmation/Email/body.{language}.html body-path: classpath:notification_templates/Confirmation/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ ] mandatory: [ "{host}", "{confirmationToken}" ]
optional: optional:
- key: "{expiration_time}" - key: "{expiration_time}"
value: -- value: --
@ -72,7 +72,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/DataManagementPlan/Email/body.{language}.html body-path: classpath:notification_templates/DataManagementPlan/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{dmpname}", "{dmprole}" ] mandatory: [ "{dmpname}", "{dmprole}", "{host}", "{invitationID}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -94,7 +94,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/Finalised/Email/body.{language}.html body-path: classpath:notification_templates/Finalised/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{reasonName}", "{name}" ] mandatory: [ "{reasonName}", "{name}", "{host}", "{path}", "{id}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -116,7 +116,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/MergeConfirmation/Email/body.{language}.html body-path: classpath:notification_templates/MergeConfirmation/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{userName}", "{host}" ] mandatory: [ "{userName}", "{host}", "{confirmationToken}" ]
optional: optional:
- key: "{expiration_time}" - key: "{expiration_time}"
value: --- value: ---
@ -138,7 +138,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/Modified/Email/body.{language}.html body-path: classpath:notification_templates/Modified/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{reasonName}", "{name}" ] mandatory: [ "{reasonName}", "{name}", "{host}", "{path}", "{id}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -160,7 +160,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/ModifiedFinalised/Email/body.{language}.html body-path: classpath:notification_templates/ModifiedFinalised/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{reasonName}", "{name}" ] mandatory: [ "{reasonName}", "{name}", "{host}", "{path}", "{id}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -182,7 +182,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/Publish/Email/body.{language}.html body-path: classpath:notification_templates/Publish/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{reasonName}", "{name}" ] mandatory: [ "{reasonName}", "{name}", "{host}", "{path}", "{id}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -204,7 +204,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/Template/Email/body.{language}.html body-path: classpath:notification_templates/Template/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{templateName}" ] mandatory: [ "{templateName}", "{host}", "{templateID}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -221,7 +221,7 @@ notification:
key: C9BC3F16-057E-4BBA-8A5F-36BD835E5604 key: C9BC3F16-057E-4BBA-8A5F-36BD835E5604
subject-path: classpath:notification_templates/UnlinkConfirmation/Email/subject.{language}.txt subject-path: classpath:notification_templates/UnlinkConfirmation/Email/subject.{language}.txt
subject-field-options: subject-field-options:
mandatory: [ ] mandatory: ["{host}", "{confirmationToken}"]
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/UnlinkConfirmation/Email/body.{language}.html body-path: classpath:notification_templates/UnlinkConfirmation/Email/body.{language}.html
body-field-options: body-field-options:

View File

@ -72,7 +72,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/DataManagementPlan/Email/body.{language}.html body-path: classpath:notification_templates/DataManagementPlan/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{dmpname}", "{dmprole}" ] mandatory: [ "{dmpname}", "{dmprole}", "{host}", "{invitationID}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -116,7 +116,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/MergeConfirmation/Email/body.{language}.html body-path: classpath:notification_templates/MergeConfirmation/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{userName}", "{host}" ] mandatory: [ "{userName}", "{host}", "{confirmationToken}" ]
optional: optional:
- key: "{expiration_time}" - key: "{expiration_time}"
value: --- value: ---
@ -204,7 +204,7 @@ notification:
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/Template/Email/body.{language}.html body-path: classpath:notification_templates/Template/Email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{templateName}" ] mandatory: [ "{templateName}", "{host}", "{templateID}" ]
optional: optional:
- key: "{recipient}" - key: "{recipient}"
value: value:
@ -221,7 +221,7 @@ notification:
key: C9BC3F16-057E-4BBA-8A5F-36BD835E5604 key: C9BC3F16-057E-4BBA-8A5F-36BD835E5604
subject-path: classpath:notification_templates/UnlinkConfirmation/Email/subject.{language}.txt subject-path: classpath:notification_templates/UnlinkConfirmation/Email/subject.{language}.txt
subject-field-options: subject-field-options:
mandatory: [ ] mandatory: ["{host}", "{confirmationToken}"]
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/UnlinkConfirmation/Email/body.{language}.html body-path: classpath:notification_templates/UnlinkConfirmation/Email/body.{language}.html
body-field-options: body-field-options:

View File

@ -355,6 +355,23 @@
<version>1.0.0</version> <version>1.0.0</version>
</dependency> </dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>queue-inbox</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>queue-outbox</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>rabbitmq-core</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>

View File

@ -2,6 +2,7 @@ package eu.eudat.controllers.v2;
import eu.eudat.audit.AuditableAction; import eu.eudat.audit.AuditableAction;
import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.authorization.OwnedResource;
import eu.eudat.authorization.Permission; import eu.eudat.authorization.Permission;
import eu.eudat.data.LockEntity; import eu.eudat.data.LockEntity;
import eu.eudat.model.Lock; import eu.eudat.model.Lock;
@ -65,6 +66,7 @@ public class LockController {
private final MessageSource messageSource; private final MessageSource messageSource;
private final AuthorizationService authorizationService; private final AuthorizationService authorizationService;
private final AuthorizationService authService;
@Autowired @Autowired
public LockController(BuilderFactory builderFactory, public LockController(BuilderFactory builderFactory,
@ -73,7 +75,7 @@ public class LockController {
CensorFactory censorFactory, CensorFactory censorFactory,
QueryFactory queryFactory, QueryFactory queryFactory,
MessageSource messageSource, MessageSource messageSource,
AuthorizationService authorizationService) { AuthorizationService authorizationService, AuthorizationService authService) {
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.auditService = auditService; this.auditService = auditService;
this.lockService = lockService; this.lockService = lockService;
@ -81,6 +83,7 @@ public class LockController {
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.messageSource = messageSource; this.messageSource = messageSource;
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.authService = authService;
} }
@PostMapping("query") @PostMapping("query")
@ -154,20 +157,19 @@ public class LockController {
} }
@Transactional @Transactional
@PostMapping("target/status/{id}") @GetMapping("target/status/{id}")
public @ResponseBody ResponseEntity<ResponseItem<Boolean>> getLocked(@RequestBody LockLookup lookup) throws Exception { public @ResponseBody Boolean getLocked(@PathVariable("id") UUID targetId) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole); this.authService.authorizeAtLeastOneForce(targetId != null ? List.of(new OwnedResource(targetId)) : null, Permission.BrowseLock);
boolean locked = this.lockService.isLocked(lookup); return this.lockService.isLocked(targetId);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Boolean>().status(ApiMessageCode.SUCCESS_MESSAGE).message("locked").payload(locked));
} }
@Transactional @Transactional
@PostMapping("target/unlock/{id}") @DeleteMapping("target/unlock/{id}")
public @ResponseBody ResponseEntity<ResponseItem<String>> unlock(@RequestBody LockLookup lookup) throws Exception { public @ResponseBody ResponseEntity<ResponseItem<String>> unlock(@PathVariable("id") UUID targetId) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole); this.authService.authorizeAtLeastOneForce(targetId != null ? List.of(new OwnedResource(targetId)) : null, Permission.BrowseLock);
this.lockService.unlock(lookup); this.lockService.unlock(targetId);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload("Lock Removed")); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload("Lock Removed"));
} }

View File

@ -8,7 +8,6 @@ import eu.eudat.models.data.ContactEmail.ContactEmailModel;
import eu.eudat.models.data.ContactEmail.PublicContactEmailModel; import eu.eudat.models.data.ContactEmail.PublicContactEmailModel;
import eu.eudat.query.UserContactInfoQuery; import eu.eudat.query.UserContactInfoQuery;
import eu.eudat.query.UserQuery; import eu.eudat.query.UserQuery;
import eu.eudat.service.mail.SimpleMail;
import gr.cite.tools.data.query.Ordering; import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -35,28 +34,28 @@ public class ContactEmailManager {
} }
public void sendContactEmail(ContactEmailModel contactEmailModel) throws MessagingException, InvalidApplicationException { public void sendContactEmail(ContactEmailModel contactEmailModel) throws MessagingException, InvalidApplicationException {
UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first(); // UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first();
SimpleMail mail = new SimpleMail(); // SimpleMail mail = new SimpleMail();
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); // UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); // query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
String enrichedMail = contactEmailModel.getDescription() + "\n\n" + "Send by user: " + query.first().getValue() ; // String enrichedMail = contactEmailModel.getDescription() + "\n\n" + "Send by user: " + query.first().getValue() ;
mail.setSubject(contactEmailModel.getSubject()); // mail.setSubject(contactEmailModel.getSubject());
mail.setTo(environment.getProperty("contact_email.mail")); // mail.setTo(environment.getProperty("contact_email.mail"));
mail.setContent(enrichedMail); // mail.setContent(enrichedMail);
mail.setFrom(query.first().getValue()); // mail.setFrom(query.first().getValue());
//
apiContext.getUtilitiesService().getMailService().sendSimpleMail(mail); // apiContext.getUtilitiesService().getMailService().sendSimpleMail(mail);
} }
public void sendContactEmailNoAuth(PublicContactEmailModel contactEmailModel) throws MessagingException { public void sendContactEmailNoAuth(PublicContactEmailModel contactEmailModel) throws MessagingException {
SimpleMail mail = new SimpleMail(); // SimpleMail mail = new SimpleMail();
String enrichedMail = contactEmailModel.getMessage() + "\n\n" + "Send by user: " + contactEmailModel.getEmail() ; // String enrichedMail = contactEmailModel.getMessage() + "\n\n" + "Send by user: " + contactEmailModel.getEmail() ;
mail.setSubject(contactEmailModel.getAffiliation()); // mail.setSubject(contactEmailModel.getAffiliation());
mail.setTo(environment.getProperty("contact_email.mail")); // mail.setTo(environment.getProperty("contact_email.mail"));
mail.setContent(enrichedMail); // mail.setContent(enrichedMail);
mail.setFrom(contactEmailModel.getEmail()); // mail.setFrom(contactEmailModel.getEmail());
//
apiContext.getUtilitiesService().getMailService().sendSimpleMail(mail); // apiContext.getUtilitiesService().getMailService().sendSimpleMail(mail);
} }
public void emailValidation(ContactEmailModel contactEmailModel) throws Exception { public void emailValidation(ContactEmailModel contactEmailModel) throws Exception {

View File

@ -75,12 +75,7 @@ public class EmailConfirmationManager {
// if (user.getEmail() != null) //TODO // if (user.getEmail() != null) //TODO
// throw new HasConfirmedEmailException("User already has confirmed his Email."); // throw new HasConfirmedEmailException("User already has confirmed his Email.");
apiContext.getUtilitiesService().getConfirmationEmailService().createConfirmationEmail( apiContext.getUtilitiesService().getConfirmationEmailService().sentConfirmationEmail(databaseRepository.getLoginConfirmationEmailDao(), email, user);
databaseRepository.getLoginConfirmationEmailDao(),
apiContext.getUtilitiesService().getMailService(),
email,
this.userScope.getUserId()
);
} }
private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser) throws InvalidApplicationException { private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser) throws InvalidApplicationException {

View File

@ -9,6 +9,9 @@ import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;
import eu.eudat.model.User; import eu.eudat.model.User;
import eu.eudat.models.data.invitation.Invitation; import eu.eudat.models.data.invitation.Invitation;
import eu.eudat.query.DmpQuery;
import eu.eudat.query.UserQuery;
import gr.cite.tools.data.query.QueryFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -25,12 +28,14 @@ public class InvitationsManager {
private ApiContext apiContext; private ApiContext apiContext;
private DataManagementPlanManager dataManagementPlanManager; private DataManagementPlanManager dataManagementPlanManager;
private final UserScope userScope; private final UserScope userScope;
private final QueryFactory queryFactory;
@Autowired @Autowired
public InvitationsManager(ApiContext apiContext, DataManagementPlanManager dataManagementPlanManager, UserScope userScope) { public InvitationsManager(ApiContext apiContext, DataManagementPlanManager dataManagementPlanManager, UserScope userScope, QueryFactory queryFactory) {
this.apiContext = apiContext; this.apiContext = apiContext;
this.dataManagementPlanManager = dataManagementPlanManager; this.dataManagementPlanManager = dataManagementPlanManager;
this.userScope = userScope; this.userScope = userScope;
this.queryFactory = queryFactory;
} }
public void inviteUsers(Invitation invitation) throws Exception { public void inviteUsers(Invitation invitation) throws Exception {
@ -63,9 +68,19 @@ public class InvitationsManager {
apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation); apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation);
}*/ }*/
} }
DmpEntity dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan()); DmpQuery dmpQuery = this.queryFactory.query(DmpQuery.class).ids(invitation.getDataManagementPlan());
// apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), apiContext.getUtilitiesService().getMailService(), invitation.getUsers().stream().map(UserInfoInvitationModel::toDataModel).collect(Collectors.toList()), dataManagementPlan, invitation.getRole(), principalUser); if(dmpQuery != null){
apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userInfoToUserDmp, dataManagementPlan); // DmpEntity dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan());
DmpEntity dmpEntity = dmpQuery.first();
UserQuery userQuery = this.queryFactory.query(UserQuery.class).ids(invitation.getUsers().stream().map(user -> user.getId()).collect(Collectors.toList()));
if (userQuery != null){
List<UserEntity> userEntities = userQuery.collect();
// apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), invitation.getUsers().stream().map(UserInfoInvitationModel::toDataModel).collect(Collectors.toList()), dmpEntity, invitation.getRole(), principalUser);
apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), userEntities, dmpEntity, invitation.getRole(), principalUser);
apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userInfoToUserDmp, dmpEntity);
}
}
} }
public List<User> getUsers() throws InstantiationException, IllegalAccessException, InvalidApplicationException { public List<User> getUsers() throws InstantiationException, IllegalAccessException, InvalidApplicationException {

View File

@ -10,7 +10,10 @@ import eu.eudat.exceptions.emailconfirmation.TokenExpiredException;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.model.UserContactInfo;
import eu.eudat.query.UserContactInfoQuery;
import eu.eudat.query.UserQuery; import eu.eudat.query.UserQuery;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -70,18 +73,18 @@ public class MergeEmailConfirmationManager {
return userToBeMergedEmail; return userToBeMergedEmail;
} }
public void sendConfirmationEmail(String email, UUID userId, Integer provider) throws HasConfirmedEmailException, InvalidApplicationException { public void sendMergeConfirmationEmail(String email, Integer provider) throws HasConfirmedEmailException, InvalidApplicationException {
UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first(); UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first();
//TODO UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
// if (user.getEmail() != null && !user.getEmail().equals(email)) { query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
// apiContext.getUtilitiesService().getConfirmationEmailService().createMergeConfirmationEmail( if (query.first().getValue() != null && !query.first().getValue().equals(email)) {
// databaseRepository.getLoginConfirmationEmailDao(), apiContext.getUtilitiesService().getConfirmationEmailService().sentMergeConfirmationEmail(
// apiContext.getUtilitiesService().getMailService(), databaseRepository.getLoginConfirmationEmailDao(),
// email, email,
// user, user,
// provider provider
// ); );
// } }
} }
@Transactional @Transactional

View File

@ -7,8 +7,6 @@ import eu.eudat.commons.enums.old.notification.ActiveStatus;
import eu.eudat.commons.enums.old.notification.NotifyState; import eu.eudat.commons.enums.old.notification.NotifyState;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;
import eu.eudat.query.UserQuery; import eu.eudat.query.UserQuery;
import eu.eudat.service.mail.MailService;
import eu.eudat.service.mail.SimpleMail;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -27,14 +25,14 @@ public class NotificationManager {
private ApiContext apiContext; private ApiContext apiContext;
private Environment environment; private Environment environment;
private MailService mailService;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
@Autowired @Autowired
public NotificationManager(ApiContext apiContext, Environment environment, MailService mailService, QueryFactory queryFactory) { public NotificationManager(ApiContext apiContext, Environment environment,
// MailService mailService,
QueryFactory queryFactory) {
this.apiContext = apiContext; this.apiContext = apiContext;
this.environment = environment; this.environment = environment;
this.mailService = mailService;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
} }
@ -64,20 +62,20 @@ public class NotificationManager {
case DMP_MODIFIED: case DMP_MODIFIED:
case DATASET_MODIFIED: case DATASET_MODIFIED:
subjectTemplate = this.environment.getProperty("notification.modified.subject"); subjectTemplate = this.environment.getProperty("notification.modified.subject");
contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.modified.template")); // contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.modified.template"));
break; break;
case DMP_PUBLISH: case DMP_PUBLISH:
subjectTemplate = this.environment.getProperty("notification.publish.subject"); subjectTemplate = this.environment.getProperty("notification.publish.subject");
contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.publish.template")); // contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.publish.template"));
break; break;
case DMP_FINALISED: case DMP_FINALISED:
subjectTemplate = this.environment.getProperty("notification.finalised.subject"); subjectTemplate = this.environment.getProperty("notification.finalised.subject");
contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.finalised.template")); // contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.finalised.template"));
break; break;
case DMP_MODIFIED_FINALISED: case DMP_MODIFIED_FINALISED:
case DATASET_MODIFIED_FINALISED: case DATASET_MODIFIED_FINALISED:
subjectTemplate = this.environment.getProperty("notification.modifiedFinalised.subject"); subjectTemplate = this.environment.getProperty("notification.modifiedFinalised.subject");
contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.modified_finalised.template")); // contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.modified_finalised.template"));
break; break;
} }
@ -95,20 +93,20 @@ public class NotificationManager {
} }
private void sendEmailNotification(Notification notification, UserEntity userInfo, Map<String, String> data, String subjectTemplate, String contentTemplate) throws IOException { private void sendEmailNotification(Notification notification, UserEntity userInfo, Map<String, String> data, String subjectTemplate, String contentTemplate) throws IOException {
SimpleMail simpleMail = new SimpleMail(); // SimpleMail simpleMail = new SimpleMail();
simpleMail.setFrom(this.environment.getProperty("mail.from")); // simpleMail.setFrom(this.environment.getProperty("mail.from"));
simpleMail.setSubject(makeSubject(data, subjectTemplate)); // simpleMail.setSubject(makeSubject(data, subjectTemplate));
simpleMail.setTo(notification.getContactHint()); // simpleMail.setTo(notification.getContactHint());
simpleMail.setContent(makeContent(data, notification, userInfo, contentTemplate)); // simpleMail.setContent(makeContent(data, notification, userInfo, contentTemplate));
try { // try {
mailService.sendSimpleMail(simpleMail); // mailService.sendSimpleMail(simpleMail);
notification.setNotifyState(NotifyState.SUCCEEDED); // notification.setNotifyState(NotifyState.SUCCEEDED);
notification.setUpdatedAt(new Date()); // notification.setUpdatedAt(new Date());
} catch (MessagingException e) { // } catch (MessagingException e) {
notification.setNotifyState(NotifyState.ERROR); // notification.setNotifyState(NotifyState.ERROR);
notification.setUpdatedAt(new Date()); // notification.setUpdatedAt(new Date());
logger.error(e.getMessage(), e); // logger.error(e.getMessage(), e);
} // }
} }
private String makeSubject(Map<String, String> data, String subjectTemplate) { private String makeSubject(Map<String, String> data, String subjectTemplate) {

View File

@ -2,7 +2,7 @@ package eu.eudat.logic.managers;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.UserCredentialEntity; import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.data.old.EmailConfirmation; import eu.eudat.data.old.EmailConfirmation;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException;
@ -32,12 +32,14 @@ public class UnlinkEmailConfirmationManager {
private ApiContext apiContext; private ApiContext apiContext;
private DatabaseRepository databaseRepository; private DatabaseRepository databaseRepository;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final UserScope userScope;
@Autowired @Autowired
public UnlinkEmailConfirmationManager(ApiContext apiContext, QueryFactory queryFactory) { public UnlinkEmailConfirmationManager(ApiContext apiContext, QueryFactory queryFactory, UserScope userScope) {
this.apiContext = apiContext; this.apiContext = apiContext;
this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository();
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.userScope = userScope;
} }
@Transactional @Transactional
@ -79,14 +81,13 @@ public class UnlinkEmailConfirmationManager {
// } // }
} }
public void sendConfirmationEmail(String email, UUID userId, Integer provider) throws InvalidApplicationException { public void sendUnlinkConfirmationEmail(String email, Integer provider) throws InvalidApplicationException {
UserEntity user = this.queryFactory.query(UserQuery.class).ids(userId).first(); UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first();
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
if (query.first().getValue() != null && !query.first().getValue().equals(email)) { if (query.first().getValue() != null && !query.first().getValue().equals(email)) {
apiContext.getUtilitiesService().getConfirmationEmailService().createUnlinkConfirmationEmail( apiContext.getUtilitiesService().getConfirmationEmailService().sentUnlinkConfirmationEmail(
databaseRepository.getLoginConfirmationEmailDao(), databaseRepository.getLoginConfirmationEmailDao(),
apiContext.getUtilitiesService().getMailService(),
email, email,
user, user,
provider provider

View File

@ -1,24 +1,15 @@
package eu.eudat.logic.services.utilities; package eu.eudat.logic.services.utilities;
import eu.eudat.data.dao.entities.EmailConfirmationDao; import eu.eudat.data.dao.entities.EmailConfirmationDao;
import eu.eudat.data.old.EmailConfirmation;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.service.mail.MailService;
import javax.management.InvalidApplicationException; import javax.management.InvalidApplicationException;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public interface ConfirmationEmailService { public interface ConfirmationEmailService {
public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId); public void sentConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user) throws InvalidApplicationException;
public void createMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UserEntity user, Integer provider) throws InvalidApplicationException;
public void createUnlinkConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UserEntity user, Integer provider) throws InvalidApplicationException; public void sentUnlinkConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user, Integer provider) throws InvalidApplicationException;
public CompletableFuture sentConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService); public void sentMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user, Integer provider) throws InvalidApplicationException;
public CompletableFuture sentMergeConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService, String userName);
public CompletableFuture sentUnlinkConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService);
} }

View File

@ -1,16 +1,20 @@
package eu.eudat.logic.services.utilities; package eu.eudat.logic.services.utilities;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.enums.ContactInfoType;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.notification.*;
import eu.eudat.configurations.notification.NotificationProperties;
import eu.eudat.data.dao.entities.EmailConfirmationDao; import eu.eudat.data.dao.entities.EmailConfirmationDao;
import eu.eudat.data.old.EmailConfirmation; import eu.eudat.data.old.EmailConfirmation;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEvent;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler;
import eu.eudat.model.UserContactInfo; import eu.eudat.model.UserContactInfo;
import eu.eudat.query.UserContactInfoQuery; import eu.eudat.query.UserContactInfoQuery;
import eu.eudat.service.mail.MailService;
import eu.eudat.service.mail.SimpleMail;
import gr.cite.tools.data.query.Ordering; import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -19,11 +23,7 @@ import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException; import javax.management.InvalidApplicationException;
import java.util.Date; import java.util.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@Service("ConfirmationEmailService") @Service("ConfirmationEmailService")
public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
@ -32,125 +32,24 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
private Environment environment; private Environment environment;
private final UserScope userScope; private final UserScope userScope;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final JsonHandlingService jsonHandlingService;
private final NotificationIntegrationEventHandler eventHandler;
private final NotificationProperties notificationProperties;
public ConfirmationEmailServiceImpl(/*Logger logger,*/ Environment environment, UserScope userScope, QueryFactory queryFactory) {
public ConfirmationEmailServiceImpl(/*Logger logger,*/ Environment environment, UserScope userScope, QueryFactory queryFactory, JsonHandlingService jsonHandlingService, NotificationIntegrationEventHandler eventHandler, NotificationProperties notificationProperties) {
// this.logger = logger; // this.logger = logger;
this.environment = environment; this.environment = environment;
this.userScope = userScope; this.userScope = userScope;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.jsonHandlingService = jsonHandlingService;
this.eventHandler = eventHandler;
this.notificationProperties = notificationProperties;
} }
@Override @Override
public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId) { public void sentConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user) throws InvalidApplicationException {
EmailConfirmation confirmationEmail = new EmailConfirmation();
confirmationEmail.setEmail(email);
confirmationEmail.setExpiresAt(Date
.from(new Date()
.toInstant()
.plusSeconds(Long.parseLong(this.environment.getProperty("conf_email.expiration_time_seconds")))
)
);
confirmationEmail.setUserId(userId);
confirmationEmail.setIsConfirmed(false);
confirmationEmail.setToken(UUID.randomUUID());
confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail);
sentConfirmationEmail(confirmationEmail, mailService);
}
@Override
public CompletableFuture sentConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService) {
return CompletableFuture.runAsync(() -> {
SimpleMail mail = new SimpleMail();
mail.setSubject(environment.getProperty("conf_email.subject"));
mail.setContent(createContent(confirmationEmail.getToken(), mailService));
mail.setTo(confirmationEmail.getEmail());
try {
mailService.sendSimpleMail(mail);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
});
}
private String createContent(UUID confirmationToken, MailService mailService) {
String content = mailService.getMailTemplateContent(this.environment.getProperty("email.confirmation"));
content = content.replace("{confirmationToken}", confirmationToken.toString());
content = content.replace("{expiration_time}", secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds"))));
content = content.replace("{host}", this.environment.getProperty("dmp.domain"));
return content;
}
@Override
public CompletableFuture sentMergeConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService, String userName) {
return CompletableFuture.runAsync(() -> {
SimpleMail mail = new SimpleMail();
mail.setSubject(environment.getProperty("conf_email.subject"));
mail.setContent(createMergeContent(confirmationEmail.getToken(), mailService, userName));
mail.setTo(confirmationEmail.getEmail());
try {
mailService.sendSimpleMail(mail);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
});
}
@Override
public CompletableFuture sentUnlinkConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService) {
String email = null;
try {
Map<String, Object> map = new ObjectMapper().readValue(confirmationEmail.getData(), new TypeReference<Map<String, Object>>() {});
email = (String) map.get("email");
}
catch (JsonProcessingException e){
logger.error(e.getMessage(), e);
}
String finalEmail = email;
return CompletableFuture.runAsync(() -> {
SimpleMail mail = new SimpleMail();
mail.setSubject(environment.getProperty("conf_email.subject"));
mail.setContent(createUnlinkContent(confirmationEmail.getToken(), mailService, finalEmail));
mail.setTo(confirmationEmail.getEmail());
try {
mailService.sendSimpleMail(mail);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
});
}
private String createMergeContent(UUID confirmationToken, MailService mailService, String userName) {
String content = mailService.getMailTemplateContent(this.environment.getProperty("email.merge"));
content = content.replace("{userName}", userName);
content = content.replace("{confirmationToken}", confirmationToken.toString());
content = content.replace("{expiration_time}", secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds"))));
content = content.replace("{host}", this.environment.getProperty("dmp.domain"));
return content;
}
private String createUnlinkContent(UUID confirmationToken, MailService mailService, String email) {
String content = mailService.getMailTemplateContent(this.environment.getProperty("email.unlink"));
content = content.replace("{confirmationToken}", confirmationToken.toString());
content = content.replace("{expiration_time}", secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds"))));
content = content.replace("{host}", this.environment.getProperty("dmp.domain"));
content = content.replace("{email}", email);
return content;
}
private String secondsToTime(int seconds) {
int sec = seconds % 60;
int hour = seconds / 60;
int min = hour % 60;
hour = hour / 60;
return (hour + ":" + min + ":" + sec);
}
@Override
public void createMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService,
String email, UserEntity user, Integer provider) throws InvalidApplicationException {
EmailConfirmation confirmationEmail = new EmailConfirmation(); EmailConfirmation confirmationEmail = new EmailConfirmation();
confirmationEmail.setEmail(email); confirmationEmail.setEmail(email);
confirmationEmail.setExpiresAt(Date confirmationEmail.setExpiresAt(Date
@ -160,24 +59,30 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
) )
); );
confirmationEmail.setUserId(user.getId()); confirmationEmail.setUserId(user.getId());
try {
Map<String, Object> map = new HashMap<>();
map.put("userId", this.userScope.getUserId());
map.put("provider", provider.toString());
confirmationEmail.setData(new ObjectMapper().writeValueAsString(map));
} catch (JsonProcessingException | InvalidApplicationException e) {
logger.error(e.getMessage(), e);
}
confirmationEmail.setIsConfirmed(false); confirmationEmail.setIsConfirmed(false);
confirmationEmail.setToken(UUID.randomUUID()); confirmationEmail.setToken(UUID.randomUUID());
confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail); confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail);
sentMergeConfirmationEmail(confirmationEmail, mailService, user.getName());
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getConfirmation()));
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{host}", DataType.String, this.environment.getProperty("dmp.domain")));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString()));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds")))));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
} }
@Override @Override
public void createUnlinkConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, public void sentUnlinkConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user, Integer provider) throws InvalidApplicationException {
String email, UserEntity user, Integer provider) throws InvalidApplicationException {
EmailConfirmation confirmationEmail = new EmailConfirmation(); EmailConfirmation confirmationEmail = new EmailConfirmation();
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
@ -200,6 +105,77 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
confirmationEmail.setIsConfirmed(false); confirmationEmail.setIsConfirmed(false);
confirmationEmail.setToken(UUID.randomUUID()); confirmationEmail.setToken(UUID.randomUUID());
confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail); confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail);
sentUnlinkConfirmationEmail(confirmationEmail, mailService);
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getUnlinkConfirmation()));
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{host}", DataType.String, this.environment.getProperty("dmp.domain")));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString()));
fieldInfoList.add(new FieldInfo("{email}", DataType.String, email));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds")))));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
} }
@Override
public void sentMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao,
String email, UserEntity user, Integer provider) throws InvalidApplicationException {
EmailConfirmation confirmationEmail = new EmailConfirmation();
confirmationEmail.setEmail(email);
confirmationEmail.setExpiresAt(Date
.from(new Date()
.toInstant()
.plusSeconds(Long.parseLong(this.environment.getProperty("conf_email.expiration_time_seconds")))
)
);
confirmationEmail.setUserId(user.getId());
try {
Map<String, Object> map = new HashMap<>();
map.put("userId", this.userScope.getUserId());
map.put("provider", provider.toString());
confirmationEmail.setData(new ObjectMapper().writeValueAsString(map));
} catch (JsonProcessingException | InvalidApplicationException e) {
logger.error(e.getMessage(), e);
}
confirmationEmail.setIsConfirmed(false);
confirmationEmail.setToken(UUID.randomUUID());
confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail);
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getMergeConfirmation()));
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{userName}", DataType.String, user.getName()));
fieldInfoList.add(new FieldInfo("{host}", DataType.String, this.environment.getProperty("dmp.domain")));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString()));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds")))));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
}
private String secondsToTime(int seconds) {
int sec = seconds % 60;
int hour = seconds / 60;
int min = hour % 60;
hour = hour / 60;
return (hour + ":" + min + ":" + sec);
}
} }

View File

@ -8,8 +8,9 @@ import eu.eudat.data.dao.entities.InvitationDao;
import eu.eudat.data.old.Invitation; import eu.eudat.data.old.Invitation;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.service.mail.MailService;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import javax.management.InvalidApplicationException;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -19,7 +20,7 @@ public interface InvitationService {
void assignToDmp(DMPDao dmpDao, DmpUserEntity user, DmpEntity dmp); void assignToDmp(DMPDao dmpDao, DmpUserEntity user, DmpEntity dmp);
void createInvitations(InvitationDao invitationDao, MailService mailService, List<UserEntity> users, DmpEntity dmp, Integer role, UserEntity creator) throws MessagingException; void createInvitations(InvitationDao invitationDao, List<UserEntity> users, DmpEntity dmp, Integer role, UserEntity creator) throws MessagingException, InvalidApplicationException;
CompletableFuture sendInvitationAsync(DmpEntity dmp, Invitation invitation, String recipient, MailService mailService, Integer role) throws MessagingException; void sendInvitation(DmpEntity dmp, Invitation invitation, UserEntity user, Integer role) throws InvalidApplicationException;
} }

View File

@ -1,17 +1,24 @@
package eu.eudat.logic.services.utilities; package eu.eudat.logic.services.utilities;
import eu.eudat.commons.JsonHandlingService;
import eu.eudat.commons.enums.ContactInfoType;
import eu.eudat.commons.enums.DmpUserRole;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.notification.*;
import eu.eudat.configurations.notification.NotificationProperties;
import eu.eudat.data.DmpEntity; import eu.eudat.data.DmpEntity;
import eu.eudat.data.DmpUserEntity; import eu.eudat.data.DmpUserEntity;
import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.dao.entities.DMPDao;
import eu.eudat.data.dao.entities.InvitationDao; import eu.eudat.data.dao.entities.InvitationDao;
import eu.eudat.data.old.Invitation; import eu.eudat.data.old.Invitation;
import eu.eudat.data.UserEntity; import eu.eudat.data.UserEntity;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEvent;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler;
import eu.eudat.model.UserContactInfo; import eu.eudat.model.UserContactInfo;
import eu.eudat.models.data.invitation.Properties; import eu.eudat.models.data.invitation.Properties;
import eu.eudat.query.UserContactInfoQuery; import eu.eudat.query.UserContactInfoQuery;
import eu.eudat.service.mail.MailService;
import eu.eudat.service.mail.SimpleMail;
import gr.cite.tools.data.query.Ordering; import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -23,20 +30,30 @@ import org.springframework.stereotype.Service;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller; import jakarta.xml.bind.Marshaller;
import javax.management.InvalidApplicationException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@Service("invitationService") @Service("invitationService")
public class InvitationServiceImpl implements InvitationService { public class InvitationServiceImpl implements InvitationService {
private static final Logger logger = LoggerFactory.getLogger(InvitationServiceImpl.class); private static final Logger logger = LoggerFactory.getLogger(InvitationServiceImpl.class);
private Environment environment; private Environment environment;
private final UserScope userScope;
private final NotificationIntegrationEventHandler eventHandler;
private final JsonHandlingService jsonHandlingService;
private final NotificationProperties notificationProperties;
@Autowired @Autowired
public InvitationServiceImpl(Environment environment, QueryFactory queryFactory) { public InvitationServiceImpl(Environment environment, UserScope userScope, NotificationIntegrationEventHandler eventHandler, JsonHandlingService jsonHandlingService, NotificationProperties notificationProperties, QueryFactory queryFactory) {
this.environment = environment; this.environment = environment;
this.userScope = userScope;
this.eventHandler = eventHandler;
this.jsonHandlingService = jsonHandlingService;
this.notificationProperties = notificationProperties;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
} }
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
@ -58,11 +75,11 @@ public class InvitationServiceImpl implements InvitationService {
} }
@Override @Override
public void createInvitations(InvitationDao invitationDao, MailService mailService, List<UserEntity> users, DmpEntity dmp, Integer role, UserEntity creator) throws MessagingException { public void createInvitations(InvitationDao invitationDao, List<UserEntity> users, DmpEntity dmp, Integer role, UserEntity creator) throws MessagingException, InvalidApplicationException {
for (UserEntity userInfo : users) { for (UserEntity user : users) {
Invitation invitation = new Invitation(); Invitation invitation = new Invitation();
// invitation.setDmp(dmp); //TODO // invitation.setDmp(dmp); //TODO
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(userInfo.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
invitation.setInvitationEmail(query.first().getValue()); invitation.setInvitationEmail(query.first().getValue());
invitation.setUser(creator); invitation.setUser(creator);
@ -80,37 +97,34 @@ public class InvitationServiceImpl implements InvitationService {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
invitationDao.createOrUpdate(invitation); invitationDao.createOrUpdate(invitation);
sendInvitationAsync(dmp, invitation, userInfo.getName(), mailService, role); this.sendInvitation(dmp, invitation, user, role);
} }
} }
@Override @Override
public CompletableFuture sendInvitationAsync(DmpEntity dmp, Invitation invitation, String recipient, MailService mailService, Integer role) { public void sendInvitation(DmpEntity dmp, Invitation invitation, UserEntity user, Integer role) throws InvalidApplicationException {
return CompletableFuture.runAsync(() -> {
SimpleMail mail = new SimpleMail();
mail.setSubject(createSubject(dmp, mailService.getMailTemplateSubject()));
mail.setContent(createContent(invitation.getId(), dmp, recipient, mailService.getMailTemplateContent(this.environment.getProperty("email.invite")), role));
mail.setTo(invitation.getInvitationEmail());
try {
mailService.sendSimpleMail(mail);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
});
}
private String createSubject(DmpEntity dmp, String templateSubject) { NotificationIntegrationEvent event = new NotificationIntegrationEvent();
String subject = templateSubject.replace("{dmpname}", dmp.getLabel()); event.setUserId(userScope.getUserIdSafe());
return subject;
}
private String createContent(UUID invitationID, DmpEntity dmp, String recipient, String templateContent, Integer role) { UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId());
String content = templateContent.replace("{dmpname}", dmp.getLabel()); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
content = content.replace("{invitationID}", invitationID.toString());
content = content.replace("{recipient}", recipient);
content = content.replace("{host}", this.environment.getProperty("dmp.domain"));
// content = content.replace("{dmprole}", UserDMP.UserDMPRoles.fromInteger(role).name()); //TODO
return content; List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue()));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getDataManagementPlan()));
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
fieldInfoList.add(new FieldInfo("{invitationID}", DataType.String, invitation.getId().toString()));
fieldInfoList.add(new FieldInfo("{host}", DataType.String, this.environment.getProperty("dmp.domain")));
fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel()));
fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, DmpUserRole.of(role.shortValue()).toString()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
} }
} }

View File

@ -1,7 +1,7 @@
package eu.eudat.logic.services.utilities; package eu.eudat.logic.services.utilities;
import eu.eudat.logic.services.forms.VisibilityRuleService; import eu.eudat.logic.services.forms.VisibilityRuleService;
import eu.eudat.service.mail.MailService; //import eu.eudat.service.mail.MailService;
/** /**
* Created by ikalyvas on 3/1/2018. * Created by ikalyvas on 3/1/2018.
@ -10,7 +10,5 @@ public interface UtilitiesService {
InvitationService getInvitationService(); InvitationService getInvitationService();
MailService getMailService();
ConfirmationEmailService getConfirmationEmailService(); ConfirmationEmailService getConfirmationEmailService();
} }

View File

@ -1,8 +1,5 @@
package eu.eudat.logic.services.utilities; package eu.eudat.logic.services.utilities;
import eu.eudat.logic.services.forms.VisibilityRuleService;
import eu.eudat.logic.services.forms.VisibilityRuleServiceImpl;
import eu.eudat.service.mail.MailService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -13,13 +10,11 @@ import org.springframework.stereotype.Service;
public class UtilitiesServiceImpl implements UtilitiesService { public class UtilitiesServiceImpl implements UtilitiesService {
private InvitationService invitationService; private InvitationService invitationService;
private MailService mailService;
private ConfirmationEmailService confirmationEmailService; private ConfirmationEmailService confirmationEmailService;
@Autowired @Autowired
public UtilitiesServiceImpl(InvitationService invitationService, MailService mailService, ConfirmationEmailService confirmationEmailService) { public UtilitiesServiceImpl(InvitationService invitationService, ConfirmationEmailService confirmationEmailService) {
this.invitationService = invitationService; this.invitationService = invitationService;
this.mailService = mailService;
this.confirmationEmailService = confirmationEmailService; this.confirmationEmailService = confirmationEmailService;
} }
@ -33,8 +28,4 @@ public class UtilitiesServiceImpl implements UtilitiesService {
return invitationService; return invitationService;
} }
@Override
public MailService getMailService() {
return mailService;
}
} }

View File

@ -25,5 +25,8 @@ spring:
optional:classpath:config/errors.yml[.yml], optional:classpath:config/errors-${spring.profiles.active}.yml[.yml], optional:file:../config/errors-${spring.profiles.active}.yml[.yml], optional:classpath:config/errors.yml[.yml], optional:classpath:config/errors-${spring.profiles.active}.yml[.yml], optional:file:../config/errors-${spring.profiles.active}.yml[.yml],
optional:classpath:config/storage.yml[.yml], optional:classpath:config/storage-${spring.profiles.active}.yml[.yml], optional:file:../config/storage-${spring.profiles.active}.yml[.yml], optional:classpath:config/storage.yml[.yml], optional:classpath:config/storage-${spring.profiles.active}.yml[.yml], optional:file:../config/storage-${spring.profiles.active}.yml[.yml],
optional:classpath:config/reference-type.yml[.yml], optional:classpath:config/reference-type-${spring.profiles.active}.yml[.yml], optional:file:../config/reference-type-${spring.profiles.active}.yml[.yml], optional:classpath:config/reference-type.yml[.yml], optional:classpath:config/reference-type-${spring.profiles.active}.yml[.yml], optional:file:../config/reference-type-${spring.profiles.active}.yml[.yml],
optional:classpath:config/tenant.yml[.yml], optional:classpath:config/tenant-${spring.profiles.active}.yml[.yml], optional:file:../config/tenant-${spring.profiles.active}.yml[.yml] optional:classpath:config/tenant.yml[.yml], optional:classpath:config/tenant-${spring.profiles.active}.yml[.yml], optional:file:../config/tenant-${spring.profiles.active}.yml[.yml],
optional:classpath:config/queue.yml[.yml], optional:classpath:config/queue-${spring.profiles.active}.yml[.yml], optional:file:../config/queue-${spring.profiles.active}.yml[.yml],
optional:classpath:config/notification.yml[.yml], optional:classpath:config/notification-${spring.profiles.active}.yml[.yml], optional:file:../config/notification-${spring.profiles.active}.yml[.yml]

View File

@ -9,6 +9,6 @@ keycloak-resources:
Manager: Manager:
groupId: 1753f7a7-cedb-4ad4-ae5f-96fe9bdabe3e groupId: 1753f7a7-cedb-4ad4-ae5f-96fe9bdabe3e
groupTitle: role-manager groupTitle: role-manager
DatasetTemplateEditor: DescriptionTemplateEditor:
groupId: 969aa109-9c4d-4f12-ba9b-4a84b2e5a394 groupId: b0ea3cf3-21b0-4c6b-9c42-fb09f0e09dbb
groupTitle: role-dataset-template-editor groupTitle: role-description-template-editor

View File

@ -7,7 +7,4 @@ keycloak-client:
clientSecret: ${KEYCLOAK_API_CLIENT_SECRET:} clientSecret: ${KEYCLOAK_API_CLIENT_SECRET:}
keycloak-resources: keycloak-resources:
authorities: null authorities: null
tenantGroupsNamingStrategy: null
guestsGroup: null
administratorsGroup: null

View File

@ -0,0 +1,10 @@
notification:
confirmation: 4FDBFA80-7A71-4A69-B854-67CBB70648F1
dataManagementPlan: 065DEECD-21BB-44AF-9983-E660FDF24BC4
finalised: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E
mergeConfirmation: BFE68845-CB05-4C5A-A03D-29161A7C9660
modified: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
modifiedFinalised: D3CD55FE-8DA2-42E7-A501-3795EE4F16D3
publish: 55736F7A-83AB-4190-AF43-9D031A6F9612
template: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B
unlinkConfirmation: C9BC3F16-057E-4BBA-8A5F-36BD835E5604

View File

@ -13,9 +13,9 @@ permissions:
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
DatasetProfileManagerRole: DescriptionTemplateEditorRole:
roles: roles:
- DatasetProfileManager - DescriptionTemplateEditor
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
@ -258,21 +258,21 @@ permissions:
BrowseDescriptionTemplate: BrowseDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
EditDescriptionTemplate: EditDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
DeleteDescriptionTemplate: DeleteDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
claims: [ ] claims: [ ]
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
@ -280,7 +280,7 @@ permissions:
CloneDescriptionTemplate: CloneDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
claims: [ ] claims: [ ]
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
@ -288,7 +288,7 @@ permissions:
CreateNewVersionDescriptionTemplate: CreateNewVersionDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
claims: [ ] claims: [ ]
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
@ -296,7 +296,7 @@ permissions:
ImportDescriptionTemplate: ImportDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
claims: [ ] claims: [ ]
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
@ -304,7 +304,7 @@ permissions:
ExportDescriptionTemplate: ExportDescriptionTemplate:
roles: roles:
- Admin - Admin
- DatasetProfileManager - DescriptionTemplateEditor
claims: [ ] claims: [ ]
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false

View File

@ -0,0 +1,18 @@
queue:
rabbitmq:
durable: true
queue: cite_dmp_devel_web_inbox_queue
exchange: cite_dmp_devel_queue
listenerEnabled: true
publisherEnabled: true
task:
publisher:
options:
exchange: cite_dmp_devel_queue
rabbitmq:
enable: true
listener:
options:
exchange: cite_dmp_devel_queue
rabbitmq:
enable: true

View File

@ -0,0 +1,58 @@
spring:
rabbitmq:
host: ${RABBIT_HOST}
port: ${RABBIT_PORT}
username: ${RABBIT_USER}
password: ${RABBIT_PASS}
ssl:
enabled: false
queue:
rabbitmq:
enable: true
app-id: ${THE_API_ID}
durable: null
queue: null
exchange: null
listenerEnabled: true
publisherEnabled: true
#TODO
connection-recovery:
enable: true
network-recovery-interval: 5000
unreachable-recovery-interval: 5000
task:
publisher:
enable: true
options:
exchange: null
forget-me-completed-topic: forgetme.completed
notify-topic: notification.notify
tenant-reactivation-topic: tenant.reactivated
tenant-removal-topic: tenant.remove
tenant-touch-topic: tenant.touch
tenant-user-invite-topic: tenant.invite
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
generate-file-topic: generate.file
rabbitmq:
enable: true
interval-seconds: 30
options:
retry-threashold: 100
retry-delay-step-seconds: 300
max-retry-delay-seconds: 10800
too-old-to-send-seconds: 604800
confirm-timeout-seconds: 30
listener:
enable: true
options:
exchange: null
user-removal-topic: [ "user.remove" ]
user-touched-topic: [ "user.touch" ]
rabbitmq:
enable: true
interval-seconds: 30
options:
retry-threashold: 100
retry-delay-step-seconds: 300
max-retry-delay-seconds: 10800
too-old-to-send-seconds: 604800

View File

@ -2,5 +2,5 @@ export enum AppRole {
Admin = "Admin", Admin = "Admin",
Manager = "Manager", Manager = "Manager",
User = "User", User = "User",
DatasetTemplateEditor = "DatasetProfileManager" DescriptionTemplateEditor = "DescriptionTemplateEditor"
} }

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpHeaders, HttpClient } from '@angular/common/http'; import { HttpHeaders, HttpClient, HttpResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs'; import { Observable, throwError } from 'rxjs';
import { Lock, LockModel, LockPersist } from '@app/core/model/lock/lock.model'; import { Lock, LockModel, LockPersist } from '@app/core/model/lock/lock.model';
import { ConfigurationService } from '../configuration/configuration.service'; import { ConfigurationService } from '../configuration/configuration.service';
@ -50,14 +50,14 @@ export class LockService {
catchError((error: any) => throwError(error))); catchError((error: any) => throwError(error)));
} }
//ToDo change Parameters checkLockStatus(targetId: Guid): Observable<Boolean> {
checkLockStatus(id: string): Observable<boolean> { return this.http.get<Boolean>(`${this.apiBase}/target/status/${targetId}`)
return this.http.get(`${this.apiBase}/target/status/${id}`, { headers: this.headers }); .pipe(catchError((error: any) => throwError(error)));
} }
//ToDo change Parameters unlockTarget(targetId: Guid): Observable<any> {
unlockTarget(id: string): Observable<any> { return this.http.delete(`${this.apiBase}/target/unlock/${targetId}`)
return this.http.delete(`${this.apiBase}/target/unlock/${id}`, { headers: this.headers }); .pipe(catchError((error: any) => throwError(error)));
} }
getSingleWithTarget(targetId: Guid, reqFields: string[] = []): Observable<Lock> { getSingleWithTarget(targetId: Guid, reqFields: string[] = []): Observable<Lock> {

View File

@ -58,7 +58,7 @@ export class EnumUtils {
case AppRole.Admin: return this.language.instant('TYPES.APP-ROLE.ADMIN'); case AppRole.Admin: return this.language.instant('TYPES.APP-ROLE.ADMIN');
case AppRole.User: return this.language.instant('TYPES.APP-ROLE.USER'); case AppRole.User: return this.language.instant('TYPES.APP-ROLE.USER');
case AppRole.Manager: return this.language.instant('TYPES.APP-ROLE.MANAGER'); case AppRole.Manager: return this.language.instant('TYPES.APP-ROLE.MANAGER');
case AppRole.DatasetTemplateEditor: return this.language.instant('TYPES.APP-ROLE.DESCRIPTION-TEMPLATE-EDITOR'); case AppRole.DescriptionTemplateEditor: return this.language.instant('TYPES.APP-ROLE.DESCRIPTION-TEMPLATE-EDITOR');
} }
} }

View File

@ -14,7 +14,7 @@ const routes: Routes = [
data: { data: {
title: 'GENERAL.TITLES.DATASET-PROFILES-NEW', title: 'GENERAL.TITLES.DATASET-PROFILES-NEW',
authContext: { authContext: {
permissions: [AppRole.Admin, AppRole.DatasetTemplateEditor] permissions: [AppRole.Admin, AppRole.DescriptionTemplateEditor]
} }
}, },
canActivate: [SpecialAuthGuard], canActivate: [SpecialAuthGuard],
@ -26,7 +26,7 @@ const routes: Routes = [
data: { data: {
title: 'GENERAL.TITLES.DATASET-PROFILES-EDIT', title: 'GENERAL.TITLES.DATASET-PROFILES-EDIT',
authContext: { authContext: {
permissions: [AppRole.Admin, AppRole.DatasetTemplateEditor] permissions: [AppRole.Admin, AppRole.DescriptionTemplateEditor]
} }
}, },
canActivate: [SpecialAuthGuard], canActivate: [SpecialAuthGuard],
@ -38,7 +38,7 @@ const routes: Routes = [
data: { data: {
title: 'GENERAL.TITLES.DATASET-PROFILES-CLONE', title: 'GENERAL.TITLES.DATASET-PROFILES-CLONE',
authContext: { authContext: {
permissions: [AppRole.Admin, AppRole.DatasetTemplateEditor] permissions: [AppRole.Admin, AppRole.DescriptionTemplateEditor]
} }
}, },
canActivate: [SpecialAuthGuard], canActivate: [SpecialAuthGuard],
@ -50,7 +50,7 @@ const routes: Routes = [
data: { data: {
title: 'GENERAL.TITLES.DATASET-PROFILES-NEW-VERSION', title: 'GENERAL.TITLES.DATASET-PROFILES-NEW-VERSION',
authContext: { authContext: {
permissions: [AppRole.Admin, AppRole.DatasetTemplateEditor] permissions: [AppRole.Admin, AppRole.DescriptionTemplateEditor]
} }
}, },
canActivate: [SpecialAuthGuard], canActivate: [SpecialAuthGuard],
@ -61,7 +61,7 @@ const routes: Routes = [
component: DatasetProfileListingComponent, component: DatasetProfileListingComponent,
data: { data: {
authContext: { authContext: {
permissions: [AppRole.Admin, AppRole.DatasetTemplateEditor] permissions: [AppRole.Admin, AppRole.DescriptionTemplateEditor]
} }
}, },
canActivate: [SpecialAuthGuard] canActivate: [SpecialAuthGuard]
@ -71,7 +71,7 @@ const routes: Routes = [
component: DatasetProfileListingComponent, component: DatasetProfileListingComponent,
data: { data: {
authContext: { authContext: {
permissions: [AppRole.Admin, AppRole.DatasetTemplateEditor] permissions: [AppRole.Admin, AppRole.DescriptionTemplateEditor]
} }
}, },
canActivate: [SpecialAuthGuard] canActivate: [SpecialAuthGuard]

View File

@ -2,7 +2,7 @@
<div *ngIf="!this.nowEditing"class="roles col"> <div *ngIf="!this.nowEditing"class="roles col">
<ng-container *ngFor="let role of this.formGroup.get('roles').value"> <ng-container *ngFor="let role of this.formGroup.get('roles').value">
<div> <div>
<span class="user-role" [ngClass]="{'user': role == appRole.User, 'manager': role == appRole.Manager, 'admin': role == appRole.Admin, 'dataset-template-editor': role == appRole.DatasetTemplateEditor}"> <span class="user-role" [ngClass]="{'user': role == appRole.User, 'manager': role == appRole.Manager, 'admin': role == appRole.Admin, 'description-template-editor': role == appRole.DescriptionTemplateEditor}">
{{enumUtils.toAppRoleString(role)}} {{enumUtils.toAppRoleString(role)}}
</span> </span>
</div> </div>

View File

@ -85,7 +85,7 @@
padding-right: 10px; padding-right: 10px;
} }
.dataset-template-editor { .description-template-editor {
// display: flex; // display: flex;
// justify-content: center; // justify-content: center;
// align-items: center; // align-items: center;

View File

@ -197,7 +197,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
this.datasetWizardService.getSingle(this.itemId) this.datasetWizardService.getSingle(this.itemId)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(data => { .subscribe(data => {
this.lockService.checkLockStatus(data.id).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => { this.lockService.checkLockStatus(Guid.parse(data.id)).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => {
this.lockStatus = lockStatus; this.lockStatus = lockStatus;
this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data); this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data);
this.dmpSectionIndex = this.datasetWizardModel.dmpSectionIndex; this.dmpSectionIndex = this.datasetWizardModel.dmpSectionIndex;
@ -343,7 +343,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
this.datasetWizardService.getSingle(this.itemId) this.datasetWizardService.getSingle(this.itemId)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(data => { .subscribe(data => {
this.lockService.checkLockStatus(data.id).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => { this.lockService.checkLockStatus(Guid.parse(data.id)).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => {
this.lockStatus = lockStatus; this.lockStatus = lockStatus;
this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data); this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data);
this.dmpSectionIndex = this.datasetWizardModel.dmpSectionIndex; this.dmpSectionIndex = this.datasetWizardModel.dmpSectionIndex;
@ -610,7 +610,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
public cancel(): void { public cancel(): void {
if (!isNullOrUndefined(this.lock)) { if (!isNullOrUndefined(this.lock)) {
this.lockService.unlockTarget(this.datasetWizardModel.id).pipe(takeUntil(this._destroyed)).subscribe( this.lockService.unlockTarget(Guid.parse(this.datasetWizardModel.id)).pipe(takeUntil(this._destroyed)).subscribe(
complete => { complete => {
this.publicMode ? this.router.navigate(['/explore-descriptions']) : this.router.navigate(['/datasets']); this.publicMode ? this.router.navigate(['/explore-descriptions']) : this.router.navigate(['/datasets']);
}, },

View File

@ -21,6 +21,7 @@ import { takeUntil } from 'rxjs/operators';
import { DatasetStatus } from '../../../../core/common/enum/dataset-status'; import { DatasetStatus } from '../../../../core/common/enum/dataset-status';
import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing';
import { DatasetCopyDialogueComponent } from '../../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component'; import { DatasetCopyDialogueComponent } from '../../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component';
import { Guid } from '@common/types/guid';
@Component({ @Component({
selector: 'app-dataset-listing-item-component', selector: 'app-dataset-listing-item-component',
@ -168,7 +169,7 @@ export class DatasetListingItemComponent extends BaseComponent implements OnInit
} }
deleteClicked(id: string) { deleteClicked(id: string) {
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed)) this.lockService.checkLockStatus(Guid.parse(id)).pipe(takeUntil(this._destroyed))
.subscribe(lockStatus => { .subscribe(lockStatus => {
if (!lockStatus) { if (!lockStatus) {
this.openDeleteDialog(id); this.openDeleteDialog(id);

View File

@ -32,6 +32,7 @@ import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver'; import * as FileSaver from 'file-saver';
import { filter, takeUntil } from 'rxjs/operators'; import { filter, takeUntil } from 'rxjs/operators';
import { DatasetCopyDialogueComponent } from '../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component'; import { DatasetCopyDialogueComponent } from '../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component';
import { Guid } from '@common/types/guid';
@Component({ @Component({
@ -137,7 +138,7 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
} }
checkLockStatus(id: string) { checkLockStatus(id: string) {
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed)) this.lockService.checkLockStatus(Guid.parse(id)).pipe(takeUntil(this._destroyed))
.subscribe(lockStatus => { .subscribe(lockStatus => {
this.lockStatus = lockStatus this.lockStatus = lockStatus
if (lockStatus) { if (lockStatus) {

View File

@ -181,7 +181,7 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
} }
deleteClicked(id: Guid) { deleteClicked(id: Guid) {
this.lockService.checkLockStatus(id.toString()).pipe(takeUntil(this._destroyed)) this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
.subscribe(lockStatus => { .subscribe(lockStatus => {
if (!lockStatus) { if (!lockStatus) {
this.openDeleteDialog(id); this.openDeleteDialog(id);

View File

@ -16,7 +16,7 @@ import { DmpDatasetProfile } from '@app/core/model/dmp/dmp-dataset-profile/dmp-d
import { DmpDatasetProfileSectionsFormModel } from '@app/core/model/dmp/dmp-dataset-profile/dmp-dataset-profile-sections-form.model'; import { DmpDatasetProfileSectionsFormModel } from '@app/core/model/dmp/dmp-dataset-profile/dmp-dataset-profile-sections-form.model';
import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item';
import { LanguageInfo } from '@app/core/model/language-info'; import { LanguageInfo } from '@app/core/model/language-info';
import { LockModel } from '@app/core/model/lock/lock.model'; import { Lock, LockPersist } from '@app/core/model/lock/lock.model';
import { UserModel } from '@app/core/model/user/user'; import { UserModel } from '@app/core/model/user/user';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing'; import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria';
@ -58,6 +58,7 @@ import { ProjectFormModel } from '../editor/grant-tab/project-form-model';
import { ReferenceSearchDefinitionLookup, ReferenceSearchLookup } from '@app/core/query/reference-search.lookup'; import { ReferenceSearchDefinitionLookup, ReferenceSearchLookup } from '@app/core/query/reference-search.lookup';
import { Reference } from '@app/core/model/reference/reference'; import { Reference } from '@app/core/model/reference/reference';
import { ReferenceTypeEditorResolver } from '@app/ui/admin/reference-type/editor/reference-type-editor.resolver'; import { ReferenceTypeEditorResolver } from '@app/ui/admin/reference-type/editor/reference-type-editor.resolver';
import { LockTargetType } from '@app/core/common/enum/lock-target-type';
interface Visible { interface Visible {
value: boolean; value: boolean;
@ -99,7 +100,8 @@ export class DmpEditorBlueprintComponent extends CheckDeactivateBaseComponent im
associatedUsers: Array<UserModel>; associatedUsers: Array<UserModel>;
people: Array<UserInfoListingModel>; people: Array<UserInfoListingModel>;
lock: LockModel; lock: Lock;
lockPersist: LockPersist;
lockStatus: Boolean = false; lockStatus: Boolean = false;
step: number = 0; step: number = 0;
@ -181,7 +183,7 @@ export class DmpEditorBlueprintComponent extends CheckDeactivateBaseComponent im
this.dmpService.getSingle(itemId).pipe(map(data => data as DmpModel)) this.dmpService.getSingle(itemId).pipe(map(data => data as DmpModel))
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(async data => { .subscribe(async data => {
this.lockService.checkLockStatus(data.id).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => { this.lockService.checkLockStatus(Guid.parse(data.id)).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => {
this.lockStatus = lockStatus; this.lockStatus = lockStatus;
this.dmp = new DmpEditorModel(); this.dmp = new DmpEditorModel();
@ -228,10 +230,14 @@ export class DmpEditorBlueprintComponent extends CheckDeactivateBaseComponent im
if (this.authService.currentAccountIsAuthenticated()) { if (this.authService.currentAccountIsAuthenticated()) {
if (!lockStatus) { if (!lockStatus) {
this.lock = new LockModel(data.id, this.getUserFromDMP()); const persist : LockPersist = null;
persist.target = Guid.parse(data.id);
persist.targetType = LockTargetType.Dmp;
persist.lockedBy = this.getUserFromDMP();
// this.lock = new LockModel(data.id, this.getUserFromDMP());
this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => { this.lockService.persist(persist).pipe(takeUntil(this._destroyed)).subscribe(async result => {
this.lock.id = Guid.parse(result); this.lock = result;
interval(this.configurationService.lockInterval).pipe(takeUntil(this._destroyed)).subscribe(() => this.pumpLock()); interval(this.configurationService.lockInterval).pipe(takeUntil(this._destroyed)).subscribe(() => this.pumpLock());
}); });
} }
@ -351,7 +357,7 @@ export class DmpEditorBlueprintComponent extends CheckDeactivateBaseComponent im
private pumpLock() { private pumpLock() {
this.lock.touchedAt = new Date(); this.lock.touchedAt = new Date();
this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => this.lock.id = Guid.parse(result)); //his.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => this.lock.id = Guid.parse(result));
} }
public isDirty(): boolean { public isDirty(): boolean {

Some files were not shown because too many files have changed in this diff Show More