diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationTemplateController.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationTemplateController.java new file mode 100644 index 000000000..6acb78c0f --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationTemplateController.java @@ -0,0 +1,123 @@ +package gr.cite.notification.web.controllers; + +import gr.cite.notification.audit.AuditableAction; +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.data.NotificationTemplateEntity; +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.notification.model.builder.NotificationTemplateBuilder; +import gr.cite.notification.model.censorship.NotificationTemplateCensor; +import gr.cite.notification.model.persist.NotificationTemplatePersist; +import gr.cite.notification.query.NotificationTemplateQuery; +import gr.cite.notification.query.lookup.NotificationTemplateLookup; +import gr.cite.notification.service.notificationtemplate.NotificationTemplateService; +import gr.cite.notification.web.model.QueryResult; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import gr.cite.tools.validation.MyValidate; +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.web.bind.annotation.*; + +import javax.management.InvalidApplicationException; +import javax.transaction.Transactional; +import java.util.*; + +@RestController +@RequestMapping(path = "api/notification-template") +public class NotificationTemplateController { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationTemplateController.class)); + + private final BuilderFactory builderFactory; + private final AuditService auditService; + private final NotificationTemplateService notificationTemplateService; + private final CensorFactory censorFactory; + private final QueryFactory queryFactory; + private final MessageSource messageSource; + + @Autowired + public NotificationTemplateController(BuilderFactory builderFactory, + AuditService auditService, + NotificationTemplateService notificationTemplateService, + CensorFactory censorFactory, + QueryFactory queryFactory, + MessageSource messageSource) { + this.builderFactory = builderFactory; + this.auditService = auditService; + this.notificationTemplateService = notificationTemplateService; + this.censorFactory = censorFactory; + this.queryFactory = queryFactory; + this.messageSource = messageSource; + } + + @PostMapping("query") + public QueryResult query(@RequestBody NotificationTemplateLookup lookup) throws MyApplicationException, MyForbiddenException { + logger.debug("querying {}", NotificationTemplate.class.getSimpleName()); + + this.censorFactory.censor(NotificationTemplateCensor.class).censor(lookup.getProject()); + + NotificationTemplateQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermission); + List data = query.collectAs(lookup.getProject()); + List models = this.builderFactory.builder(NotificationTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(lookup.getProject(), data); + long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); + + this.auditService.track(AuditableAction.Notification_Template_Query, "lookup", lookup); + + return new QueryResult<>(models, count); + } + + @GetMapping("{id}") + @Transactional + public NotificationTemplate get(@PathVariable UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("retrieving" + NotificationTemplate.class.getSimpleName()).And("id", id).And("fields", fieldSet)); + + this.censorFactory.censor(NotificationTemplateCensor.class).censor(fieldSet); + + NotificationTemplateQuery query = this.queryFactory.query(NotificationTemplateQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).ids(id); + NotificationTemplate model = this.builderFactory.builder(NotificationTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet)); + if (model == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, NotificationTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.Notification_Template_Lookup, Map.ofEntries( + new AbstractMap.SimpleEntry("id", id), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return model; + } + + @PostMapping("persist") + @Transactional + public NotificationTemplate persist(@MyValidate @RequestBody NotificationTemplatePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + logger.debug(new MapLogEntry("persisting" + NotificationTemplate.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); + + NotificationTemplate persisted = this.notificationTemplateService.persist(model, fieldSet); + + this.auditService.track(AuditableAction.Notification_Template_Persist, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return persisted; + } + + @DeleteMapping("{id}") + @Transactional + public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug(new MapLogEntry("deleting" + NotificationTemplate.class.getSimpleName()).And("id", id)); + + this.notificationTemplateService.deleteAndSave(id); + + this.auditService.track(AuditableAction.Notification_Template_Delete, "id", id); + } + +} diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/config/notification.yml b/dmp-backend/notification-service/notification-web/src/main/resources/config/notification.yml index be4c65d36..d77667a18 100644 --- a/dmp-backend/notification-service/notification-web/src/main/resources/config/notification.yml +++ b/dmp-backend/notification-service/notification-web/src/main/resources/config/notification.yml @@ -76,7 +76,7 @@ notification: optional: [ ] body-path: classpath:notification_templates/dmpinvitationexistinguser/email/body.{language}.html body-field-options: - mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}", "{id}"] + mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}", "{installation-url}", "{id}"] optional: - key: "{recipient}" value: diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/config/permissions.yml b/dmp-backend/notification-service/notification-web/src/main/resources/config/permissions.yml index 2f8484c6b..b5408b3c7 100644 --- a/dmp-backend/notification-service/notification-web/src/main/resources/config/permissions.yml +++ b/dmp-backend/notification-service/notification-web/src/main/resources/config/permissions.yml @@ -140,4 +140,24 @@ permissions: - ic-sti-superuser clients: [ ] allowAnonymous: false + allowAuthenticated: false + + # ViewPage Permissions + BrowseNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + EditNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + DeleteNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false allowAuthenticated: false \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/target/classes/config/notification.yml b/dmp-backend/notification-service/notification-web/target/classes/config/notification.yml index 5fbc2b22a..d77667a18 100644 --- a/dmp-backend/notification-service/notification-web/target/classes/config/notification.yml +++ b/dmp-backend/notification-service/notification-web/target/classes/config/notification.yml @@ -76,7 +76,7 @@ notification: optional: [ ] body-path: classpath:notification_templates/dmpinvitationexistinguser/email/body.{language}.html body-field-options: - mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}" ] + mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}", "{installation-url}", "{id}"] optional: - key: "{recipient}" value: diff --git a/dmp-backend/notification-service/notification-web/target/classes/config/permissions.yml b/dmp-backend/notification-service/notification-web/target/classes/config/permissions.yml index 2f8484c6b..b5408b3c7 100644 --- a/dmp-backend/notification-service/notification-web/target/classes/config/permissions.yml +++ b/dmp-backend/notification-service/notification-web/target/classes/config/permissions.yml @@ -140,4 +140,24 @@ permissions: - ic-sti-superuser clients: [ ] allowAnonymous: false + allowAuthenticated: false + + # ViewPage Permissions + BrowseNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + EditNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + DeleteNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false allowAuthenticated: false \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/email/body.en.html b/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/email/body.en.html index 4259f6e59..75a586097 100644 --- a/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/email/body.en.html +++ b/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/email/body.en.html @@ -262,6 +262,23 @@

Dear {recipient},

{reasonName} just add you to collaborate to Data Management plan {dmpname} with role {dmprole}.

+

Click the button to redirect to {dmpname}.

+ + + + + + + +
+ + + + + + +
Join
+
diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/audit/AuditableAction.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/audit/AuditableAction.java index 2fb58d514..dee3f5110 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/audit/AuditableAction.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/audit/AuditableAction.java @@ -20,12 +20,19 @@ public class AuditableAction { public static final EventId InApp_Notification_Delete = new EventId(20003, "InApp_Notification_Delete"); public static final EventId InApp_Notification_Read = new EventId(20003, "InApp_Notification_Read"); public static final EventId InApp_Notification_Read_All = new EventId(20003, "InApp_Notification_Read_All"); + public static final EventId Tenant_Configuration_Query = new EventId(21000, "Tenant_Configuration_Query"); public static final EventId Tenant_Configuration_Lookup = new EventId(21001, "Tenant_Configuration_Lookup"); public static final EventId Tenant_Configuration_Persist = new EventId(21002, "Tenant_Configuration_Persist"); public static final EventId Tenant_Configuration_Delete = new EventId(21003, "Tenant_Configuration_Delete"); + public static final EventId User_Notification_Preference_Query = new EventId(22000, "User_Notification_Preference_Query"); public static final EventId User_Notification_Preference_Lookup = new EventId(22001, "User_Notification_Preference_Lookup"); public static final EventId User_Notification_Preference_Persist = new EventId(22002, "User_Notification_Preference_Persist"); public static final EventId User_Notification_Preference_Delete = new EventId(22003, "User_Notification_Preference_Delete"); + + public static final EventId Notification_Template_Query = new EventId(23000, "Notification_Template_Query"); + public static final EventId Notification_Template_Lookup = new EventId(23001, "Notification_Template_Lookup"); + public static final EventId Notification_Template_Persist = new EventId(23002, "Notification_Template_Persist"); + public static final EventId Notification_Template_Delete = new EventId(23003, "Notification_Template_Delete"); } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/authorization/Permission.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/authorization/Permission.java index 346165927..bd4f8494b 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/authorization/Permission.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/authorization/Permission.java @@ -25,10 +25,15 @@ public final class Permission { public static final String BrowseTenantConfiguration = "BrowseTenantConfiguration"; public static final String EditTenantConfiguration = "EditTenantConfiguration"; - //Notification + //Notification Preference public static final String BrowseUserNotificationPreference = "BrowseUserNotificationPreference"; public static final String EditUserNotificationPreference = "EditUserNotificationPreference"; + //Notification Template + public static final String BrowseNotificationTemplate = "BrowseNotificationTemplate"; + public static String EditNotificationTemplate = "EditNotificationTemplate"; + public static String DeleteNotificationTemplate = "DeleteNotificationTemplate"; + // UI Pages public static String ViewTenantConfigurationPage = "ViewTenantConfigurationPage"; public static String ViewNotificationPage = "ViewNotificationPage"; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationTemplateChannel.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationTemplateChannel.java new file mode 100644 index 000000000..d484f9198 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationTemplateChannel.java @@ -0,0 +1,30 @@ +package gr.cite.notification.common.enums; + +import com.fasterxml.jackson.annotation.JsonValue; +import gr.cite.notification.data.conventers.DatabaseEnum; + +import java.util.Map; + +public enum NotificationTemplateChannel implements DatabaseEnum { + + Email((short)0), + InApp((short)1); + + private final Short value; + + NotificationTemplateChannel(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(NotificationTemplateChannel.class); + + public static NotificationTemplateChannel of(Short i) { + return map.get(i); + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationTemplateKind.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationTemplateKind.java new file mode 100644 index 000000000..8dbabd5fc --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationTemplateKind.java @@ -0,0 +1,30 @@ +package gr.cite.notification.common.enums; + +import com.fasterxml.jackson.annotation.JsonValue; +import gr.cite.notification.data.conventers.DatabaseEnum; + +import java.util.Map; + +public enum NotificationTemplateKind implements DatabaseEnum { + + Draft((short)0), + Primary((short)1); + + private final Short value; + + NotificationTemplateKind(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(NotificationTemplateKind.class); + + public static NotificationTemplateKind of(Short i) { + return map.get(i); + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notification/FieldInfo.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notification/FieldInfo.java index a16ebc570..44ad9a3c5 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notification/FieldInfo.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notification/FieldInfo.java @@ -2,8 +2,11 @@ package gr.cite.notification.common.types.notification; public class FieldInfo { private String key; + public final static String _key = "key"; private DataType type; + public final static String _type = "type"; private String value; + public final static String _value = "value"; public FieldInfo(String key, DataType type, String value) { this.key = key; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/FieldInfoEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/FieldInfoEntity.java new file mode 100644 index 000000000..2183ede58 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/FieldInfoEntity.java @@ -0,0 +1,42 @@ +package gr.cite.notification.common.types.notificationtemplate; + +import gr.cite.notification.common.types.notification.DataType; + +public class FieldInfoEntity { + private String key; + private DataType type; + private String value; + + public FieldInfoEntity(String key, DataType type, String value) { + this.key = key; + this.type = type; + this.value = value; + } + + public FieldInfoEntity() { + } + + 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; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/FieldOptionsEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/FieldOptionsEntity.java new file mode 100644 index 000000000..831b12535 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/FieldOptionsEntity.java @@ -0,0 +1,38 @@ +package gr.cite.notification.common.types.notificationtemplate; + + +import java.util.Dictionary; +import java.util.List; + +public class FieldOptionsEntity { + + private List mandatory; + + private List optional; + + private Dictionary formatting; + + public List getMandatory() { + return mandatory; + } + + public void setMandatory(List mandatory) { + this.mandatory = mandatory; + } + + public List getOptional() { + return optional; + } + + public void setOptional(List optional) { + this.optional = optional; + } + + public Dictionary getFormatting() { + return formatting; + } + + public void setFormatting(Dictionary formatting) { + this.formatting = formatting; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/NotificationTemplateValueEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/NotificationTemplateValueEntity.java new file mode 100644 index 000000000..6157594c2 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/notificationtemplate/NotificationTemplateValueEntity.java @@ -0,0 +1,126 @@ +package gr.cite.notification.common.types.notificationtemplate; + +import gr.cite.notification.common.types.notification.EmailOverrideMode; + +import java.util.List; + +public class NotificationTemplateValueEntity { + + private String subjectText; + private String subjectKey; + private FieldOptionsEntity subjectFieldOptions; + private String bodyText; + private String bodyKey; + private String priorityKey; + private Boolean allowAttachments; + private List cc; + private EmailOverrideMode ccMode; + private List bcc; + private EmailOverrideMode bccMode; + private List extraDataKeys; + private FieldOptionsEntity bodyFieldOptions; + + public String getSubjectText() { + return subjectText; + } + + public void setSubjectText(String subjectText) { + this.subjectText = subjectText; + } + + public String getSubjectKey() { + return subjectKey; + } + + public void setSubjectKey(String subjectKey) { + this.subjectKey = subjectKey; + } + + public FieldOptionsEntity getSubjectFieldOptions() { + return subjectFieldOptions; + } + + public void setSubjectFieldOptions(FieldOptionsEntity subjectFieldOptions) { + this.subjectFieldOptions = subjectFieldOptions; + } + + public String getBodyText() { + return bodyText; + } + + public void setBodyText(String bodyText) { + this.bodyText = bodyText; + } + + public String getBodyKey() { + return bodyKey; + } + + public void setBodyKey(String bodyKey) { + this.bodyKey = bodyKey; + } + + public String getPriorityKey() { + return priorityKey; + } + + public void setPriorityKey(String priorityKey) { + this.priorityKey = priorityKey; + } + + public Boolean getAllowAttachments() { + return allowAttachments; + } + + public void setAllowAttachments(Boolean allowAttachments) { + this.allowAttachments = allowAttachments; + } + + public List getCc() { + return cc; + } + + public void setCc(List cc) { + this.cc = cc; + } + + public EmailOverrideMode getCcMode() { + return ccMode; + } + + public void setCcMode(EmailOverrideMode ccMode) { + this.ccMode = ccMode; + } + + public List getBcc() { + return bcc; + } + + public void setBcc(List bcc) { + this.bcc = bcc; + } + + public EmailOverrideMode getBccMode() { + return bccMode; + } + + public void setBccMode(EmailOverrideMode bccMode) { + this.bccMode = bccMode; + } + + public List getExtraDataKeys() { + return extraDataKeys; + } + + public void setExtraDataKeys(List extraDataKeys) { + this.extraDataKeys = extraDataKeys; + } + + public FieldOptionsEntity getBodyFieldOptions() { + return bodyFieldOptions; + } + + public void setBodyFieldOptions(FieldOptionsEntity bodyFieldOptions) { + this.bodyFieldOptions = bodyFieldOptions; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/LanguageEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/LanguageEntity.java new file mode 100644 index 000000000..cbd2f4e8d --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/LanguageEntity.java @@ -0,0 +1,100 @@ +package gr.cite.notification.data; + +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.data.conventers.IsActiveConverter; +import gr.cite.notification.data.tenant.TenantScopedBaseEntity; + +import javax.persistence.*; +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "\"Language\"") +public class LanguageEntity extends TenantScopedBaseEntity { + + @Id + @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) + private UUID id; + public static final String _id = "id"; + + @Column(name = "code", length = 20, nullable = false) + private String code; + public static final String _code = "code"; + + @Column(name = "payload") + private String payload; + public static final String _payload = "payload"; + + @Column(name = "\"created_at\"", nullable = false) + private Instant createdAt; + public static final String _createdAt = "createdAt"; + + @Column(name = "\"updated_at\"", nullable = false) + private Instant updatedAt; + public static final String _updatedAt = "updatedAt"; + + @Column(name = "is_active", nullable = false) + @Convert(converter = IsActiveConverter.class) + private IsActive isActive; + public static final String _isActive = "isActive"; + + @Column(name = "ordinal") + private Integer ordinal; + public static final String _ordinal = "ordinal"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + 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 IsActive getIsActive() { + return isActive; + } + + public void setIsActive(IsActive isActive) { + this.isActive = isActive; + } + + public Integer getOrdinal() { + return ordinal; + } + + public void setOrdinal(Integer ordinal) { + this.ordinal = ordinal; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationTemplateEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationTemplateEntity.java new file mode 100644 index 000000000..be3d907c6 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationTemplateEntity.java @@ -0,0 +1,126 @@ +package gr.cite.notification.data; + +import gr.cite.notification.common.enums.*; +import gr.cite.notification.data.conventers.*; +import gr.cite.notification.data.tenant.TenantScopedBaseEntity; + +import javax.persistence.*; +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "\"ntf_NotificationTemplate\"") +public class NotificationTemplateEntity extends TenantScopedBaseEntity { + + @Id + @Column(name = "\"id\"", columnDefinition = "uuid", updatable = false, nullable = false) + private UUID id; + public final static String _id = "id"; + + @Column(name = "\"channel\"", nullable = false) + @Convert(converter = NotificationTemplateChannelConverter.class) + private NotificationTemplateChannel channel; + public final static String _channel = "channel"; + + @Column(name = "\"notification_type\"", columnDefinition = "uuid", nullable = false) + private UUID notificationType; + public final static String _notificationType = "notificationType"; + + @Column(name = "\"kind\"", nullable = false) + @Convert(converter = NotificationTemplateKindConverter.class) + private NotificationTemplateKind kind; + public final static String _kind = "kind"; + + @Column(name = "\"language\"", columnDefinition = "uuid", nullable = false) + private UUID languageId; + public final static String _language = "language"; + + @Column(name = "\"value\"", nullable = false) + private String value; + public final static String _value = "value"; + + @Column(name = "\"is_active\"", 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 NotificationTemplateChannel getChannel() { + return channel; + } + + public void setChannel(NotificationTemplateChannel channel) { + this.channel = channel; + } + + public UUID getNotificationType() { + return notificationType; + } + + public void setNotificationType(UUID notificationType) { + this.notificationType = notificationType; + } + + public NotificationTemplateKind getKind() { + return kind; + } + + public void setKind(NotificationTemplateKind kind) { + this.kind = kind; + } + + public UUID getLanguageId() { + return languageId; + } + + public void setLanguageId(UUID languageId) { + this.languageId = languageId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + 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; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTemplateChannelConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTemplateChannelConverter.java new file mode 100644 index 000000000..0b0c6fc4f --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTemplateChannelConverter.java @@ -0,0 +1,25 @@ +package gr.cite.notification.data.conventers; + + + +import gr.cite.notification.common.enums.NotificationTemplateChannel; + +import javax.persistence.Converter; + +@Converter +public class NotificationTemplateChannelConverter extends DatabaseEnumConverter { + public NotificationTemplateChannel of(Short i) { + return NotificationTemplateChannel.of(i); + } + + @Override + public Short convertToDatabaseColumn(NotificationTemplateChannel value) { + if (value == null) return null; + return value.getValue(); + } + + @Override + public NotificationTemplateChannel convertToEntityAttribute(Short dbData) { + return dbData == null ? null : this.of(dbData); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTemplateKindConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTemplateKindConverter.java new file mode 100644 index 000000000..a4f355b58 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTemplateKindConverter.java @@ -0,0 +1,24 @@ +package gr.cite.notification.data.conventers; + + +import gr.cite.notification.common.enums.NotificationTemplateKind; + +import javax.persistence.Converter; + +@Converter +public class NotificationTemplateKindConverter extends DatabaseEnumConverter { + public NotificationTemplateKind of(Short i) { + return NotificationTemplateKind.of(i); + } + + @Override + public Short convertToDatabaseColumn(NotificationTemplateKind value) { + if (value == null) return null; + return value.getValue(); + } + + @Override + public NotificationTemplateKind convertToEntityAttribute(Short dbData) { + return dbData == null ? null : this.of(dbData); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Language.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Language.java new file mode 100644 index 000000000..e83e23b6d --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Language.java @@ -0,0 +1,97 @@ +package gr.cite.notification.model; + +import gr.cite.notification.common.enums.IsActive; + +import java.time.Instant; +import java.util.UUID; + +public class Language { + + private UUID id; + public static final String _id = "id"; + + private String code; + public static final String _code = "code"; + + private String payload; + public static final String _payload = "payload"; + + private Instant createdAt; + public static final String _createdAt = "createdAt"; + + private Instant updatedAt; + public static final String _updatedAt = "updatedAt"; + + private IsActive isActive; + public static final String _isActive = "isActive"; + + private Integer ordinal; + public static final String _ordinal = "ordinal"; + + private String hash; + public final static String _hash = "hash"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + 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 IsActive getIsActive() { + return isActive; + } + + public void setIsActive(IsActive isActive) { + this.isActive = isActive; + } + + public Integer getOrdinal() { + return ordinal; + } + + public void setOrdinal(Integer ordinal) { + this.ordinal = ordinal; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/NotificationTemplate.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/NotificationTemplate.java new file mode 100644 index 000000000..fa6cc6221 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/NotificationTemplate.java @@ -0,0 +1,134 @@ +package gr.cite.notification.model; + +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.common.enums.NotificationTemplateChannel; +import gr.cite.notification.common.enums.NotificationTemplateKind; +import gr.cite.notification.model.notificationtemplate.NotificationTemplateValue; + + +import java.time.Instant; +import java.util.UUID; + +public class NotificationTemplate { + + private UUID id; + public final static String _id = "id"; + + private NotificationTemplateChannel channel; + public final static String _channel = "channel"; + + private UUID notificationType; + public final static String _notificationType = "notificationType"; + + private NotificationTemplateKind kind; + public final static String _kind = "kind"; + + private Language language; + public final static String _language = "language"; + + private NotificationTemplateValue value; + public final static String _value = "value"; + + private IsActive isActive; + public final static String _isActive = "isActive"; + + private Instant createdAt; + public final static String _createdAt = "createdAt"; + + private Instant updatedAt; + public final static String _updatedAt = "updatedAt"; + + private Tenant tenant; + public final static String _tenant = "tenant"; + + private String hash; + public final static String _hash = "hash"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public NotificationTemplateChannel getChannel() { + return channel; + } + + public void setChannel(NotificationTemplateChannel channel) { + this.channel = channel; + } + + public UUID getNotificationType() { + return notificationType; + } + + public void setNotificationType(UUID notificationType) { + this.notificationType = notificationType; + } + + public NotificationTemplateKind getKind() { + return kind; + } + + public void setKind(NotificationTemplateKind kind) { + this.kind = kind; + } + + public Language getLanguage() { + return language; + } + + public void setLanguage(Language language) { + this.language = language; + } + + public NotificationTemplateValue getValue() { + return value; + } + + public void setValue(NotificationTemplateValue value) { + this.value = value; + } + + 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 Tenant getTenant() { + return tenant; + } + + public void setTenant(Tenant tenant) { + this.tenant = tenant; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/LanguageBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/LanguageBuilder.java new file mode 100644 index 000000000..940877886 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/LanguageBuilder.java @@ -0,0 +1,59 @@ +package gr.cite.notification.model.builder; + + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.data.LanguageEntity; +import gr.cite.notification.model.Language; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class LanguageBuilder extends BaseBuilder{ + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public LanguageBuilder( + ConventionService conventionService) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(LanguageBuilder.class))); + } + + public LanguageBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + List models = new ArrayList<>(); + for (LanguageEntity d : data) { + Language m = new Language(); + if (fields.hasField(this.asIndexer(Language._id))) m.setId(d.getId()); + if (fields.hasField(this.asIndexer(Language._code))) m.setCode(d.getCode()); + if (fields.hasField(this.asIndexer(Language._payload))) m.setPayload(d.getPayload()); + if (fields.hasField(this.asIndexer(Language._ordinal))) m.setOrdinal(d.getOrdinal()); + if (fields.hasField(this.asIndexer(Language._createdAt))) m.setCreatedAt(d.getCreatedAt()); + if (fields.hasField(this.asIndexer(Language._updatedAt))) m.setUpdatedAt(d.getUpdatedAt()); + if (fields.hasField(this.asIndexer(Language._isActive))) m.setIsActive(d.getIsActive()); + if (fields.hasField(this.asIndexer(Language._hash))) m.setHash(this.hashValue(d.getUpdatedAt())); + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationTemplateBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationTemplateBuilder.java new file mode 100644 index 000000000..297c52aeb --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationTemplateBuilder.java @@ -0,0 +1,145 @@ +package gr.cite.notification.model.builder; + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.types.notificationtemplate.NotificationTemplateValueEntity; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.data.NotificationTemplateEntity; +import gr.cite.notification.model.Language; +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.notification.model.Tenant; +import gr.cite.notification.model.builder.notificationtemplate.NotificationTemplateValueBuilder; +import gr.cite.notification.model.notificationtemplate.NotificationTemplateValue; +import gr.cite.notification.query.LanguageQuery; +import gr.cite.notification.query.TenantQuery; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class NotificationTemplateBuilder extends BaseBuilder { + + private final BuilderFactory builderFactory; + private final QueryFactory queryFactory; + private final JsonHandlingService jsonHandlingService; + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + @Autowired + public NotificationTemplateBuilder(ConventionService conventionService, BuilderFactory builderFactory, QueryFactory queryFactory, JsonHandlingService jsonHandlingService) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(NotificationTemplateBuilder.class))); + this.builderFactory = builderFactory; + this.queryFactory = queryFactory; + this.jsonHandlingService = jsonHandlingService; + } + + public NotificationTemplateBuilder authorize(EnumSet values){ + this.authorize = values; + return this; + } + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0),Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size) .orElse(0)); + this.logger.trace(new DataLogEntry("requested fields",fields)); + if(fields == null || data == null || fields.isEmpty()) return new ArrayList<>(); + + FieldSet valueFields = fields.extractPrefixed(this.asPrefix(NotificationTemplate._value)); + + FieldSet tenantFields = fields.extractPrefixed(this.asPrefix(NotificationTemplate._tenant)); + Map tenantMap = this.collectTenants(tenantFields, data); + + FieldSet languageFields = fields.extractPrefixed(this.asPrefix(NotificationTemplate._language)); + Map languageMap = this.collectLanguages(tenantFields, data); + + List models = new ArrayList<>(); + for(NotificationTemplateEntity d : data){ + NotificationTemplate m = new NotificationTemplate(); + if(fields.hasField(this.asIndexer(NotificationTemplate._id))) m.setId(d.getId()); + if(fields.hasField(this.asIndexer(NotificationTemplate._channel))) m.setChannel(d.getChannel()); + if(fields.hasField(this.asIndexer(NotificationTemplate._notificationType))) m.setNotificationType(d.getNotificationType()); + if(fields.hasField(this.asIndexer(NotificationTemplate._kind))) m.setKind(d.getKind()); + if (!languageFields.isEmpty() && languageMap != null && languageMap.containsKey(d.getLanguageId())) m.setLanguage(languageMap.get(d.getLanguageId())); + if (!valueFields.isEmpty() && d.getValue() != null){ + NotificationTemplateValueEntity value = this.jsonHandlingService.fromJsonSafe(NotificationTemplateValueEntity.class, d.getValue()); + m.setValue(this.builderFactory.builder(NotificationTemplateValueBuilder.class).authorize(this.authorize).build(valueFields, value)); + } + if(fields.hasField(this.asIndexer(NotificationTemplate._isActive))) m.setIsActive(d.getIsActive()); + if(fields.hasField(this.asIndexer(Tenant._createdAt))) m.setCreatedAt(d.getCreatedAt()); + if(fields.hasField(this.asIndexer(Tenant._updatedAt))) m.setUpdatedAt(d.getUpdatedAt()); + if(fields.hasField(this.asIndexer(NotificationTemplate._hash))) m.setHash(this.hashValue(d.getUpdatedAt())); + if (!tenantFields.isEmpty() && tenantMap != null && tenantMap.containsKey(d.getTenantId())) m.setTenant(tenantMap.get(d.getTenantId())); + models.add(m); + } + this.logger.debug("build {} items",Optional.of(models).map(List::size).orElse(0)); + return models; + } + + private Map collectLanguages(FieldSet fields, List datas) throws MyApplicationException { + if (fields.isEmpty() || datas.isEmpty()) return null; + this.logger.debug("checking related - {}", NotificationTemplate.class.getSimpleName()); + + Map itemMap = null; + if (!fields.hasOtherField(this.asIndexer(Language._id))) { + itemMap = this.asEmpty( + datas.stream().map(x -> x.getLanguageId()).distinct().collect(Collectors.toList()), + x -> { + Language item = new Language(); + item.setId(x); + return item; + }, + x -> x.getId()); + } else { + FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(Language._id); + LanguageQuery q = this.queryFactory.query(LanguageQuery.class).authorize(this.authorize).ids(datas.stream().map(x -> x.getLanguageId()).distinct().collect(Collectors.toList())); + itemMap = this.builderFactory.builder(LanguageBuilder.class).authorize(this.authorize).asForeignKey(q, clone, x -> x.getId()); + } + if (!fields.hasField(Tenant._id)) { + itemMap.values().stream().filter(x -> x != null).map(x -> { + x.setId(null); + return x; + }).collect(Collectors.toList()); + } + + return itemMap; + } + + private Map collectTenants(FieldSet fields, List datas) throws MyApplicationException { + if (fields.isEmpty() || datas.isEmpty()) return null; + this.logger.debug("checking related - {}", NotificationTemplate.class.getSimpleName()); + + Map itemMap = null; + if (!fields.hasOtherField(this.asIndexer(Tenant._id))) { + itemMap = this.asEmpty( + datas.stream().map(x -> x.getTenantId()).distinct().collect(Collectors.toList()), + x -> { + Tenant item = new Tenant(); + item.setId(x); + return item; + }, + x -> x.getId()); + } else { + FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(Tenant._id); + TenantQuery q = this.queryFactory.query(TenantQuery.class).authorize(this.authorize).ids(datas.stream().map(x -> x.getTenantId()).distinct().collect(Collectors.toList())); + itemMap = this.builderFactory.builder(TenantBuilder.class).authorize(this.authorize).asForeignKey(q, clone, x -> x.getId()); + } + if (!fields.hasField(Tenant._id)) { + itemMap.values().stream().filter(x -> x != null).map(x -> { + x.setId(null); + return x; + }).collect(Collectors.toList()); + } + + return itemMap; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/FieldInfoBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/FieldInfoBuilder.java new file mode 100644 index 000000000..339ef670f --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/FieldInfoBuilder.java @@ -0,0 +1,57 @@ +package gr.cite.notification.model.builder.notificationtemplate; + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.types.notification.FieldInfo; +import gr.cite.notification.common.types.notificationtemplate.FieldInfoEntity; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.model.builder.BaseBuilder; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class FieldInfoBuilder extends BaseBuilder { + + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public FieldInfoBuilder( + ConventionService conventionService, BuilderFactory builderFactory) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(FieldInfoBuilder.class))); + } + + public FieldInfoBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + List models = new ArrayList<>(); + for (FieldInfoEntity d : data) { + FieldInfo m = new FieldInfo(); + if (fields.hasField(this.asIndexer(FieldInfo._key))) m.setKey(d.getKey()); + if (fields.hasField(this.asIndexer(FieldInfo._value))) m.setValue(d.getValue()); + if (fields.hasField(this.asIndexer(FieldInfo._type))) m.setType(d.getType()); + + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/FieldOptionsBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/FieldOptionsBuilder.java new file mode 100644 index 000000000..c213dc88b --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/FieldOptionsBuilder.java @@ -0,0 +1,64 @@ +package gr.cite.notification.model.builder.notificationtemplate; + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.types.notificationtemplate.FieldOptionsEntity; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.model.builder.BaseBuilder; +import gr.cite.notification.model.notificationtemplate.FieldOptions; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class FieldOptionsBuilder extends BaseBuilder { + + private final BuilderFactory builderFactory; + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public FieldOptionsBuilder( + ConventionService conventionService, BuilderFactory builderFactory) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(FieldOptionsBuilder.class))); + this.builderFactory = builderFactory; + } + + public FieldOptionsBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + FieldSet optionalFields = fields.extractPrefixed(this.asPrefix(FieldOptions._optional)); + + List models = new ArrayList<>(); + for (FieldOptionsEntity d : data) { + FieldOptions m = new FieldOptions(); + if (fields.hasField(this.asIndexer(FieldOptions._mandatory))) m.setMandatory(d.getMandatory()); + if (!optionalFields.isEmpty() && d.getOptional() != null) { + m.setOptional(this.builderFactory.builder(FieldInfoBuilder.class).authorize(this.authorize).build(optionalFields, d.getOptional())); + } + if (fields.hasField(this.asIndexer(FieldOptions._formatting))) m.setFormatting(d.getFormatting()); + + + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/NotificationTemplateValueBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/NotificationTemplateValueBuilder.java new file mode 100644 index 000000000..d5022d8dd --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/notificationtemplate/NotificationTemplateValueBuilder.java @@ -0,0 +1,78 @@ +package gr.cite.notification.model.builder.notificationtemplate; + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.types.notificationtemplate.NotificationTemplateValueEntity; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.model.builder.BaseBuilder; +import gr.cite.notification.model.notificationtemplate.FieldOptions; +import gr.cite.notification.model.notificationtemplate.NotificationTemplateValue; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class NotificationTemplateValueBuilder extends BaseBuilder { + + private final BuilderFactory builderFactory; + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public NotificationTemplateValueBuilder( + ConventionService conventionService, BuilderFactory builderFactory) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(NotificationTemplateValueBuilder.class))); + this.builderFactory = builderFactory; + } + + public NotificationTemplateValueBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + FieldSet subjectFieldOptionsFields = fields.extractPrefixed(this.asPrefix(NotificationTemplateValue._subjectFieldOptions)); + FieldSet bodyFieldOptionsFields = fields.extractPrefixed(this.asPrefix(NotificationTemplateValue._bodyFieldOptions)); + + + List models = new ArrayList<>(); + for (NotificationTemplateValueEntity d : data) { + NotificationTemplateValue m = new NotificationTemplateValue(); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._subjectText))) m.setSubjectText(d.getSubjectText()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._subjectKey))) m.setSubjectKey(d.getSubjectKey()); + if (!subjectFieldOptionsFields.isEmpty() && d.getSubjectFieldOptions() != null) { + m.setSubjectFieldOptions(this.builderFactory.builder(FieldOptionsBuilder.class).authorize(this.authorize).build(subjectFieldOptionsFields, d.getSubjectFieldOptions())); + } + if (fields.hasField(this.asIndexer(NotificationTemplateValue._bodyText))) m.setBodyText(d.getBodyText()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._bodyKey))) m.setBodyKey(d.getBodyKey()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._priorityKey))) m.setPriorityKey(d.getPriorityKey()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._allowAttachments))) m.setAllowAttachments(d.getAllowAttachments()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._cc))) m.setCc(d.getCc()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._ccMode))) m.setCcMode(d.getCcMode()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._bcc))) m.setBcc(d.getBcc()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._bccMode))) m.setBccMode(d.getBccMode()); + if (fields.hasField(this.asIndexer(NotificationTemplateValue._extraDataKeys))) m.setExtraDataKeys(d.getExtraDataKeys()); + if (!bodyFieldOptionsFields.isEmpty() && d.getBodyFieldOptions() != null) { + m.setBodyFieldOptions(this.builderFactory.builder(FieldOptionsBuilder.class).authorize(this.authorize).build(bodyFieldOptionsFields, d.getBodyFieldOptions())); + } + + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/NotificationTemplateCensor.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/NotificationTemplateCensor.java new file mode 100644 index 000000000..b90fe4dd5 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/NotificationTemplateCensor.java @@ -0,0 +1,32 @@ +package gr.cite.notification.model.censorship; + +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.Permission; +import gr.cite.notification.convention.ConventionService; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +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 NotificationTemplateCensor extends BaseCensor { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationTemplateCensor.class)); + private final AuthorizationService authService; + + @Autowired + public NotificationTemplateCensor(ConventionService conventionService, AuthorizationService authService) { + super(conventionService); + this.authService = authService; + } + + public void censor(FieldSet fields) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (this.isEmpty(fields)) return; + this.authService.authorizeForce(Permission.BrowseNotificationTemplate); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/FieldInfoCensor.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/FieldInfoCensor.java new file mode 100644 index 000000000..7f8c93fb7 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/FieldInfoCensor.java @@ -0,0 +1,33 @@ +package gr.cite.notification.model.censorship.notificationtemplate; + +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.Permission; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.model.censorship.BaseCensor; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +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 FieldInfoCensor extends BaseCensor { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FieldInfoCensor.class)); + private final AuthorizationService authService; + + @Autowired + public FieldInfoCensor(ConventionService conventionService, AuthorizationService authService) { + super(conventionService); + this.authService = authService; + } + + public void censor(FieldSet fields) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (this.isEmpty(fields)) return; + this.authService.authorizeForce(Permission.BrowseNotificationTemplate); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/FieldOptionsCensor.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/FieldOptionsCensor.java new file mode 100644 index 000000000..44894dec9 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/FieldOptionsCensor.java @@ -0,0 +1,39 @@ +package gr.cite.notification.model.censorship.notificationtemplate; + +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.Permission; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.model.censorship.BaseCensor; +import gr.cite.notification.model.notificationtemplate.FieldOptions; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +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 FieldOptionsCensor extends BaseCensor { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FieldOptionsCensor.class)); + protected final AuthorizationService authService; + protected final CensorFactory censorFactory; + + @Autowired + public FieldOptionsCensor(ConventionService conventionService, AuthorizationService authService, CensorFactory censorFactory) { + super(conventionService); + this.authService = authService; + this.censorFactory = censorFactory; + } + + public void censor(FieldSet fields) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (this.isEmpty(fields)) return; + this.authService.authorizeForce(Permission.BrowseNotificationTemplate); + FieldSet optionalFields = fields.extractPrefixed(this.asIndexerPrefix(FieldOptions._optional)); + this.censorFactory.censor(FieldInfoCensor.class).censor(optionalFields); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/NotificationTemplateValueCensor.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/NotificationTemplateValueCensor.java new file mode 100644 index 000000000..38f6c104c --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/censorship/notificationtemplate/NotificationTemplateValueCensor.java @@ -0,0 +1,43 @@ +package gr.cite.notification.model.censorship.notificationtemplate; + +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.Permission; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.notification.model.censorship.BaseCensor; +import gr.cite.notification.model.notificationtemplate.FieldOptions; +import gr.cite.notification.model.notificationtemplate.NotificationTemplateValue; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +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 NotificationTemplateValueCensor extends BaseCensor { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationTemplateValueCensor.class)); + protected final AuthorizationService authService; + protected final CensorFactory censorFactory; + + @Autowired + public NotificationTemplateValueCensor(ConventionService conventionService, AuthorizationService authService, CensorFactory censorFactory) { + super(conventionService); + this.authService = authService; + this.censorFactory = censorFactory; + } + + public void censor(FieldSet fields) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (this.isEmpty(fields)) return; + this.authService.authorizeForce(Permission.BrowseNotificationTemplate); + FieldSet subjectFieldOptionsFields = fields.extractPrefixed(this.asIndexerPrefix(NotificationTemplateValue._subjectFieldOptions)); + this.censorFactory.censor(FieldOptionsCensor.class).censor(subjectFieldOptionsFields); + FieldSet bodyFieldOptionsFields = fields.extractPrefixed(this.asIndexerPrefix(NotificationTemplateValue._bodyFieldOptions)); + this.censorFactory.censor(FieldOptionsCensor.class).censor(bodyFieldOptionsFields); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/deleter/NotificationTemplateDeleter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/deleter/NotificationTemplateDeleter.java new file mode 100644 index 000000000..7ff4c3ead --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/deleter/NotificationTemplateDeleter.java @@ -0,0 +1,78 @@ +package gr.cite.notification.model.deleter; + +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.data.NotificationTemplateEntity; +import gr.cite.notification.data.TenantScopedEntityManager; +import gr.cite.notification.query.NotificationTemplateQuery; +import gr.cite.tools.data.deleter.Deleter; +import gr.cite.tools.data.deleter.DeleterFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class NotificationTemplateDeleter implements Deleter { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationTemplateDeleter.class)); + + private final TenantScopedEntityManager entityManager; + protected final QueryFactory queryFactory; + private final DeleterFactory deleterFactory; + + @Autowired + public NotificationTemplateDeleter( + TenantScopedEntityManager entityManager, + QueryFactory queryFactory, + DeleterFactory deleterFactory + ) { + this.entityManager = entityManager; + this.queryFactory = queryFactory; + this.deleterFactory = deleterFactory; + } + + public void deleteAndSaveByIds(List ids) throws InvalidApplicationException { + logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids)); + List data = this.queryFactory.query(NotificationTemplateQuery.class).ids(ids).collect(); + logger.trace("received {} items", Optional.of(data).map(List::size).orElse(0)); + this.deleteAndSave(data); + } + + public void deleteAndSave(List data) throws InvalidApplicationException { + logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + this.delete(data); + logger.trace("saving changes"); + this.entityManager.flush(); + logger.trace("changes saved"); + } + + public void delete(List datas) throws InvalidApplicationException { + logger.debug("will delete {} items", Optional.ofNullable(datas).map(List::size).orElse(0)); + if (datas == null || datas.isEmpty()) return; + + List ids = datas.stream().map(NotificationTemplateEntity::getId).distinct().collect(Collectors.toList()); + + Instant now = Instant.now(); + + for (NotificationTemplateEntity item : datas) { + logger.trace("deleting item {}", item.getId()); + item.setIsActive(IsActive.Inactive); + item.setUpdatedAt(now); + logger.trace("updating item"); + this.entityManager.merge(item); + logger.trace("updated item"); + } + + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/notificationtemplate/FieldOptions.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/notificationtemplate/FieldOptions.java new file mode 100644 index 000000000..878f93025 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/notificationtemplate/FieldOptions.java @@ -0,0 +1,42 @@ +package gr.cite.notification.model.notificationtemplate; + +import gr.cite.notification.common.types.notification.FieldInfo; + +import java.util.Dictionary; +import java.util.List; + +public class FieldOptions { + + private List mandatory; + public final static String _mandatory = "mandatory"; + + private List optional; + public final static String _optional = "optional"; + + private Dictionary formatting; + public final static String _formatting = "formatting"; + + public List getMandatory() { + return mandatory; + } + + public void setMandatory(List mandatory) { + this.mandatory = mandatory; + } + + public List getOptional() { + return optional; + } + + public void setOptional(List optional) { + this.optional = optional; + } + + public Dictionary getFormatting() { + return formatting; + } + + public void setFormatting(Dictionary formatting) { + this.formatting = formatting; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/notificationtemplate/NotificationTemplateValue.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/notificationtemplate/NotificationTemplateValue.java new file mode 100644 index 000000000..05725f260 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/notificationtemplate/NotificationTemplateValue.java @@ -0,0 +1,139 @@ +package gr.cite.notification.model.notificationtemplate; + +import gr.cite.notification.common.types.notification.EmailOverrideMode; + +import java.util.List; + +public class NotificationTemplateValue { + + private String subjectText; + public final static String _subjectText = "subjectText"; + private String subjectKey; + public final static String _subjectKey = "subjectKey"; + private FieldOptions subjectFieldOptions; + public final static String _subjectFieldOptions = "subjectFieldOptions"; + private String bodyText; + public final static String _bodyText = "bodyText"; + private String bodyKey; + public final static String _bodyKey = "bodyKey"; + private String priorityKey; + public final static String _priorityKey = "priorityKey"; + private Boolean allowAttachments; + public final static String _allowAttachments = "allowAttachments"; + private List cc; + public final static String _cc = "cc"; + private EmailOverrideMode ccMode; + public final static String _ccMode = "ccMode"; + private List bcc; + public final static String _bcc = "bcc"; + private EmailOverrideMode bccMode; + public final static String _bccMode = "bccMode"; + private List extraDataKeys; + public final static String _extraDataKeys = "extraDataKeys"; + private FieldOptions bodyFieldOptions; + public final static String _bodyFieldOptions = "bodyFieldOptions"; + + public String getSubjectText() { + return subjectText; + } + + public void setSubjectText(String subjectText) { + this.subjectText = subjectText; + } + + public String getSubjectKey() { + return subjectKey; + } + + public void setSubjectKey(String subjectKey) { + this.subjectKey = subjectKey; + } + + public FieldOptions getSubjectFieldOptions() { + return subjectFieldOptions; + } + + public void setSubjectFieldOptions(FieldOptions subjectFieldOptions) { + this.subjectFieldOptions = subjectFieldOptions; + } + + public String getBodyText() { + return bodyText; + } + + public void setBodyText(String bodyText) { + this.bodyText = bodyText; + } + + public String getBodyKey() { + return bodyKey; + } + + public void setBodyKey(String bodyKey) { + this.bodyKey = bodyKey; + } + + public String getPriorityKey() { + return priorityKey; + } + + public void setPriorityKey(String priorityKey) { + this.priorityKey = priorityKey; + } + + public Boolean getAllowAttachments() { + return allowAttachments; + } + + public void setAllowAttachments(Boolean allowAttachments) { + this.allowAttachments = allowAttachments; + } + + public List getCc() { + return cc; + } + + public void setCc(List cc) { + this.cc = cc; + } + + public EmailOverrideMode getCcMode() { + return ccMode; + } + + public void setCcMode(EmailOverrideMode ccMode) { + this.ccMode = ccMode; + } + + public List getBcc() { + return bcc; + } + + public void setBcc(List bcc) { + this.bcc = bcc; + } + + public EmailOverrideMode getBccMode() { + return bccMode; + } + + public void setBccMode(EmailOverrideMode bccMode) { + this.bccMode = bccMode; + } + + public List getExtraDataKeys() { + return extraDataKeys; + } + + public void setExtraDataKeys(List extraDataKeys) { + this.extraDataKeys = extraDataKeys; + } + + public FieldOptions getBodyFieldOptions() { + return bodyFieldOptions; + } + + public void setBodyFieldOptions(FieldOptions bodyFieldOptions) { + this.bodyFieldOptions = bodyFieldOptions; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/NotificationTemplatePersist.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/NotificationTemplatePersist.java new file mode 100644 index 000000000..71927dbad --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/NotificationTemplatePersist.java @@ -0,0 +1,93 @@ +package gr.cite.notification.model.persist; + +import gr.cite.notification.common.enums.NotificationTemplateChannel; +import gr.cite.notification.common.enums.NotificationTemplateKind; +import gr.cite.notification.common.validation.ValidEnum; +import gr.cite.notification.common.validation.ValidId; +import gr.cite.notification.model.persist.notificationtemplate.NotificationTemplateValuePersist; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.UUID; + +public class NotificationTemplatePersist { + + @ValidId(message = "{validation.invalidid}") + private UUID id; + + @ValidEnum + private NotificationTemplateChannel channel; + + @NotNull(message = "{validation.empty}") + @Valid + private UUID notificationType; + + @ValidEnum + private NotificationTemplateKind kind; + + @NotNull(message = "{validation.empty}") + @ValidId(message = "{validation.invalidid}") + private UUID languageId; + + @NotNull(message = "{validation.empty}") + @Valid + private NotificationTemplateValuePersist value; + + private String hash; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public NotificationTemplateChannel getChannel() { + return channel; + } + + public void setChannel(NotificationTemplateChannel channel) { + this.channel = channel; + } + + public UUID getNotificationType() { + return notificationType; + } + + public void setNotificationType(UUID notificationType) { + this.notificationType = notificationType; + } + + public NotificationTemplateKind getKind() { + return kind; + } + + public void setKind(NotificationTemplateKind kind) { + this.kind = kind; + } + + public UUID getLanguageId() { + return languageId; + } + + public void setLanguageId(UUID languageId) { + this.languageId = languageId; + } + + public NotificationTemplateValuePersist getValue() { + return value; + } + + public void setValue(NotificationTemplateValuePersist value) { + this.value = value; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/FieldInfoPersist.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/FieldInfoPersist.java new file mode 100644 index 000000000..d37341758 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/FieldInfoPersist.java @@ -0,0 +1,54 @@ +package gr.cite.notification.model.persist.notificationtemplate; + +import gr.cite.notification.common.types.notification.DataType; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +public class FieldInfoPersist { + + @NotNull + @NotEmpty + private String key; + + @NotNull + @NotEmpty + private DataType type; + + @NotNull + @NotEmpty + private String value; + + public FieldInfoPersist(String key, DataType type, String value) { + this.key = key; + this.type = type; + this.value = value; + } + + public FieldInfoPersist() { + } + + 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; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/FieldOptionsPersist.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/FieldOptionsPersist.java new file mode 100644 index 000000000..d145554db --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/FieldOptionsPersist.java @@ -0,0 +1,44 @@ +package gr.cite.notification.model.persist.notificationtemplate; + + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.Dictionary; +import java.util.List; + +public class FieldOptionsPersist { + + @NotNull(message = "{validation.empty}") + @Valid + private List mandatory; + + @Valid + private List optional; + + @Valid + private Dictionary formatting; + + public List getMandatory() { + return mandatory; + } + + public void setMandatory(List mandatory) { + this.mandatory = mandatory; + } + + public List getOptional() { + return optional; + } + + public void setOptional(List optional) { + this.optional = optional; + } + + public Dictionary getFormatting() { + return formatting; + } + + public void setFormatting(Dictionary formatting) { + this.formatting = formatting; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/NotificationTemplateValuePersist.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/NotificationTemplateValuePersist.java new file mode 100644 index 000000000..bba46e8ce --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/persist/notificationtemplate/NotificationTemplateValuePersist.java @@ -0,0 +1,150 @@ +package gr.cite.notification.model.persist.notificationtemplate; + +import gr.cite.notification.common.types.notification.EmailOverrideMode; +import gr.cite.notification.common.validation.ValidEnum; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +public class NotificationTemplateValuePersist { + + @NotNull + @NotEmpty + private String subjectText; + + @NotNull + @NotEmpty + private String subjectKey; + + @Valid + private FieldOptionsPersist subjectFieldOptions; + + @NotNull + @NotEmpty + private String bodyText; + + @NotNull + @NotEmpty + private String bodyKey; + private String priorityKey; + @NotNull + private Boolean allowAttachments = false; + private List cc; + + @ValidEnum + private EmailOverrideMode ccMode; + private List bcc; + + @ValidEnum + private EmailOverrideMode bccMode; + private List extraDataKeys; + + @Valid + private FieldOptionsPersist bodyFieldOptions; + + public String getSubjectText() { + return subjectText; + } + + public void setSubjectText(String subjectText) { + this.subjectText = subjectText; + } + + public String getSubjectKey() { + return subjectKey; + } + + public void setSubjectKey(String subjectKey) { + this.subjectKey = subjectKey; + } + + public FieldOptionsPersist getSubjectFieldOptions() { + return subjectFieldOptions; + } + + public void setSubjectFieldOptions(FieldOptionsPersist subjectFieldOptions) { + this.subjectFieldOptions = subjectFieldOptions; + } + + public String getBodyText() { + return bodyText; + } + + public void setBodyText(String bodyText) { + this.bodyText = bodyText; + } + + public String getBodyKey() { + return bodyKey; + } + + public void setBodyKey(String bodyKey) { + this.bodyKey = bodyKey; + } + + public String getPriorityKey() { + return priorityKey; + } + + public void setPriorityKey(String priorityKey) { + this.priorityKey = priorityKey; + } + + public Boolean getAllowAttachments() { + return allowAttachments; + } + + public void setAllowAttachments(Boolean allowAttachments) { + this.allowAttachments = allowAttachments; + } + + public List getCc() { + return cc; + } + + public void setCc(List cc) { + this.cc = cc; + } + + public EmailOverrideMode getCcMode() { + return ccMode; + } + + public void setCcMode(EmailOverrideMode ccMode) { + this.ccMode = ccMode; + } + + public List getBcc() { + return bcc; + } + + public void setBcc(List bcc) { + this.bcc = bcc; + } + + public EmailOverrideMode getBccMode() { + return bccMode; + } + + public void setBccMode(EmailOverrideMode bccMode) { + this.bccMode = bccMode; + } + + public List getExtraDataKeys() { + return extraDataKeys; + } + + public void setExtraDataKeys(List extraDataKeys) { + this.extraDataKeys = extraDataKeys; + } + + public FieldOptionsPersist getBodyFieldOptions() { + return bodyFieldOptions; + } + + public void setBodyFieldOptions(FieldOptionsPersist bodyFieldOptions) { + this.bodyFieldOptions = bodyFieldOptions; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/LanguageQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/LanguageQuery.java new file mode 100644 index 000000000..1cf2024e2 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/LanguageQuery.java @@ -0,0 +1,184 @@ +package gr.cite.notification.query; + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.data.LanguageEntity; +import gr.cite.notification.model.Language; +import gr.cite.tools.data.query.FieldResolver; +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 javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Predicate; +import java.time.Instant; +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class LanguageQuery extends QueryBase { + + private String like; + + private Collection ids; + + private Collection isActives; + + private Collection codes; + + private Collection excludedIds; + + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + public LanguageQuery like(String value) { + this.like = value; + return this; + } + + public LanguageQuery ids(UUID value) { + this.ids = List.of(value); + return this; + } + + public LanguageQuery ids(UUID... value) { + this.ids = Arrays.asList(value); + return this; + } + + public LanguageQuery ids(Collection values) { + this.ids = values; + return this; + } + + public LanguageQuery isActive(IsActive value) { + this.isActives = List.of(value); + return this; + } + + public LanguageQuery isActive(IsActive... value) { + this.isActives = Arrays.asList(value); + return this; + } + + public LanguageQuery isActive(Collection values) { + this.isActives = values; + return this; + } + + public LanguageQuery codes(String value) { + this.codes = List.of(value); + return this; + } + + public LanguageQuery codes(String... value) { + this.codes = Arrays.asList(value); + return this; + } + + public LanguageQuery codes(Collection values) { + this.codes = values; + return this; + } + + public LanguageQuery excludedIds(Collection values) { + this.excludedIds = values; + return this; + } + + public LanguageQuery excludedIds(UUID value) { + this.excludedIds = List.of(value); + return this; + } + + public LanguageQuery excludedIds(UUID... value) { + this.excludedIds = Arrays.asList(value); + return this; + } + + public LanguageQuery authorize(EnumSet values) { + this.authorize = values; + return this; + } + + public LanguageQuery( + ) { + } + + @Override + protected Class entityClass() { + return LanguageEntity.class; + } + + @Override + protected Boolean isFalseQuery() { + return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.excludedIds) || this.isEmpty(this.codes); + } + + @Override + protected Predicate applyFilters(QueryContext queryContext) { + List predicates = new ArrayList<>(); + if (this.ids != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._id)); + for (UUID item : this.ids) + inClause.value(item); + predicates.add(inClause); + } + if (this.like != null && !this.like.isEmpty()) { + predicates.add(queryContext.CriteriaBuilder.like(queryContext.Root.get(LanguageEntity._code), this.like)); + } + if (this.isActives != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._isActive)); + for (IsActive item : this.isActives) + inClause.value(item); + predicates.add(inClause); + } + if (this.codes != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._code)); + for (String item : this.codes) + inClause.value(item); + predicates.add(inClause); + } + if (this.excludedIds != null) { + CriteriaBuilder.In notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._id)); + for (UUID item : this.excludedIds) + notInClause.value(item); + predicates.add(notInClause.not()); + } + if (!predicates.isEmpty()) { + Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); + return queryContext.CriteriaBuilder.and(predicatesArray); + } else { + return null; + } + } + + @Override + protected LanguageEntity convert(Tuple tuple, Set columns) { + LanguageEntity item = new LanguageEntity(); + item.setId(QueryBase.convertSafe(tuple, columns, LanguageEntity._id, UUID.class)); + item.setCode(QueryBase.convertSafe(tuple, columns, LanguageEntity._code, String.class)); + item.setPayload(QueryBase.convertSafe(tuple, columns, LanguageEntity._payload, String.class)); + item.setOrdinal(QueryBase.convertSafe(tuple, columns, LanguageEntity._ordinal, Integer.class)); + item.setCreatedAt(QueryBase.convertSafe(tuple, columns, LanguageEntity._createdAt, Instant.class)); + item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, LanguageEntity._updatedAt, Instant.class)); + item.setIsActive(QueryBase.convertSafe(tuple, columns, LanguageEntity._isActive, IsActive.class)); + return item; + } + + @Override + protected String fieldNameOf(FieldResolver item) { + if (item.match(Language._id)) return LanguageEntity._id; + else if (item.match(Language._code)) return LanguageEntity._code; + else if (item.match(Language._payload)) return LanguageEntity._payload; + else if (item.match(Language._ordinal)) return LanguageEntity._ordinal; + else if (item.match(Language._createdAt)) return LanguageEntity._createdAt; + else if (item.match(Language._updatedAt)) return LanguageEntity._updatedAt; + else if (item.match(Language._hash)) return LanguageEntity._updatedAt; + else if (item.match(Language._isActive)) return LanguageEntity._isActive; + else return null; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationTemplateQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationTemplateQuery.java new file mode 100644 index 000000000..b06888c6b --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationTemplateQuery.java @@ -0,0 +1,202 @@ +package gr.cite.notification.query; + +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.enums.*; +import gr.cite.notification.data.NotificationTemplateEntity; +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.tools.data.query.FieldResolver; +import gr.cite.tools.data.query.QueryBase; +import gr.cite.tools.data.query.QueryContext; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Predicate; +import java.time.Instant; +import java.util.*; + + +@Component +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class NotificationTemplateQuery extends QueryBase { + private Collection ids; + + private Collection excludedIds; + private Collection isActives; + private List channels; + private List kinds; + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + public NotificationTemplateQuery ids(UUID value) { + this.ids = List.of(value); + return this; + } + + public NotificationTemplateQuery ids(UUID... value) { + this.ids = Arrays.asList(value); + return this; + } + + public NotificationTemplateQuery ids(Collection values) { + this.ids = values; + return this; + } + + public NotificationTemplateQuery isActive(IsActive value) { + this.isActives = List.of(value); + return this; + } + + public NotificationTemplateQuery isActive(IsActive... value) { + this.isActives = Arrays.asList(value); + return this; + } + + public NotificationTemplateQuery isActive(Collection values) { + this.isActives = values; + return this; + } + + public NotificationTemplateQuery channels(NotificationTemplateChannel... channels) { + this.channels = List.of(channels); + return this; + } + + public NotificationTemplateQuery channels(NotificationTemplateChannel channels) { + this.channels = List.of(channels); + return this; + } + + public NotificationTemplateQuery channels(List channels) { + this.channels = channels; + return this; + } + + public NotificationTemplateQuery kinds(NotificationTemplateKind... kinds) { + this.kinds = List.of(kinds); + return this; + } + + public NotificationTemplateQuery kinds(NotificationTemplateKind kinds) { + this.kinds = List.of(kinds); + return this; + } + + public NotificationTemplateQuery kinds(List kinds) { + this.kinds = kinds; + return this; + } + + public NotificationTemplateQuery excludedIds(Collection values) { + this.excludedIds = values; + return this; + } + + public NotificationTemplateQuery excludedIds(UUID value) { + this.excludedIds = List.of(value); + return this; + } + + public NotificationTemplateQuery excludedIds(UUID... value) { + this.excludedIds = Arrays.asList(value); + return this; + } + + + public NotificationTemplateQuery authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + protected Boolean isFalseQuery() { + return this.isNullOrEmpty(this.ids) + && this.isNullOrEmpty(this.isActives) + && this.isNullOrEmpty(this.kinds) + && this.isNullOrEmpty(this.channels); + } + + @Override + protected Class entityClass() { + return NotificationTemplateEntity.class; + } + + @Override + protected Predicate applyFilters(QueryContext queryContext) { + List predicates = new ArrayList<>(); + if (this.ids != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._id)); + for (UUID item : this.ids) + inClause.value(item); + predicates.add(inClause); + } + + if (this.isActives != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._isActive)); + for (IsActive item : this.isActives) + inClause.value(item); + predicates.add(inClause); + } + + if (this.channels != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._channel)); + for (NotificationTemplateChannel item : this.channels) + inClause.value(item); + predicates.add(inClause); } + + if (this.kinds != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._kind)); + for (NotificationTemplateKind item : this.kinds) + inClause.value(item); + predicates.add(inClause); + } + + if (this.excludedIds != null) { + CriteriaBuilder.In notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._id)); + for (UUID item : this.excludedIds) + notInClause.value(item); + predicates.add(notInClause.not()); + } + + if (predicates.size() > 0) { + Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); + return queryContext.CriteriaBuilder.and(predicatesArray); + } else { + return null; + } + + } + + @Override + protected String fieldNameOf(FieldResolver item) { + if (item.match(NotificationTemplate._id)) return NotificationTemplateEntity._id; + else if (item.match(NotificationTemplate._channel)) return NotificationTemplateEntity._channel; + else if (item.match(NotificationTemplate._kind)) return NotificationTemplateEntity._kind; + else if (item.match(NotificationTemplate._notificationType)) return NotificationTemplateEntity._notificationType; + else if (item.prefix(NotificationTemplate._value)) return NotificationTemplateEntity._value; + else if (item.prefix(NotificationTemplate._language)) return NotificationTemplateEntity._language; + else if (item.match(NotificationTemplate._createdAt)) return NotificationTemplateEntity._createdAt; + else if (item.match(NotificationTemplate._updatedAt)) return NotificationTemplateEntity._updatedAt; + else if (item.match(NotificationTemplate._isActive)) return NotificationTemplateEntity._isActive; + else if (item.match(NotificationTemplate._tenant)) return NotificationTemplateEntity._tenantId; + else return null; + } + + @Override + protected NotificationTemplateEntity convert(Tuple tuple, Set columns) { + NotificationTemplateEntity item = new NotificationTemplateEntity(); + item.setId(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._id, UUID.class)); + item.setChannel(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._channel, NotificationTemplateChannel.class)); + item.setKind(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._kind, NotificationTemplateKind.class)); + item.setNotificationType(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._notificationType, UUID.class)); + item.setValue(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._value, String.class)); + item.setLanguageId(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._language, UUID.class)); + item.setCreatedAt(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._createdAt, Instant.class)); + item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._updatedAt, Instant.class)); + item.setIsActive(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._isActive, IsActive.class)); + item.setTenantId(QueryBase.convertSafe(tuple, columns, NotificationTemplateEntity._tenantId, UUID.class)); + return item; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/LanguageLookup.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/LanguageLookup.java new file mode 100644 index 000000000..6d3f7dc3b --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/LanguageLookup.java @@ -0,0 +1,76 @@ +package gr.cite.notification.query.lookup; + +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.query.LanguageQuery; +import gr.cite.tools.data.query.Lookup; +import gr.cite.tools.data.query.QueryFactory; + +import java.util.List; +import java.util.UUID; + +public class LanguageLookup extends Lookup { + + private String like; + + private List isActive; + + private List codes; + + private List ids; + + private List excludedIds; + + public String getLike() { + return like; + } + + public void setLike(String like) { + this.like = like; + } + + public List getIsActive() { + return isActive; + } + + public void setIsActive(List isActive) { + this.isActive = isActive; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + public List getExcludedIds() { + return excludedIds; + } + + public void setExcludedIds(List excludeIds) { + this.excludedIds = excludeIds; + } + + public List getCodes() { + return codes; + } + + public void setCodes(List codes) { + this.codes = codes; + } + + public LanguageQuery enrich(QueryFactory queryFactory) { + LanguageQuery query = queryFactory.query(LanguageQuery.class); + if (this.like != null) query.like(this.like); + if (this.isActive != null) query.isActive(this.isActive); + if (this.codes != null) query.codes(this.codes); + if (this.ids != null) query.ids(this.ids); + if (this.excludedIds != null) query.excludedIds(this.excludedIds); + + this.enrichCommon(query); + + return query; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationTemplateLookup.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationTemplateLookup.java new file mode 100644 index 000000000..9625e3600 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationTemplateLookup.java @@ -0,0 +1,78 @@ +package gr.cite.notification.query.lookup; + +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.common.enums.NotificationTemplateChannel; +import gr.cite.notification.common.enums.NotificationTemplateKind; +import gr.cite.notification.query.NotificationTemplateQuery; +import gr.cite.tools.data.query.Lookup; +import gr.cite.tools.data.query.QueryFactory; + +import java.util.List; +import java.util.UUID; + +public class NotificationTemplateLookup extends Lookup { + + private List isActive; + + private List channels; + + private List kinds; + + private List ids; + + private List excludedIds; + + public List getIsActive() { + return isActive; + } + + public void setIsActive(List isActive) { + this.isActive = isActive; + } + + public List getChannels() { + return channels; + } + + public void setChannels(List channels) { + this.channels = channels; + } + + public List getKinds() { + return kinds; + } + + public void setKinds(List kinds) { + this.kinds = kinds; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + public List getExcludedIds() { + return excludedIds; + } + + public void setExcludedIds(List excludedIds) { + this.excludedIds = excludedIds; + } + + public NotificationTemplateQuery enrich(QueryFactory queryFactory) { + NotificationTemplateQuery query = queryFactory.query(NotificationTemplateQuery.class); + if (this.ids != null) query.ids(this.ids); + if (this.excludedIds != null) query.excludedIds(this.excludedIds); + if (this.isActive != null) query.isActive(this.isActive); + if (this.channels != null) query.channels(this.channels); + if (this.kinds != null) query.kinds(this.kinds); + + this.enrichCommon(query); + + return query; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationtemplate/NotificationServiceTemplateImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationtemplate/NotificationServiceTemplateImpl.java new file mode 100644 index 000000000..3155d5759 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationtemplate/NotificationServiceTemplateImpl.java @@ -0,0 +1,176 @@ +package gr.cite.notification.service.notificationtemplate; + +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.authorization.Permission; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.common.types.notificationtemplate.FieldInfoEntity; +import gr.cite.notification.common.types.notificationtemplate.FieldOptionsEntity; +import gr.cite.notification.common.types.notificationtemplate.NotificationTemplateValueEntity; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.data.NotificationTemplateEntity; +import gr.cite.notification.data.TenantScopedEntityManager; +import gr.cite.notification.errorcode.ErrorThesaurusProperties; +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.notification.model.builder.NotificationTemplateBuilder; +import gr.cite.notification.model.deleter.NotificationTemplateDeleter; +import gr.cite.notification.model.persist.NotificationTemplatePersist; +import gr.cite.notification.model.persist.notificationtemplate.FieldInfoPersist; +import gr.cite.notification.model.persist.notificationtemplate.FieldOptionsPersist; +import gr.cite.notification.model.persist.notificationtemplate.NotificationTemplateValuePersist; +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.jetbrains.annotations.NotNull; +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.ArrayList; +import java.util.List; +import java.util.UUID; + +@Service +@RequestScope +public class NotificationServiceTemplateImpl implements NotificationTemplateService { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationServiceTemplateImpl.class)); + private final TenantScopedEntityManager entityManager; + private final AuthorizationService authService; + private final AuthorizationService authorizationService; + private final DeleterFactory deleterFactory; + private final BuilderFactory builderFactory; + private final ConventionService conventionService; + private final ErrorThesaurusProperties errors; + private final MessageSource messageSource; + private final JsonHandlingService jsonHandlingService; + + @Autowired + public NotificationServiceTemplateImpl( + TenantScopedEntityManager entityManager, + AuthorizationService authService, AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + ConventionService conventionService, + ErrorThesaurusProperties errors, + MessageSource messageSource, + JsonHandlingService jsonHandlingService) { + this.entityManager = entityManager; + this.authService = authService; + this.authorizationService = authorizationService; + this.deleterFactory = deleterFactory; + this.builderFactory = builderFactory; + this.conventionService = conventionService; + this.errors = errors; + this.messageSource = messageSource; + this.jsonHandlingService = jsonHandlingService; + } + + @Override + public NotificationTemplate persist(NotificationTemplatePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException { + logger.debug(new MapLogEntry("persisting notification template").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeForce(Permission.EditNotificationTemplate); + + Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); + + NotificationTemplateEntity data = null; + if (isUpdate) { + data = this.entityManager.find(NotificationTemplateEntity.class, model.getId()); + if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), NotificationTemplate.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 NotificationTemplateEntity(); + data.setId(UUID.randomUUID()); + data.setIsActive(IsActive.Active); + data.setCreatedAt(Instant.now()); + } + + data.setChannel(model.getChannel()); + data.setKind(model.getKind()); + data.setNotificationType(model.getNotificationType()); + data.setLanguageId(model.getLanguageId()); + data.setValue(this.jsonHandlingService.toJsonSafe(this.buildNotificationTemplateValueEntity(model.getValue()))); + data.setUpdatedAt(Instant.now()); + + if (isUpdate) this.entityManager.merge(data); + else this.entityManager.persist(data); + + this.entityManager.flush(); + + return this.builderFactory.builder(NotificationTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(BaseFieldSet.build(fields, NotificationTemplate._id, NotificationTemplate._hash), data); + } + + private @NotNull NotificationTemplateValueEntity buildNotificationTemplateValueEntity(NotificationTemplateValuePersist persist) { + NotificationTemplateValueEntity data = new NotificationTemplateValueEntity(); + if (persist == null) return data; + + data.setSubjectText(persist.getSubjectText()); + data.setSubjectKey(persist.getSubjectKey()); + if (!this.conventionService.isListNullOrEmpty(List.of(persist.getSubjectFieldOptions()))) { + data.setSubjectFieldOptions(this.buildFieldOptionsEntity(persist.getSubjectFieldOptions())); + } + data.setBodyText(persist.getBodyText()); + data.setBodyKey(persist.getBodyKey()); + data.setPriorityKey(persist.getPriorityKey()); + data.setAllowAttachments(persist.getAllowAttachments()); + data.setCc(persist.getCc()); + data.setCcMode(persist.getCcMode()); + data.setBcc(persist.getBcc()); + data.setBccMode(persist.getBccMode()); + data.setExtraDataKeys(persist.getExtraDataKeys()); + if (!this.conventionService.isListNullOrEmpty(List.of(persist.getBodyFieldOptions()))) { + data.setBodyFieldOptions(this.buildFieldOptionsEntity(persist.getBodyFieldOptions())); + } + + return data; + } + + private @NotNull FieldOptionsEntity buildFieldOptionsEntity(FieldOptionsPersist persist) { + FieldOptionsEntity data = new FieldOptionsEntity(); + if (persist == null) return data; + + data.setMandatory(persist.getMandatory()); + if (!this.conventionService.isListNullOrEmpty(persist.getOptional())) { + data.setOptional(new ArrayList<>()); + for (FieldInfoPersist optionalPersist : persist.getOptional()) { + data.getOptional().add(this.buildFieldInfoEntity(optionalPersist)); + } + } + data.setFormatting(persist.getFormatting()); + + return data; + } + + private @NotNull FieldInfoEntity buildFieldInfoEntity(FieldInfoPersist persist) { + FieldInfoEntity data = new FieldInfoEntity(); + if (persist == null) return data; + + data.setKey(persist.getKey()); + data.setType(persist.getType()); + data.setValue(persist.getValue()); + + return data; + } + + @Override + public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug("deleting notification template: {}", id); + this.authService.authorizeForce(Permission.DeleteNotificationTemplate); + this.deleterFactory.deleter(NotificationTemplateDeleter.class).deleteAndSaveByIds(List.of(id)); + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationtemplate/NotificationTemplateService.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationtemplate/NotificationTemplateService.java new file mode 100644 index 000000000..b7d3e315d --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationtemplate/NotificationTemplateService.java @@ -0,0 +1,18 @@ +package gr.cite.notification.service.notificationtemplate; + +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.notification.model.persist.NotificationTemplatePersist; +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; +import java.util.UUID; + +public interface NotificationTemplateService { + + NotificationTemplate persist(NotificationTemplatePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException; + void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; +} diff --git a/dmp-db-scema/updates/00.01.041_add_ntf_NotificationTemplate.sql b/dmp-db-scema/updates/00.01.041_add_ntf_NotificationTemplate.sql new file mode 100644 index 000000000..4fc0fed16 --- /dev/null +++ b/dmp-db-scema/updates/00.01.041_add_ntf_NotificationTemplate.sql @@ -0,0 +1,34 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.01.041'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + + CREATE TABLE public."ntf_NotificationTemplate" + ( + id uuid NOT NULL, + channel smallint NOT NULL, + notification_type uuid NOT NULL, + kind smallint NOT NULL, + language uuid NOT NULL, + value text NOT NULL, + is_active smallint NOT NULL, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL, + tenant uuid, + CONSTRAINT "NotificationTemplate_pkey" PRIMARY KEY (id), + CONSTRAINT "NotificationTemplate_language_fkey" FOREIGN KEY (language) + REFERENCES public."Language" (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION + NOT VALID, + CONSTRAINT "NotificationTemplate_tenant_fkey" FOREIGN KEY (tenant) + REFERENCES public."Tenant" (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION + NOT VALID + ); + + INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.01.041', '2023-12-15 12:00:00.000000+02', now(), 'Add ntf_NotificationTemplate table.'); + +END$$; \ No newline at end of file