diff --git a/dmp-backend/core/pom.xml b/dmp-backend/core/pom.xml index 5ece8aa4e..24197ca4e 100644 --- a/dmp-backend/core/pom.xml +++ b/dmp-backend/core/pom.xml @@ -24,10 +24,15 @@ commons-csv 1.10.0 + + commons-validator + commons-validator + 1.8.0 + gr.cite validation - 2.1.0 + 3.0.1 gr.cite diff --git a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java index 2d15d5232..8297c8d42 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java +++ b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java @@ -37,6 +37,7 @@ public class AuditableAction { public static final EventId Dmp_RemoveUser = new EventId(5007, "Dmp_RemoveUser"); public static final EventId Dmp_Invite_Users = new EventId(5008, "Dmp_Invite_Users"); public static final EventId Dmp_Invite_Accept = new EventId(5009, "Dmp_Invite_Accept"); + public static final EventId Dmp_PublicQuery = new EventId(5010, "Dmp_PublicQuery"); public static final EventId Description_Query = new EventId(6000, "Description_Query"); public static final EventId Description_Lookup = new EventId(6001, "Description_Lookup"); @@ -129,5 +130,14 @@ public class AuditableAction { public static final EventId ContactSupport_Sent = new EventId(210000, "ContactSupport_Sent"); public static final EventId ContactSupport_PublicSent = new EventId(210001, "ContactSupport_PublicSent"); + public static final EventId Prefilling_Query = new EventId(220000, "Prefilling_Query"); + public static final EventId Prefilling_Generate = new EventId(210001, "Prefilling_Generate"); + public static final EventId Prefilling_GenerateWithData = new EventId(210002, "Prefilling_GenerateWithData"); + + public static final EventId Maintenance_GenerateElastic = new EventId(220000, "Maintenance_GenerateElastic"); + public static final EventId Maintenance_ClearElastic = new EventId(230000, "Maintenance_ClearElastic"); + + public static final EventId Principal_Lookup = new EventId(240000, "Principal_Lookup"); + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/ClaimNames.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/ClaimNames.java new file mode 100644 index 000000000..4e6edfdbd --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/ClaimNames.java @@ -0,0 +1,5 @@ +package eu.eudat.authorization; + +public class ClaimNames { + public static final String ExternalProviderName = "ExternalProviderName"; +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java index 1ddf0698d..869f36ef1 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java @@ -164,6 +164,10 @@ public final class Permission { public static String BrowseTenantUser = "BrowseTenantUser"; public static String EditTenantUser = "EditTenantUser"; public static String DeleteTenantUser = "DeleteTenantUser"; + + //Prefilling + public static String BrowsePrefilling = "BrowsePrefilling"; + //Lock public static String BrowseLock = "BrowseLock"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/EmailConfirmationEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/MergeAccountConfirmationEntity.java similarity index 83% rename from dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/EmailConfirmationEntity.java rename to dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/MergeAccountConfirmationEntity.java index 72c74869a..d158f1b22 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/EmailConfirmationEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/MergeAccountConfirmationEntity.java @@ -5,9 +5,9 @@ import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlRootElement; -@XmlRootElement(name = "email-confirmation") +@XmlRootElement(name = "merge-account-confirmation") @XmlAccessorType(XmlAccessType.FIELD) -public class EmailConfirmationEntity { +public class MergeAccountConfirmationEntity { @XmlAttribute(name = "email") private String email; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/RemoveCredentialRequestEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/RemoveCredentialRequestEntity.java new file mode 100644 index 000000000..773c9aacc --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/actionconfirmation/RemoveCredentialRequestEntity.java @@ -0,0 +1,24 @@ +package eu.eudat.commons.types.actionconfirmation; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.util.UUID; + +@XmlRootElement(name = "remove-credential-confirmation") +@XmlAccessorType(XmlAccessType.FIELD) +public class RemoveCredentialRequestEntity { + + @XmlAttribute(name = "credential-id") + private UUID credentialId; + + public UUID getCredentialId() { + return credentialId; + } + + public void setCredentialId(UUID credentialId) { + this.credentialId = credentialId; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/DefinitionEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/DefinitionEntity.java index 492495a74..5e87fdc1c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/DefinitionEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/DefinitionEntity.java @@ -77,15 +77,18 @@ public class DefinitionEntity implements XmlSerializable { } return this; } - public List getFieldById(String id){ + public List getAllField(){ List fieldEntities = new ArrayList<>(); - if (id == null || id.isBlank()) return fieldEntities; if (this.getSections() != null){ for (SectionEntity sectionEntity: this.getSections()) { - fieldEntities.addAll(sectionEntity.getFieldById(id)); + fieldEntities.addAll(sectionEntity.getAllField()); } } return fieldEntities; } + public List getFieldById(String id) { + return this.getAllField().stream().filter(x-> id.equals(x.getId())).toList(); + } + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/FieldSetEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/FieldSetEntity.java index 85ff4c7c2..35492ff86 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/FieldSetEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/FieldSetEntity.java @@ -190,11 +190,8 @@ public class FieldSetEntity implements DatabaseViewStyleDefinition, XmlSerializa this.multiplicity.setTableView(Boolean.parseBoolean(multiplicity.getAttribute("tableView"))); return this; - } - - public List getFieldById(String id){ - if (this.getFields() == null || id == null || id.isBlank()) return new ArrayList<>(); - - return this.getFields().stream().filter(x-> id.equals(x.getId())).toList(); + } + public List getAllField() { + return this.getFields() == null ? new ArrayList<>() : this.getFields(); } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/SectionEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/SectionEntity.java index 72a4bf5e0..2041ed3bc 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/SectionEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/SectionEntity.java @@ -209,17 +209,16 @@ public class SectionEntity implements DatabaseViewStyleDefinition, XmlSerializab return this; } - public List getFieldById(String id){ + public List getAllField(){ List fieldEntities = new ArrayList<>(); - if (id == null || id.isBlank()) return fieldEntities; if (this.getFieldSets() != null){ for (FieldSetEntity fieldSetEntity: this.getFieldSets()) { - fieldEntities.addAll(fieldSetEntity.getFieldById(id)); + fieldEntities.addAll(fieldSetEntity.getAllField()); } } if (this.getSections() != null){ for (SectionEntity sectionEntity: this.getSections()) { - fieldEntities.addAll(sectionEntity.getFieldById(id)); + fieldEntities.addAll(sectionEntity.getAllField()); } } return fieldEntities; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/AutoCompleteDataEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/AutoCompleteDataEntity.java index 971e8ae31..d3d0a05fb 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/AutoCompleteDataEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/AutoCompleteDataEntity.java @@ -15,6 +15,9 @@ import java.util.List; import java.util.Map; public class AutoCompleteDataEntity extends ComboBoxDataEntity { + public AutoCompleteDataEntity() { + super(FieldType.AUTO_COMPLETE); + } public static class AuthAutoCompleteData { private String url; @@ -145,11 +148,6 @@ public class AutoCompleteDataEntity extends ComboBoxDataEntity implements XmlSerializable { + + private final FieldType fieldType; + + public BaseFieldDataEntity(FieldType fieldType) { + this.fieldType = fieldType; + } + private String label; - public abstract FieldType getFieldType(); + + public FieldType getFieldType() { + return fieldType; + } public String getLabel() { return label; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/BooleanDecisionDataEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/BooleanDecisionDataEntity.java deleted file mode 100644 index b92b2c7d1..000000000 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/BooleanDecisionDataEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package eu.eudat.commons.types.descriptiontemplate.fielddata; - -import eu.eudat.commons.enums.FieldType; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -public class BooleanDecisionDataEntity extends BaseFieldDataEntity { - - @Override - public FieldType getFieldType() { - return FieldType.BOOLEAN_DECISION; - } -} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/CheckBoxDataEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/CheckBoxDataEntity.java deleted file mode 100644 index b45af367e..000000000 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/CheckBoxDataEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package eu.eudat.commons.types.descriptiontemplate.fielddata; - -import eu.eudat.commons.enums.FieldType; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -public class CheckBoxDataEntity extends BaseFieldDataEntity { - - @Override - public FieldType getFieldType() { - return FieldType.CHECK_BOX; - } -} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/ComboBoxDataEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/ComboBoxDataEntity.java index 2551604ce..a84abc5ba 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/ComboBoxDataEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/descriptiontemplate/fielddata/ComboBoxDataEntity.java @@ -1,6 +1,7 @@ package eu.eudat.commons.types.descriptiontemplate.fielddata; import eu.eudat.commons.enums.FieldDataComboBoxType; +import eu.eudat.commons.enums.FieldType; import eu.eudat.commons.types.xml.XmlSerializable; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -10,6 +11,10 @@ import java.util.Map; public abstract class ComboBoxDataEntity extends BaseFieldDataEntity { + public ComboBoxDataEntity(FieldType fieldType) { + super(fieldType); + } + public abstract FieldDataComboBoxType getFieldSubType(); public static class Option implements XmlSerializable + + org.springframework.boot + spring-boot-starter-webflux + + org.springframework.boot spring-boot-starter-validation - 2.6.4 @@ -35,15 +40,21 @@ postgresql - org.hibernate + org.hibernate.orm hibernate-core + + org.springframework.boot + spring-boot-starter-tomcat + + gr.cite notification 1.0.0 + gr.cite oidc-authz @@ -64,15 +75,6 @@ cors-web 1.0.0 - - org.springframework.boot - spring-boot - 2.6.4 - - - org.springframework - spring-web - diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/NotificationApplication.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/NotificationApplication.java index 164fdca37..300316451 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/NotificationApplication.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/NotificationApplication.java @@ -3,19 +3,24 @@ package gr.cite.notification.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableAsync; -@SpringBootApplication -@ComponentScan({ - "gr.cite.notification", - "gr.cite.tools", - "gr.cite.commons"}) +@SpringBootApplication( + scanBasePackages = { + "eu.eudat", + "gr.cite", + "gr.cite.queueoutbox", + "gr.cite.queueinbox", + "gr.cite.notification.integrationevent", + "gr.cite.tools", + "gr.cite.commons"}) @EntityScan({ - "gr.cite.notification.data"}) + "gr.cite.notification.data"}) +@EnableAsync public class NotificationApplication { - public static void main(String[] args) { - SpringApplication.run(NotificationApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(NotificationApplication.class, args); + } } diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/config/SecurityConfiguration.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/config/SecurityConfiguration.java index 18d3c5172..2e17e3de6 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/config/SecurityConfiguration.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/config/SecurityConfiguration.java @@ -18,18 +18,20 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManagerResolver; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; -import javax.servlet.Filter; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.Filter; +import jakarta.servlet.http.HttpServletRequest; import java.util.List; import java.util.Set; @Configuration @EnableWebSecurity -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { +public class SecurityConfiguration { private final WebSecurityProperties webSecurityProperties; private final AuthenticationManagerResolver authenticationManagerResolver; @@ -47,20 +49,19 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { this.ownedAuthorizationHandler = ownedAuthorizationHandler; } - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .csrf().disable() - .cors() - .and() + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + HttpSecurity tempHttp = http + .csrf(AbstractHttpConfigurer::disable) + .cors(httpSecurityCorsConfigurer -> {}) + .headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) .addFilterBefore(apiKeyFilter, AbstractPreAuthenticatedProcessingFilter.class) - .authorizeRequests() - .antMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous() - .antMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated() - .and() - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) - .and() + .authorizeHttpRequests(authRequest -> + authRequest.requestMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous() + .requestMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated()) + .sessionManagement( sessionManagementConfigurer-> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.NEVER)) .oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver)); + return tempHttp.build(); } @Bean diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/InAppNotificationController.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/InAppNotificationController.java index 95aab412c..519148da3 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/InAppNotificationController.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/InAppNotificationController.java @@ -31,21 +31,19 @@ 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.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.management.InvalidApplicationException; -import javax.transaction.Transactional; +import jakarta.transaction.Transactional; import java.util.*; @RestController -@RequestMapping(path = "api/notification/inapp-notification") +@RequestMapping(path = "api/inapp-notification") public class InAppNotificationController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(InAppNotificationController.class)); private final BuilderFactory builderFactory; private final AuditService auditService; - private final NotificationService notificationService; private final CensorFactory censorFactory; private final QueryFactory queryFactory; private final MessageSource messageSource; @@ -62,7 +60,6 @@ public class InAppNotificationController { InAppNotificationService inAppNotificationService, UserScope userScope, ErrorThesaurusProperties errors) { this.builderFactory = builderFactory; this.auditService = auditService; - this.notificationService = notificationService; this.censorFactory = censorFactory; this.queryFactory = queryFactory; this.messageSource = messageSource; @@ -112,7 +109,7 @@ public class InAppNotificationController { @PostMapping("{id}/read") @Transactional - public ResponseEntity persist(@PathVariable UUID id) + public Boolean persist(@PathVariable UUID id) { logger.debug(new MapLogEntry("marking as read").And("id", id)); @@ -120,12 +117,12 @@ public class InAppNotificationController { this.auditService.track(AuditableAction.InApp_Notification_Read, Map.of("id", id)); //this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action); - return ResponseEntity.ok("ok"); + return true; } @PostMapping("read-all") @Transactional - public ResponseEntity MarkAsReadAllUserInAppNotification() throws InvalidApplicationException { + public Boolean MarkAsReadAllUserInAppNotification() throws InvalidApplicationException { logger.debug(new MapLogEntry("marking as read all")); UUID userId = this.userScope.getUserId(); @@ -134,12 +131,12 @@ public class InAppNotificationController { this.inAppNotificationService.markAsReadAllUserNotification(userId); this.auditService.track(AuditableAction.InApp_Notification_Read_All, Map.of("userId", userId)); - return ResponseEntity.ok("ok"); + return true; } @GetMapping("count-unread") @Transactional - public ResponseEntity CountUnread() throws InvalidApplicationException { + public Integer CountUnread() throws InvalidApplicationException { logger.debug("count-unread"); UUID userId = this.userScope.getUserId(); @@ -152,7 +149,7 @@ public class InAppNotificationController { //this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action); - return ResponseEntity.ok(count); + return count; } @DeleteMapping("{id}") @@ -160,7 +157,7 @@ public class InAppNotificationController { public void Delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { logger.debug(new MapLogEntry("deleting" + Notification.class.getSimpleName()).And("id", id)); - this.notificationService.deleteAndSave(id); + this.inAppNotificationService.deleteAndSave(id); this.auditService.track(AuditableAction.InApp_Notification_Delete, "id", id); diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationController.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationController.java index 236769802..789ab6d5e 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationController.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/NotificationController.java @@ -4,7 +4,6 @@ import gr.cite.notification.audit.AuditableAction; import gr.cite.notification.authorization.AuthorizationFlags; import gr.cite.notification.data.NotificationEntity; import gr.cite.notification.model.Notification; -import gr.cite.notification.model.SendNotificationResult; import gr.cite.notification.model.builder.NotificationBuilder; import gr.cite.notification.model.censorship.NotificationCensor; import gr.cite.notification.model.persist.NotificationPersist; @@ -23,6 +22,7 @@ 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 jakarta.transaction.Transactional; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -30,11 +30,10 @@ 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/notification") +@RequestMapping(path = "api/notification") public class NotificationController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotificationController.class)); 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 index 820b7caf5..ba3050101 100644 --- 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 @@ -29,7 +29,7 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.web.bind.annotation.*; import javax.management.InvalidApplicationException; -import javax.transaction.Transactional; +import jakarta.transaction.Transactional; import java.util.*; @RestController diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/TenantConfigurationController.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/TenantConfigurationController.java index 0112e376c..82de8be48 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/TenantConfigurationController.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/TenantConfigurationController.java @@ -32,8 +32,8 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.web.bind.annotation.*; import javax.management.InvalidApplicationException; -import javax.transaction.Transactional; -import javax.validation.Valid; +import jakarta.transaction.Transactional; +import jakarta.validation.Valid; import java.util.*; @RestController diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java index 352b0c3ba..1a54be1b0 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java @@ -10,11 +10,9 @@ import gr.cite.notification.model.UserNotificationPreference; import gr.cite.notification.model.builder.UserNotificationPreferenceBuilder; import gr.cite.notification.model.censorship.UserNotificationPreferenceCensor; import gr.cite.notification.model.persist.UserNotificationPreferencePersist; -import gr.cite.notification.model.persist.tenantconfiguration.TenantConfigurationNotifierListPersist; import gr.cite.notification.query.UserNotificationPreferenceQuery; import gr.cite.notification.query.lookup.NotifierListLookup; import gr.cite.notification.query.lookup.UserNotificationPreferenceLookup; -import gr.cite.notification.service.tenantconfiguration.TenantConfigurationService; import gr.cite.notification.service.userNotificationPreference.UserNotificationPreferenceService; import gr.cite.notification.web.model.QueryResult; import gr.cite.tools.auditing.AuditService; @@ -27,15 +25,14 @@ 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 jakarta.validation.Valid; 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 javax.validation.Valid; +import jakarta.transaction.Transactional; import java.util.*; @RestController diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java index 47208b1ca..83e461b18 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java @@ -35,8 +35,8 @@ import org.springframework.ui.ModelMap; import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequestInterceptor; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import java.time.Instant; import java.util.ArrayList; import java.util.List; diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantInterceptor.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantInterceptor.java index ef36af989..e28f0a5ec 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantInterceptor.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantInterceptor.java @@ -26,13 +26,13 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequestInterceptor; import javax.management.InvalidApplicationException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; -import javax.persistence.criteria.Subquery; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; import java.util.List; import java.util.Locale; diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeClaimInterceptor.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeClaimInterceptor.java index dbabb0857..138b9661f 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeClaimInterceptor.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeClaimInterceptor.java @@ -22,12 +22,12 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequestInterceptor; import javax.management.InvalidApplicationException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import java.util.List; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeHeaderInterceptor.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeHeaderInterceptor.java index 15bc2790f..3a5b2ca20 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeHeaderInterceptor.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/tenant/TenantScopeHeaderInterceptor.java @@ -17,12 +17,12 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequestInterceptor; import javax.management.InvalidApplicationException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import java.util.List; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/user/UserInterceptor.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/user/UserInterceptor.java index 43bc4fb9b..63ac88829 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/user/UserInterceptor.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/scope/user/UserInterceptor.java @@ -21,12 +21,12 @@ //import org.springframework.web.context.request.WebRequestInterceptor; // //import javax.management.InvalidApplicationException; -//import javax.persistence.EntityManager; -//import javax.persistence.PersistenceContext; -//import javax.persistence.Tuple; -//import javax.persistence.criteria.CriteriaBuilder; -//import javax.persistence.criteria.CriteriaQuery; -//import javax.persistence.criteria.Root; +//import jakarta.persistence.EntityManager; +//import jakarta.persistence.PersistenceContext; +//import jakarta.persistence.Tuple; +//import jakarta.persistence.criteria.CriteriaBuilder; +//import jakarta.persistence.criteria.CriteriaQuery; +//import jakarta.persistence.criteria.Root; //import java.time.Instant; //import java.util.List; //import java.util.UUID; diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/config/application.yml b/dmp-backend/notification-service/notification-web/src/main/resources/config/application.yml index 4f9a66b6d..06b5f37c9 100644 --- a/dmp-backend/notification-service/notification-web/src/main/resources/config/application.yml +++ b/dmp-backend/notification-service/notification-web/src/main/resources/config/application.yml @@ -16,5 +16,6 @@ spring: optional:classpath:config/cors.yml[.yml], optional:classpath:config/cors-${spring.profiles.active}.yml[.yml], optional:file:../config/cors-${spring.profiles.active}.yml[.yml], optional:classpath:config/notification.yml[.yml], optional:classpath:config/notification-${spring.profiles.active}.yml[.yml], optional:file:../config/notification-${spring.profiles.active}.yml[.yml], optional:classpath:config/email.yml[.yml], optional:classpath:config/email-${spring.profiles.active}.yml[.yml], optional:file:../config/email-${spring.profiles.active}.yml[.yml], + optional:classpath:config/queue.yml[.yml], optional:classpath:config/queue-${spring.profiles.active}.yml[.yml], optional:file:../config/queue-${spring.profiles.active}.yml[.yml], optional:classpath:config/cipher.yml[.yml], optional:classpath:config/cipher-${spring.profiles.active}.yml[.yml], optional:file:../config/cipher-${spring.profiles.active}.yml[.yml], optional:classpath:config/formatting.yml[.yml], optional:classpath:config/formatting-${spring.profiles.active}.yml[.yml], optional:file:../config/formatting-${spring.profiles.active}.yml[.yml] 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 5c5e91151..7192cf334 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 @@ -16,7 +16,7 @@ notification: contacts: [ email ] - #dmpInvitationExistingUser type: 4904dea2-5079-46d3-83be-3a19c9ab45dc - contacts: [ email ] + contacts: [ inapp, email ] - #dpmModified type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB contacts: [ email ] @@ -314,6 +314,187 @@ notification: template-cache: prefix: ${CACHE_DISAMBIGUATION:} key-pattern: "{prefix}:Notification_Message_Email_Template:{key}:v0" + in-app: + flows: + - #dmpInvitationExistingUser + key: 4904dea2-5079-46d3-83be-3a19c9ab45dc + subject-path: classpath:notification_templates/dmpinvitationexistinguser/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpinvitationexistinguser/inapp/body.{language}.html + body-field-options: + mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{dmpname}]': null + '[{dmprole}]': null + '[{reasonName}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #dmpModified + key: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB + subject-path: classpath:notification_templates/dmpmodified/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpmodified/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #dmpFinalised + key: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E + subject-path: classpath:notification_templates/dmpfinalised/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpfinalised/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #desriptionModified + key: 4FDBFA80-7A71-4A69-B854-67CBB70648F1 + subject-path: classpath:notification_templates/descriptionmodified/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/descriptionmodified/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #descriptionFinalised + key: 33790bad-94d4-488a-8ee2-7f6295ca18ea + subject-path: classpath:notification_templates/descriptionfinalised/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/descriptionfinalised/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #mergeAccountConfirmation + key: BFE68845-CB05-4C5A-A03D-29161A7C9660 + subject-path: classpath:notification_templates/mergeacountconfirmation/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/mergeacountconfirmation/inapp/body.{language}.html + body-field-options: + mandatory: [ "{userName}", "{installation-url}", "{confirmationToken}" ] + optional: + - key: "{expiration_time}" + value: --- + formatting: + '[{userName}]': null + '[{installation-url}]': null + '[{confirmationToken}]': null + '[{expiration_time}]': null + priority-key: null + cipher-fields: [ ] + - #removeCredentialConfirmation + key: C9BC3F16-057E-4BBA-8A5F-36BD835E5604 + subject-path: classpath:notification_templates/removecredentialconfirmation/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ "{installation-url}", "{confirmationToken}" ] + optional: [ ] + body-path: classpath:notification_templates/removecredentialconfirmation/inapp/body.{language}.html + body-field-options: + mandatory: [ ] + optional: + - key: "{email}" + value: email + - key: "{expiration_time}" + value: -- + formatting: + '[{email}]': null + '[{expiration_time}]': null + priority-key: null + cipher-fields: [ ] + - #dmpDeposit + key: 55736F7A-83AB-4190-AF43-9D031A6F9612 + subject-path: classpath:notification_templates/dmpdeposit/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpdeposit/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #descriptionTemplateInvitation + key: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B + subject-path: classpath:notification_templates/descriptiontemplateinvitation/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/descriptiontemplateinvitation/inapp/body.{language}.html + body-field-options: + mandatory: [ "{templateName}", "{installation-url}", "{templateID}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{templateName}]': null + '[{installation-url}]': null + '[{templateID}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + template-cache: + prefix: ${CACHE_DISAMBIGUATION:} + key-pattern: "{prefix}:Notification_Message_InApp_Template:{key}:v0" override-cache: template-cache: prefix: ${CACHE_DISAMBIGUATION:} 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 1bc742f5f..e93f4f3af 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 @@ -75,18 +75,22 @@ permissions: #Notification BrowseNotification: roles: - - ic-sti-superuser - - user + - Admin clients: [ ] allowAnonymous: true allowAuthenticated: false EditNotification: roles: - - ic-sti-superuser - - user + - Admin clients: [ ] allowAnonymous: true allowAuthenticated: false + DeleteNotification: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false #Tenant Configuration BrowseTenantConfiguration: roles: @@ -156,6 +160,20 @@ permissions: allowAnonymous: false allowAuthenticated: false DeleteNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + + # In App Notification Permissions + BrowseInAppNotification: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + DeleteInAppNotification: roles: - Admin clients: [ ] diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/config/queue-devel.yml b/dmp-backend/notification-service/notification-web/src/main/resources/config/queue-devel.yml index f0e31766d..1c761d9e5 100644 --- a/dmp-backend/notification-service/notification-web/src/main/resources/config/queue-devel.yml +++ b/dmp-backend/notification-service/notification-web/src/main/resources/config/queue-devel.yml @@ -1,5 +1,6 @@ queue: rabbitmq: + enable: true durable: true queue: cite_dmp_devel_notification_inbox_queue exchange: cite_dmp_devel_queue @@ -7,12 +8,14 @@ queue: publisherEnabled: true task: publisher: + enable: true options: exchange: cite_dmp_devel_queue rabbitmq: enable: true listener: + enable: true options: exchange: cite_dmp_devel_queue rabbitmq: - enable: false + enable: true diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/config/queue.yml b/dmp-backend/notification-service/notification-web/src/main/resources/config/queue.yml index 2886f369a..a61881d7d 100644 --- a/dmp-backend/notification-service/notification-web/src/main/resources/config/queue.yml +++ b/dmp-backend/notification-service/notification-web/src/main/resources/config/queue.yml @@ -26,11 +26,6 @@ queue: options: exchange: null forget-me-completed-topic: forgetme.completed - notify-topic: notification.notify - tenant-reactivation-topic: tenant.reactivated - tenant-removal-topic: tenant.remove - tenant-touch-topic: tenant.touch - tenant-user-invite-topic: tenant.invite what-you-know-about-me-completed-topic: whatyouknowaboutme.completed generate-file-topic: generate.file rabbitmq: @@ -46,8 +41,11 @@ queue: enable: false options: exchange: null - user-removal-topic: [ "user.remove" ] - user-touched-topic: [ "user.touch" ] + notify-topic: notification.notify + tenant-removal-topic: tenant.remove + tenant-touched-topic: tenant.touch + user-removal-topic: user.remove + user-touched-topic: user.touch rabbitmq: enable: false interval-seconds: 30 diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html new file mode 100644 index 000000000..7025e58bf --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

{reasonName} just made changes to the Description {name}.

+ + + + + + + +
+ + + + + + +
Click here to view it.
+
+ +
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/subject.en.txt new file mode 100644 index 000000000..440dc3c4f --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Description Modified \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html new file mode 100644 index 000000000..8c2ac8ab7 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html @@ -0,0 +1,305 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

You have been invited to co-develop the Template {templateName}.

+

Click the button to redirect to {templateName}.

+ + + + + + + +
+ + + + + + +
{templateName}
+
+ +
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/subject.en.txt new file mode 100644 index 000000000..f634a5493 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Description Template Invite \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/body.en.html new file mode 100644 index 000000000..f34f75c23 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

{reasonName} just finalised the Description {name}.

+ + + + + + + +
+ + + + + + +
Click here to view it.
+
+ +
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/subject.en.txt new file mode 100644 index 000000000..76e26cfec --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Description Finalised \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html new file mode 100644 index 000000000..c80220834 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

{reasonName} just publish the {name}.

+ + + + + + + +
+ + + + + + +
Click here to view it.
+
+ +
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/subject.en.txt new file mode 100644 index 000000000..5176c62fa --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Dmp Deposit \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html new file mode 100644 index 000000000..3e00fce2d --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

{reasonName} just finalised the Dmp {name}.

+ + + + + + + +
+ + + + + + +
Click here to view it.
+
+ +
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/subject.en.txt new file mode 100644 index 000000000..9332be920 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Dmp Finalised \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html new file mode 100644 index 000000000..75a586097 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

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

+

Click the button to redirect to {dmpname}.

+ + + + + + + +
+ + + + + + +
Join
+
+
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/subject.en.txt new file mode 100644 index 000000000..2c36d1524 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Data Management Plan Invite \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html new file mode 100644 index 000000000..7a36dccba --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

{reasonName} just made changes to the Dmp {name}.

+ + + + + + + +
+ + + + + + +
Click here to view it.
+
+ +
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/subject.en.txt new file mode 100644 index 000000000..cd9748bae --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Dmp Modified \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html new file mode 100644 index 000000000..bc5bfc087 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+ OpenDMP +

User {userName} have sent you a merge Request.

+

Please confirm that you want to merge your {installation-url} account with that account. +
The link will expire in {expiration_time}.

+ + + + + + +
+ + + + + + +
Confirm Merge Request
+
+
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/subject.en.txt new file mode 100644 index 000000000..3c52e9249 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Merge Account Confirmation \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html new file mode 100644 index 000000000..a43224531 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+ OpenDMP +

You have made a request to unlink your email account in ARGOS.

+

Please confirm that you want to unlink your {email} account. +
The link will expire in {expiration_time}.

+ + + + + + +
+ + + + + + +
Confirm Unlink Request
+
+
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/subject.en.txt new file mode 100644 index 000000000..e957d468f --- /dev/null +++ b/dmp-backend/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Unlink Email Confirmation \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/target/classes/config/application.yml b/dmp-backend/notification-service/notification-web/target/classes/config/application.yml index 4f9a66b6d..06b5f37c9 100644 --- a/dmp-backend/notification-service/notification-web/target/classes/config/application.yml +++ b/dmp-backend/notification-service/notification-web/target/classes/config/application.yml @@ -16,5 +16,6 @@ spring: optional:classpath:config/cors.yml[.yml], optional:classpath:config/cors-${spring.profiles.active}.yml[.yml], optional:file:../config/cors-${spring.profiles.active}.yml[.yml], optional:classpath:config/notification.yml[.yml], optional:classpath:config/notification-${spring.profiles.active}.yml[.yml], optional:file:../config/notification-${spring.profiles.active}.yml[.yml], optional:classpath:config/email.yml[.yml], optional:classpath:config/email-${spring.profiles.active}.yml[.yml], optional:file:../config/email-${spring.profiles.active}.yml[.yml], + optional:classpath:config/queue.yml[.yml], optional:classpath:config/queue-${spring.profiles.active}.yml[.yml], optional:file:../config/queue-${spring.profiles.active}.yml[.yml], optional:classpath:config/cipher.yml[.yml], optional:classpath:config/cipher-${spring.profiles.active}.yml[.yml], optional:file:../config/cipher-${spring.profiles.active}.yml[.yml], optional:classpath:config/formatting.yml[.yml], optional:classpath:config/formatting-${spring.profiles.active}.yml[.yml], optional:file:../config/formatting-${spring.profiles.active}.yml[.yml] 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 5c5e91151..7192cf334 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 @@ -16,7 +16,7 @@ notification: contacts: [ email ] - #dmpInvitationExistingUser type: 4904dea2-5079-46d3-83be-3a19c9ab45dc - contacts: [ email ] + contacts: [ inapp, email ] - #dpmModified type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB contacts: [ email ] @@ -314,6 +314,187 @@ notification: template-cache: prefix: ${CACHE_DISAMBIGUATION:} key-pattern: "{prefix}:Notification_Message_Email_Template:{key}:v0" + in-app: + flows: + - #dmpInvitationExistingUser + key: 4904dea2-5079-46d3-83be-3a19c9ab45dc + subject-path: classpath:notification_templates/dmpinvitationexistinguser/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpinvitationexistinguser/inapp/body.{language}.html + body-field-options: + mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{dmpname}]': null + '[{dmprole}]': null + '[{reasonName}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #dmpModified + key: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB + subject-path: classpath:notification_templates/dmpmodified/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpmodified/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #dmpFinalised + key: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E + subject-path: classpath:notification_templates/dmpfinalised/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpfinalised/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #desriptionModified + key: 4FDBFA80-7A71-4A69-B854-67CBB70648F1 + subject-path: classpath:notification_templates/descriptionmodified/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/descriptionmodified/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #descriptionFinalised + key: 33790bad-94d4-488a-8ee2-7f6295ca18ea + subject-path: classpath:notification_templates/descriptionfinalised/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/descriptionfinalised/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #mergeAccountConfirmation + key: BFE68845-CB05-4C5A-A03D-29161A7C9660 + subject-path: classpath:notification_templates/mergeacountconfirmation/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/mergeacountconfirmation/inapp/body.{language}.html + body-field-options: + mandatory: [ "{userName}", "{installation-url}", "{confirmationToken}" ] + optional: + - key: "{expiration_time}" + value: --- + formatting: + '[{userName}]': null + '[{installation-url}]': null + '[{confirmationToken}]': null + '[{expiration_time}]': null + priority-key: null + cipher-fields: [ ] + - #removeCredentialConfirmation + key: C9BC3F16-057E-4BBA-8A5F-36BD835E5604 + subject-path: classpath:notification_templates/removecredentialconfirmation/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ "{installation-url}", "{confirmationToken}" ] + optional: [ ] + body-path: classpath:notification_templates/removecredentialconfirmation/inapp/body.{language}.html + body-field-options: + mandatory: [ ] + optional: + - key: "{email}" + value: email + - key: "{expiration_time}" + value: -- + formatting: + '[{email}]': null + '[{expiration_time}]': null + priority-key: null + cipher-fields: [ ] + - #dmpDeposit + key: 55736F7A-83AB-4190-AF43-9D031A6F9612 + subject-path: classpath:notification_templates/dmpdeposit/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/dmpdeposit/inapp/body.{language}.html + body-field-options: + mandatory: [ "{reasonName}", "{name}", "{installation-url}", "{id}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{reasonName}]': null + '[{name}]': null + '[{installation-url}]': null + '[{id}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + - #descriptionTemplateInvitation + key: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B + subject-path: classpath:notification_templates/descriptiontemplateinvitation/inapp/subject.{language}.txt + subject-field-options: + mandatory: [ ] + optional: [ ] + body-path: classpath:notification_templates/descriptiontemplateinvitation/inapp/body.{language}.html + body-field-options: + mandatory: [ "{templateName}", "{installation-url}", "{templateID}" ] + optional: + - key: "{recipient}" + value: + formatting: + '[{templateName}]': null + '[{installation-url}]': null + '[{templateID}]': null + '[{recipient}]': null + priority-key: null + cipher-fields: [ ] + template-cache: + prefix: ${CACHE_DISAMBIGUATION:} + key-pattern: "{prefix}:Notification_Message_InApp_Template:{key}:v0" override-cache: template-cache: prefix: ${CACHE_DISAMBIGUATION:} 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 1bc742f5f..e93f4f3af 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 @@ -75,18 +75,22 @@ permissions: #Notification BrowseNotification: roles: - - ic-sti-superuser - - user + - Admin clients: [ ] allowAnonymous: true allowAuthenticated: false EditNotification: roles: - - ic-sti-superuser - - user + - Admin clients: [ ] allowAnonymous: true allowAuthenticated: false + DeleteNotification: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false #Tenant Configuration BrowseTenantConfiguration: roles: @@ -156,6 +160,20 @@ permissions: allowAnonymous: false allowAuthenticated: false DeleteNotificationTemplate: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + + # In App Notification Permissions + BrowseInAppNotification: + roles: + - Admin + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + DeleteInAppNotification: roles: - Admin clients: [ ] diff --git a/dmp-backend/notification-service/notification-web/target/classes/config/queue-devel.yml b/dmp-backend/notification-service/notification-web/target/classes/config/queue-devel.yml index f0e31766d..1c761d9e5 100644 --- a/dmp-backend/notification-service/notification-web/target/classes/config/queue-devel.yml +++ b/dmp-backend/notification-service/notification-web/target/classes/config/queue-devel.yml @@ -1,5 +1,6 @@ queue: rabbitmq: + enable: true durable: true queue: cite_dmp_devel_notification_inbox_queue exchange: cite_dmp_devel_queue @@ -7,12 +8,14 @@ queue: publisherEnabled: true task: publisher: + enable: true options: exchange: cite_dmp_devel_queue rabbitmq: enable: true listener: + enable: true options: exchange: cite_dmp_devel_queue rabbitmq: - enable: false + enable: true diff --git a/dmp-backend/notification-service/notification-web/target/classes/config/queue.yml b/dmp-backend/notification-service/notification-web/target/classes/config/queue.yml index 2886f369a..a61881d7d 100644 --- a/dmp-backend/notification-service/notification-web/target/classes/config/queue.yml +++ b/dmp-backend/notification-service/notification-web/target/classes/config/queue.yml @@ -26,11 +26,6 @@ queue: options: exchange: null forget-me-completed-topic: forgetme.completed - notify-topic: notification.notify - tenant-reactivation-topic: tenant.reactivated - tenant-removal-topic: tenant.remove - tenant-touch-topic: tenant.touch - tenant-user-invite-topic: tenant.invite what-you-know-about-me-completed-topic: whatyouknowaboutme.completed generate-file-topic: generate.file rabbitmq: @@ -46,8 +41,11 @@ queue: enable: false options: exchange: null - user-removal-topic: [ "user.remove" ] - user-touched-topic: [ "user.touch" ] + notify-topic: notification.notify + tenant-removal-topic: tenant.remove + tenant-touched-topic: tenant.touch + user-removal-topic: user.remove + user-touched-topic: user.touch rabbitmq: enable: false interval-seconds: 30 diff --git a/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/inapp/body.en.html b/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/inapp/body.en.html new file mode 100644 index 000000000..75a586097 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/inapp/body.en.html @@ -0,0 +1,304 @@ + + + + + + Simple Transactional Email + + + + + + + + + +
  +
+ + + This is preheader text. Some clients will show this text as a preview. + + + + + + + + +
+ + + + +
+

Dear {recipient},

+

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

+

Click the button to redirect to {dmpname}.

+ + + + + + + +
+ + + + + + +
Join
+
+
+
+ + + + + + +
+
 
+ + \ No newline at end of file diff --git a/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/inapp/subject.en.txt b/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/inapp/subject.en.txt new file mode 100644 index 000000000..2c36d1524 --- /dev/null +++ b/dmp-backend/notification-service/notification-web/target/classes/notification_templates/dmpinvitationexistinguser/inapp/subject.en.txt @@ -0,0 +1 @@ +ARGOS - Data Management Plan Invite \ No newline at end of file diff --git a/dmp-backend/notification-service/notification/pom.xml b/dmp-backend/notification-service/notification/pom.xml index b5e71bb6a..50ba3238f 100644 --- a/dmp-backend/notification-service/notification/pom.xml +++ b/dmp-backend/notification-service/notification/pom.xml @@ -7,16 +7,17 @@ gr.cite notification-service-parent 1.0.0 - ../pom.xml + ../../notification-service/pom.xml notification - 1.0.0 + 11 11 11 + org.springframework.boot @@ -45,16 +46,11 @@ poi-ooxml 5.2.2 - - - javax.persistence - javax.persistence-api - gr.cite data-tools - 1.0.0 + 2.1.2 gr.cite @@ -84,16 +80,14 @@ gr.cite validation - 1.0.0 + 2.1.0 + com.fasterxml.jackson.datatype jackson-datatype-jsr310 - - org.springframework - spring-web - + gr.cite cipher 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 dee3f5110..0ad1baed7 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 @@ -9,6 +9,16 @@ public class AuditableAction { public static final EventId User_Available_Notifiers_Query = new EventId(10004, "User_Available_Notifiers_Query"); + public static final EventId User_Query = new EventId(11000, "User_Query"); + public static final EventId User_Lookup = new EventId(11001, "User_Lookup"); + public static final EventId User_Persist = new EventId(11002, "User_Persist"); + public static final EventId User_Delete = new EventId(11003, "User_Delete"); + + public static final EventId Tenant_Query = new EventId(12000, "Tenant_Query"); + public static final EventId Tenant_Lookup = new EventId(12001, "Tenant_Lookup"); + public static final EventId Tenant_Persist = new EventId(12002, "Tenant_Persist"); + public static final EventId Tenant_Delete = new EventId(12003, "Tenant_Delete"); + public static final EventId Notification_Query = new EventId(19000, "Notification_Query"); public static final EventId Notification_Lookup = new EventId(19001, "Notification_Lookup"); public static final EventId Notification_Persist = new EventId(19002, "Notification_Persist"); 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 bd4f8494b..59b247dec 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 @@ -34,6 +34,10 @@ public final class Permission { public static String EditNotificationTemplate = "EditNotificationTemplate"; public static String DeleteNotificationTemplate = "DeleteNotificationTemplate"; + //InApp Notification + public static final String BrowseInAppNotification = "BrowseInAppNotification"; + public static String DeleteInAppNotification = "DeleteInAppNotification"; + // 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/XmlHandlingService.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/XmlHandlingService.java index e6b4b991e..cec063abf 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/XmlHandlingService.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/XmlHandlingService.java @@ -10,10 +10,10 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.management.InvalidApplicationException; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationContactType.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationContactType.java index 778358983..8b30d02e7 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationContactType.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/enums/NotificationContactType.java @@ -3,29 +3,28 @@ package gr.cite.notification.common.enums; import com.fasterxml.jackson.annotation.JsonValue; import gr.cite.notification.data.conventers.DatabaseEnum; -import java.util.HashMap; import java.util.Map; public enum NotificationContactType implements DatabaseEnum { - EMAIL((short)0), - SLACK_BROADCAST((short)1), - SMS((short)2), - IN_APP((short)3); + EMAIL((short) 0), + SLACK_BROADCAST((short) 1), + SMS((short) 2), + IN_APP((short) 3); - private final Short value; + private final Short value; - NotificationContactType(Short value) { - this.value = value; - } + NotificationContactType(Short value) { + this.value = value; + } - @JsonValue - public Short getValue() { - return value; - } + @JsonValue + public Short getValue() { + return value; + } - private static final Map map = EnumUtils.getEnumValueMap(NotificationContactType.class); + private static final Map map = EnumUtils.getEnumValueMap(NotificationContactType.class); - public static NotificationContactType of(Short i) { - return map.get(i); - } + public static NotificationContactType of(Short i) { + return map.get(i); + } } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java index 34e102280..99111183a 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java @@ -13,7 +13,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; import javax.management.InvalidApplicationException; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import java.util.UUID; @Component diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantConfigEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantConfigEntity.java index 6a13dbd50..4d5a0a7db 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantConfigEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantConfigEntity.java @@ -1,10 +1,10 @@ package gr.cite.notification.common.types.tenant; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "config") @XmlAccessorType(XmlAccessType.FIELD) diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantDepositConfigEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantDepositConfigEntity.java index e4b02bd46..f2498eada 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantDepositConfigEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantDepositConfigEntity.java @@ -1,6 +1,6 @@ package gr.cite.notification.common.types.tenant; -import javax.xml.bind.annotation.*; +import jakarta.xml.bind.annotation.*; import java.util.List; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantFileTransformersConfigEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantFileTransformersConfigEntity.java index bd1e3409b..e661197d7 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantFileTransformersConfigEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantFileTransformersConfigEntity.java @@ -1,6 +1,6 @@ package gr.cite.notification.common.types.tenant; -import javax.xml.bind.annotation.*; +import jakarta.xml.bind.annotation.*; import java.util.List; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantSourceEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantSourceEntity.java index 6c8ccf4b3..5871f2c0e 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantSourceEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/types/tenant/TenantSourceEntity.java @@ -1,6 +1,6 @@ package gr.cite.notification.common.types.tenant; -import javax.xml.bind.annotation.*; +import jakarta.xml.bind.annotation.*; import java.util.List; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/EnumNotNull.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/EnumNotNull.java index 111523d6e..9b6cc2a3f 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/EnumNotNull.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/EnumNotNull.java @@ -1,7 +1,7 @@ package gr.cite.notification.common.validation; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class EnumNotNull implements ConstraintValidator { @Override diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSet.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSet.java index ad2fd2fa9..23b812d12 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSet.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSet.java @@ -1,8 +1,8 @@ package gr.cite.notification.common.validation; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.*; @Constraint( validatedBy = { FieldNotNullIfOtherSetValidator.class } ) diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSetValidator.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSetValidator.java index b12b3eaf7..dc537b9d0 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSetValidator.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldNotNullIfOtherSetValidator.java @@ -2,8 +2,8 @@ package gr.cite.notification.common.validation; import org.springframework.beans.BeanWrapperImpl; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; import java.util.Objects; public class FieldNotNullIfOtherSetValidator implements ConstraintValidator { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatch.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatch.java index 872fdb55a..3935b5f7e 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatch.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatch.java @@ -1,7 +1,7 @@ package gr.cite.notification.common.validation; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatchValidator.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatchValidator.java index 6f1a4cde0..15097deb8 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatchValidator.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/FieldsValueMatchValidator.java @@ -2,8 +2,8 @@ package gr.cite.notification.common.validation; import org.springframework.beans.BeanWrapperImpl; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class FieldsValueMatchValidator implements ConstraintValidator { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidEnum.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidEnum.java index b48e7c503..5c3002235 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidEnum.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidEnum.java @@ -1,7 +1,7 @@ package gr.cite.notification.common.validation; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidId.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidId.java index ed0240c5e..8fa3989fa 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidId.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidId.java @@ -1,8 +1,8 @@ package gr.cite.notification.common.validation; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.*; @Constraint( validatedBy = { ValidIdValidator.class } ) diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidIdValidator.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidIdValidator.java index 729c032ff..c1ce3886c 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidIdValidator.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidIdValidator.java @@ -3,8 +3,8 @@ package gr.cite.notification.common.validation; import gr.cite.notification.convention.ConventionService; import org.springframework.beans.factory.annotation.Autowired; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; import java.util.UUID; public class ValidIdValidator implements ConstraintValidator { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidationServiceImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidationServiceImpl.java index b6ebb716a..47e0b807b 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidationServiceImpl.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/common/validation/ValidationServiceImpl.java @@ -8,7 +8,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; -import javax.validation.Validator; +import jakarta.validation.Validator; import java.util.List; import java.util.Map; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/email/EmailProperties.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/email/EmailProperties.java index 9f57df829..505b2bd96 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/email/EmailProperties.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/email/EmailProperties.java @@ -1,11 +1,10 @@ package gr.cite.notification.config.email; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.ConstructorBinding; -@ConstructorBinding @ConfigurationProperties(prefix = "email") public class EmailProperties { + private final String address; public EmailProperties(String address) { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/formatting/FormattingServiceProperties.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/formatting/FormattingServiceProperties.java index 9366026c3..39f517869 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/formatting/FormattingServiceProperties.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/formatting/FormattingServiceProperties.java @@ -1,38 +1,38 @@ package gr.cite.notification.config.formatting; - import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.ConstructorBinding; -@ConstructorBinding @ConfigurationProperties(prefix = "formatting.options") public class FormattingServiceProperties { - private final String integerFormat; - private final String decimalFormat; - private final String dateTimeFormat; - private final Integer decimalDigitsRound; + private final String integerFormat; - public FormattingServiceProperties(String integerFormat, String decimalFormat, String dateTimeFormat, Integer decimalDigitsRound) { - this.integerFormat = integerFormat; - this.decimalFormat = decimalFormat; - this.dateTimeFormat = dateTimeFormat; - this.decimalDigitsRound = decimalDigitsRound; - } + private final String decimalFormat; - public String getIntegerFormat() { - return integerFormat; - } + private final String dateTimeFormat; - public String getDecimalFormat() { - return decimalFormat; - } + private final Integer decimalDigitsRound; - public String getDateTimeFormat() { - return dateTimeFormat; - } + public FormattingServiceProperties(String integerFormat, String decimalFormat, String dateTimeFormat, Integer decimalDigitsRound) { + this.integerFormat = integerFormat; + this.decimalFormat = decimalFormat; + this.dateTimeFormat = dateTimeFormat; + this.decimalDigitsRound = decimalDigitsRound; + } - public Integer getDecimalDigitsRound() { - return decimalDigitsRound; - } + public String getIntegerFormat() { + return integerFormat; + } + + public String getDecimalFormat() { + return decimalFormat; + } + + public String getDateTimeFormat() { + return dateTimeFormat; + } + + public Integer getDecimalDigitsRound() { + return decimalDigitsRound; + } } \ No newline at end of file diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationConfig.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationConfig.java index d757deb02..5ede51cd9 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationConfig.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationConfig.java @@ -5,6 +5,7 @@ import gr.cite.notification.schedule.NotificationScheduleTask; import gr.cite.notification.service.message.common.MessageBuilderBase; import gr.cite.notification.service.notificationscheduling.NotificationSchedulingService; import gr.cite.notification.service.notificationscheduling.NotificationSchedulingServiceImpl; +import gr.cite.queueinbox.task.rabbitmq.QueueListenerProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -32,11 +33,13 @@ public class NotificationConfig { } private final ApplicationContext applicationContext; private final NotificationProperties properties; + private final QueueListenerProperties queueListenerProperties; @Autowired - public NotificationConfig(ApplicationContext applicationContext, NotificationProperties properties) { + public NotificationConfig(ApplicationContext applicationContext, NotificationProperties properties, QueueListenerProperties queueListenerProperties) { this.applicationContext = applicationContext; this.properties = properties; + this.queueListenerProperties = queueListenerProperties; } @Bean(BeanQualifier.GLOBAL_POLICIES_MAP) diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationProperties.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationProperties.java index f8a4e75af..1e963fcd7 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationProperties.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/config/notification/NotificationProperties.java @@ -1,348 +1,385 @@ package gr.cite.notification.config.notification; -import gr.cite.notification.common.enums.NotificationContactType; import gr.cite.notification.common.enums.EmailOverrideMode; +import gr.cite.notification.common.enums.NotificationContactType; import gr.cite.notification.common.types.notification.FieldInfo; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.ConstructorBinding; import java.util.List; import java.util.Map; import java.util.UUID; -@ConstructorBinding @ConfigurationProperties(prefix = "notification") public class NotificationProperties { - private final Task task; - private final Resolver resolver; - private final Map message; - private final Template overrideCache; - private final StaticFieldItems staticFields; - - public NotificationProperties(Task task, Resolver resolver, Map message, Template overrideCache, StaticFieldItems staticFields) { - this.task = task; - this.resolver = resolver; - this.message = message; - this.overrideCache = overrideCache; - this.staticFields = staticFields; - } - - public Task getTask() { - return task; - } - - public Resolver getResolver() { - return resolver; - } - - public Map getMessage() { - return message; - } - - public Template getOverrideCache() { - return overrideCache; - } - - public StaticFieldItems getStaticFields() { - return staticFields; - } - - public static class Task { - private final Processor processor; - - public Task(Processor processor) { - this.processor = processor; - } - - public Processor getProcessor() { - return processor; - } - - public static class Processor { - private final Boolean enable; - private final Long intervalSeconds; - private final Options options; - private final List overrides; - - public Processor(Boolean enable, Long intervalSeconds, Options options, List overrides) { - this.enable = enable; - this.intervalSeconds = intervalSeconds; - this.options = options; - this.overrides = overrides; - } - - public Boolean getEnable() { - return enable; - } - - public Long getIntervalSeconds() { - return intervalSeconds; - } - - public Options getOptions() { - return options; - } - - public List getOverrides() { - return overrides; - } - - public static class Options { - private final Long retryThreshold; - private final Long maxRetryDelaySeconds; - private final Long tooOldToSendSeconds; - private final Long tooOldToTrackSeconds; - - public Options(Long retryThreshold, Long maxRetryDelaySeconds, Long tooOldToSendSeconds, Long tooOldToTrackSeconds) { - this.retryThreshold = retryThreshold; - this.maxRetryDelaySeconds = maxRetryDelaySeconds; - this.tooOldToSendSeconds = tooOldToSendSeconds; - this.tooOldToTrackSeconds = tooOldToTrackSeconds; - } - - public Long getRetryThreshold() { - return retryThreshold; - } - - public Long getMaxRetryDelaySeconds() { - return maxRetryDelaySeconds; - } - - public Long getTooOldToSendSeconds() { - return tooOldToSendSeconds; - } - - public Long getTooOldToTrackSeconds() { - return tooOldToTrackSeconds; - } - } - } - } - - public static class Resolver { - private final List globalPolicies; - - public Resolver(List globalPolicies) { - this.globalPolicies = globalPolicies; - } - - public List getGlobalPolicies() { - return globalPolicies; - } - - public static class GlobalPolicy { - private final UUID type; - private final List contacts; - - public GlobalPolicy(UUID type, List contacts) { - this.type = type; - this.contacts = contacts; - } - - public UUID getType() { - return type; - } - - public List getContacts() { - return contacts; - } - } - } - - public static class Template { - private final TemplateCache templateCache; - - private final List flows; - - public Template(TemplateCache templateCache, List flows) { - this.templateCache = templateCache; - this.flows = flows; - } - - public TemplateCache getTemplateCache() { - return templateCache; - } - - - public List getFlows() { - return flows; - } - - public static class TemplateCache { - private final String prefix; - private final String keyPattern; - - public TemplateCache(String prefix, String keyPattern) { - this.prefix = prefix; - this.keyPattern = keyPattern; - } - - public String getPrefix() { - return prefix; - } - - public String getKeyPattern() { - return keyPattern; - } - } - } - - public static class StaticFieldItems { - private final List Fields; - - public StaticFieldItems(List fields) { - Fields = fields; - } - - public List getFields() { - return Fields; - } - } - - public static class Field { - private final String key; - private final String type; - private final String value; - - public Field(String key, String type, String value) { - this.key = key; - this.type = type; - this.value = value; - } - - public String getKey() { - return key; - } - - public String getType() { - return type; - } - - public String getValue() { - return value; - } - } - - public static class Flow { - private final UUID key; - private final String subjectPath; - private final String subjectKey; - private final FieldOption subjectFieldOptions; - private final String bodyPath; - private final String bodyKey; - private final FieldOption bodyFieldOptions; - private final List cc; - private final EmailOverrideMode ccMode; - private final List bcc; - private final EmailOverrideMode bccMode; - private final Boolean allowAttachments; - private final List cipherFields; - private final String priorityKey; - private final List extraDataKeys; - - public Flow(UUID key, String subjectPath, String subjectKey, FieldOption subjectFieldOptions, String bodyPath, String bodyKey, FieldOption bodyFieldOptions, List cc, EmailOverrideMode ccMode, List bcc, EmailOverrideMode bccMode, Boolean allowAttachments, List cipherFields, String priorityKey, List extraDataKeys) { - this.key = key; - this.subjectPath = subjectPath; - this.subjectKey = subjectKey; - this.subjectFieldOptions = subjectFieldOptions; - this.bodyPath = bodyPath; - this.bodyKey = bodyKey; - this.bodyFieldOptions = bodyFieldOptions; - this.cc = cc; - this.ccMode = ccMode; - this.bcc = bcc; - this.bccMode = bccMode; - this.allowAttachments = allowAttachments; - this.cipherFields = cipherFields; - this.priorityKey = priorityKey; - this.extraDataKeys = extraDataKeys; - } - - public UUID getKey() { - return key; - } - - public String getSubjectPath() { - return subjectPath; - } - - public String getSubjectKey() { - return subjectKey; - } - - public FieldOption getSubjectFieldOptions() { - return subjectFieldOptions; - } - - public String getBodyPath() { - return bodyPath; - } - - public String getBodyKey() { - return bodyKey; - } - - public FieldOption getBodyFieldOptions() { - return bodyFieldOptions; - } - - public List getCc() { - return cc; - } - - public EmailOverrideMode getCcMode() { - return ccMode; - } - - public List getBcc() { - return bcc; - } - - public EmailOverrideMode getBccMode() { - return bccMode; - } - - public Boolean getAllowAttachments() { - return allowAttachments; - } - - public List getCipherFields() { - return cipherFields; - } - - public String getPriorityKey() { - return priorityKey; - } - - public List getExtraDataKeys() { - return extraDataKeys; - } - - public static class FieldOption { - private final List mandatory; - private final List optional; - - private final Map formatting; - - public FieldOption(List mandatory, List optional, Map formatting) { - this.mandatory = mandatory; - this.optional = optional; - this.formatting = formatting; - } - - public List getMandatory() { - return mandatory; - } - - public List getOptional() { - return optional; - } - - public Map getFormatting() { - return formatting; - } - - } - } + private final Task task; + + private final Resolver resolver; + + private final Map message; + + private final Template overrideCache; + + private final StaticFieldItems staticFields; + + public NotificationProperties(Task task, Resolver resolver, Map message, Template overrideCache, StaticFieldItems staticFields) { + this.task = task; + this.resolver = resolver; + this.message = message; + this.overrideCache = overrideCache; + this.staticFields = staticFields; + } + + public Task getTask() { + return task; + } + + public Resolver getResolver() { + return resolver; + } + + public Map getMessage() { + return message; + } + + public Template getOverrideCache() { + return overrideCache; + } + + public StaticFieldItems getStaticFields() { + return staticFields; + } + + public static class Task { + + private final Processor processor; + + public Task(Processor processor) { + this.processor = processor; + } + + public Processor getProcessor() { + return processor; + } + + public static class Processor { + + private final Boolean enable; + + private final Long intervalSeconds; + + private final Options options; + + private final List overrides; + + public Processor(Boolean enable, Long intervalSeconds, Options options, List overrides) { + this.enable = enable; + this.intervalSeconds = intervalSeconds; + this.options = options; + this.overrides = overrides; + } + + public Boolean getEnable() { + return enable; + } + + public Long getIntervalSeconds() { + return intervalSeconds; + } + + public Options getOptions() { + return options; + } + + public List getOverrides() { + return overrides; + } + + public static class Options { + + private final Long retryThreshold; + + private final Long maxRetryDelaySeconds; + + private final Long tooOldToSendSeconds; + + private final Long tooOldToTrackSeconds; + + public Options(Long retryThreshold, Long maxRetryDelaySeconds, Long tooOldToSendSeconds, Long tooOldToTrackSeconds) { + this.retryThreshold = retryThreshold; + this.maxRetryDelaySeconds = maxRetryDelaySeconds; + this.tooOldToSendSeconds = tooOldToSendSeconds; + this.tooOldToTrackSeconds = tooOldToTrackSeconds; + } + + public Long getRetryThreshold() { + return retryThreshold; + } + + public Long getMaxRetryDelaySeconds() { + return maxRetryDelaySeconds; + } + + public Long getTooOldToSendSeconds() { + return tooOldToSendSeconds; + } + + public Long getTooOldToTrackSeconds() { + return tooOldToTrackSeconds; + } + } + } + } + + public static class Resolver { + + private final List globalPolicies; + + public Resolver(List globalPolicies) { + this.globalPolicies = globalPolicies; + } + + public List getGlobalPolicies() { + return globalPolicies; + } + + public static class GlobalPolicy { + + private final UUID type; + + private final List contacts; + + public GlobalPolicy(UUID type, List contacts) { + this.type = type; + this.contacts = contacts; + } + + public UUID getType() { + return type; + } + + public List getContacts() { + return contacts; + } + } + } + + public static class Template { + + private final TemplateCache templateCache; + + private final List flows; + + public Template(TemplateCache templateCache, List flows) { + this.templateCache = templateCache; + this.flows = flows; + } + + public TemplateCache getTemplateCache() { + return templateCache; + } + + public List getFlows() { + return flows; + } + + public static class TemplateCache { + + private final String prefix; + + private final String keyPattern; + + public TemplateCache(String prefix, String keyPattern) { + this.prefix = prefix; + this.keyPattern = keyPattern; + } + + public String getPrefix() { + return prefix; + } + + public String getKeyPattern() { + return keyPattern; + } + } + } + + public static class StaticFieldItems { + + private final List Fields; + + public StaticFieldItems(List fields) { + Fields = fields; + } + + public List getFields() { + return Fields; + } + } + + public static class Field { + + private final String key; + + private final String type; + + private final String value; + + public Field(String key, String type, String value) { + this.key = key; + this.type = type; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getType() { + return type; + } + + public String getValue() { + return value; + } + } + + public static class Flow { + + private final UUID key; + + private final String subjectPath; + + private final String subjectKey; + + private final FieldOption subjectFieldOptions; + + private final String bodyPath; + + private final String bodyKey; + + private final FieldOption bodyFieldOptions; + + private final List cc; + + private final EmailOverrideMode ccMode; + + private final List bcc; + + private final EmailOverrideMode bccMode; + + private final Boolean allowAttachments; + + private final List cipherFields; + + private final String priorityKey; + + private final List extraDataKeys; + + public Flow(UUID key, String subjectPath, String subjectKey, FieldOption subjectFieldOptions, String bodyPath, String bodyKey, FieldOption bodyFieldOptions, List cc, EmailOverrideMode ccMode, List bcc, EmailOverrideMode bccMode, Boolean allowAttachments, List cipherFields, String priorityKey, List extraDataKeys) { + this.key = key; + this.subjectPath = subjectPath; + this.subjectKey = subjectKey; + this.subjectFieldOptions = subjectFieldOptions; + this.bodyPath = bodyPath; + this.bodyKey = bodyKey; + this.bodyFieldOptions = bodyFieldOptions; + this.cc = cc; + this.ccMode = ccMode; + this.bcc = bcc; + this.bccMode = bccMode; + this.allowAttachments = allowAttachments; + this.cipherFields = cipherFields; + this.priorityKey = priorityKey; + this.extraDataKeys = extraDataKeys; + } + + public UUID getKey() { + return key; + } + + public String getSubjectPath() { + return subjectPath; + } + + public String getSubjectKey() { + return subjectKey; + } + + public FieldOption getSubjectFieldOptions() { + return subjectFieldOptions; + } + + public String getBodyPath() { + return bodyPath; + } + + public String getBodyKey() { + return bodyKey; + } + + public FieldOption getBodyFieldOptions() { + return bodyFieldOptions; + } + + public List getCc() { + return cc; + } + + public EmailOverrideMode getCcMode() { + return ccMode; + } + + public List getBcc() { + return bcc; + } + + public EmailOverrideMode getBccMode() { + return bccMode; + } + + public Boolean getAllowAttachments() { + return allowAttachments; + } + + public List getCipherFields() { + return cipherFields; + } + + public String getPriorityKey() { + return priorityKey; + } + + public List getExtraDataKeys() { + return extraDataKeys; + } + + public static class FieldOption { + + private final List mandatory; + + private final List optional; + + private final Map formatting; + + public FieldOption(List mandatory, List optional, Map formatting) { + this.mandatory = mandatory; + this.optional = optional; + this.formatting = formatting; + } + + public List getMandatory() { + return mandatory; + } + + public List getOptional() { + return optional; + } + + public Map getFormatting() { + return formatting; + } + + } + } } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/InAppNotificationEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/InAppNotificationEntity.java index ac42461f6..2fdb75a32 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/InAppNotificationEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/InAppNotificationEntity.java @@ -8,7 +8,7 @@ import gr.cite.notification.data.conventers.IsActiveConverter; import gr.cite.notification.data.conventers.NotificationInAppTrackingConverter; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; @@ -16,58 +16,57 @@ import java.util.UUID; @Table(name = "\"ntf_InAppNotification\"") public class InAppNotificationEntity extends TenantScopedBaseEntity { public static class Field { - public static final String ID = "id"; - public static final String USER_ID = "userId"; - public static final String IS_ACTIVE = "isActive"; - public static final String TYPE = "type"; - public static final String READ_TIME = "readTime"; - public static final String TRACKING_STATE = "trackingState"; - public static final String PRIORITY = "priority"; - public static final String SUBJECT = "subject"; - public static final String BODY = "body"; - public static final String EXTRA_DATA = "extraData"; - public static final String CREATED_AT = "createdAt"; - public static final String UPDATED_AT = "updatedAt"; + public static final String _id = "id"; + public static final String _userId = "userId"; + public static final String _isActive = "isActive"; + public static final String _type = "type"; + public static final String _readTime = "readTime"; + public static final String _trackingState = "trackingState"; + public static final String _priority = "priority"; + public static final String _subject = "subject"; + public static final String _body = "body"; + public static final String _extraData = "extraData"; + public static final String _createdAt = "createdAt"; + public static final String _updatedAt = "updatedAt"; } @Id - @Column(name = "id", columnDefinition = "uuid", nullable = false) + @Column(name = "\"id\"", columnDefinition = "uuid", nullable = false) private UUID id; - - @Column(name = "user", columnDefinition = "uuid", nullable = false) + @Column(name = "\"user\"", columnDefinition = "uuid", nullable = false) private UUID userId; - @Column(name = "is_active", nullable = false) + @Column(name = "\"is_active\"", nullable = false) @Convert(converter = IsActiveConverter.class) private IsActive isActive; - @Column(name = "type", columnDefinition = "uuid", nullable = false) + @Column(name = "\"type\"", columnDefinition = "uuid", nullable = false) private UUID type; - @Column(name = "read_time") + @Column(name = "\"read_time\"") private Instant readTime; - @Column(name = "tracking_state", nullable = false) + @Column(name = "\"tracking_state\"", nullable = false) @Convert(converter = NotificationInAppTrackingConverter.class) private NotificationInAppTracking trackingState; - @Column(name = "priority", nullable = false) + @Column(name = "\"priority\"", nullable = false) @Convert(converter = InAppNotificationPriorityConverter.class) private InAppNotificationPriority priority; - @Column(name = "subject") + @Column(name = "\"subject\"") private String subject; - @Column(name = "body") + @Column(name = "\"body\"") private String body; - @Column(name = "extra_data") + @Column(name = "\"extra_data\"") private String extraData; - @Column(name = "created_at", nullable = false) + @Column(name = "\"created_at\"", nullable = false) private Instant createdAt; - @Column(name = "updated_at", nullable = false) + @Column(name = "\"updated_at\"", nullable = false) @Version private Instant updatedAt; 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 index cbd2f4e8d..3c8d8f4bf 100644 --- 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 @@ -4,7 +4,7 @@ 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 jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationEntity.java index f4925acbc..b6fee25a3 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/NotificationEntity.java @@ -4,7 +4,7 @@ import gr.cite.notification.common.enums.*; import gr.cite.notification.data.conventers.*; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; 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 index 393794885..6e7db21c1 100644 --- 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 @@ -4,7 +4,7 @@ import gr.cite.notification.common.enums.*; import gr.cite.notification.data.conventers.*; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueInboxEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueInboxEntity.java index ac0cf52ce..9fee15112 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueInboxEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueInboxEntity.java @@ -5,7 +5,7 @@ import gr.cite.notification.data.conventers.IsActiveConverter; import gr.cite.queueinbox.entity.QueueInbox; import gr.cite.queueinbox.entity.QueueInboxStatus; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueOutboxEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueOutboxEntity.java index 4ebf0a938..a5dac204d 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueOutboxEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/QueueOutboxEntity.java @@ -6,7 +6,7 @@ import gr.cite.notification.data.conventers.IsActiveConverter; import gr.cite.queueoutbox.entity.QueueOutbox; import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantConfigurationEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantConfigurationEntity.java index b7744dd08..2377a11d5 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantConfigurationEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantConfigurationEntity.java @@ -6,7 +6,7 @@ import gr.cite.notification.data.conventers.IsActiveConverter; import gr.cite.notification.data.conventers.TenantConfigurationTypeConverter; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantEntity.java index 74bb43f5e..297da6dc1 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantEntity.java @@ -3,7 +3,7 @@ package gr.cite.notification.data; import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.data.conventers.IsActiveConverter; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantScopedEntityManager.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantScopedEntityManager.java index 4426b514b..b5c1a866f 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantScopedEntityManager.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantScopedEntityManager.java @@ -8,12 +8,12 @@ import gr.cite.tools.exception.MyForbiddenException; import org.hibernate.Session; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; -import org.springframework.web.context.annotation.RequestScope; import javax.management.InvalidApplicationException; -import javax.persistence.EntityManager; -import javax.persistence.FlushModeType; -import javax.persistence.PersistenceContext; +import jakarta.persistence.EntityManager; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Query; import java.util.UUID; @Service @@ -39,6 +39,9 @@ public class TenantScopedEntityManager { Session session = this.entityManager.unwrap(Session.class); session.setJdbcBatchSize(size); } + public Query createQuery(String query){ + return this.entityManager.createQuery(query); + } public void persist(Object entity) { this.entityManager.persist(entity); } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantUserEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantUserEntity.java index a0823546d..257689196 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantUserEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/TenantUserEntity.java @@ -4,7 +4,7 @@ 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 jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserContactInfoEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserContactInfoEntity.java index 678d3aa78..08a8da048 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserContactInfoEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserContactInfoEntity.java @@ -4,7 +4,7 @@ import gr.cite.notification.common.enums.ContactInfoType; import gr.cite.notification.data.conventers.ContactInfoTypeConverter; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserCredentialEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserCredentialEntity.java index ebd5b44f1..ca4053893 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserCredentialEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserCredentialEntity.java @@ -3,7 +3,7 @@ package gr.cite.notification.data; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserEntity.java index 20b69be02..fd38203ed 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserEntity.java @@ -3,7 +3,7 @@ package gr.cite.notification.data; import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.data.conventers.IsActiveConverter; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserNotificationPreferenceEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserNotificationPreferenceEntity.java index 05d1e149c..331f22523 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserNotificationPreferenceEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserNotificationPreferenceEntity.java @@ -5,7 +5,7 @@ import gr.cite.notification.data.composite.CompositeUserNotificationPreferenceId import gr.cite.notification.data.conventers.NotificationContactTypeConverter; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserRoleEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserRoleEntity.java index 1a4cbc9c2..cbc808350 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserRoleEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/UserRoleEntity.java @@ -3,7 +3,7 @@ package gr.cite.notification.data; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/ContactInfoTypeConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/ContactInfoTypeConverter.java index 5a2859c6f..76617646e 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/ContactInfoTypeConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/ContactInfoTypeConverter.java @@ -2,7 +2,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.ContactInfoType; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class ContactInfoTypeConverter extends DatabaseEnumConverter{ diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/DatabaseEnumConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/DatabaseEnumConverter.java index 0962df9fc..6cb0dd82c 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/DatabaseEnumConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/DatabaseEnumConverter.java @@ -1,8 +1,8 @@ package gr.cite.notification.data.conventers; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; @Converter public abstract class DatabaseEnumConverter, T> implements AttributeConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/InAppNotificationPriorityConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/InAppNotificationPriorityConverter.java index 6bc531660..42a43d3b1 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/InAppNotificationPriorityConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/InAppNotificationPriorityConverter.java @@ -2,7 +2,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.InAppNotificationPriority; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class InAppNotificationPriorityConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/IsActiveConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/IsActiveConverter.java index cf8b1a095..b761adc7e 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/IsActiveConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/IsActiveConverter.java @@ -3,7 +3,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.IsActive; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class IsActiveConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationContactTypeConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationContactTypeConverter.java index 889c4a81b..ad21a70a3 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationContactTypeConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationContactTypeConverter.java @@ -3,7 +3,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationContactType; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationContactTypeConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationInAppTrackingConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationInAppTrackingConverter.java index 831281c9a..1ed3bb9e1 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationInAppTrackingConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationInAppTrackingConverter.java @@ -2,7 +2,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationInAppTracking; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationInAppTrackingConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationNotifyStateConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationNotifyStateConverter.java index 1a03b8726..7116e9b39 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationNotifyStateConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationNotifyStateConverter.java @@ -3,7 +3,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationNotifyState; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationNotifyStateConverter extends DatabaseEnumConverter { 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 index 0b0c6fc4f..a18b99656 100644 --- 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 @@ -4,7 +4,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationTemplateChannel; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationTemplateChannelConverter extends DatabaseEnumConverter { 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 index a4f355b58..4d6f1cce2 100644 --- 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 @@ -3,7 +3,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationTemplateKind; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationTemplateKindConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingProcessConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingProcessConverter.java index 64e7ada64..c85a83240 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingProcessConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingProcessConverter.java @@ -2,7 +2,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationTrackingProcess; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationTrackingProcessConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingStateConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingStateConverter.java index 25109651f..290639cda 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingStateConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/NotificationTrackingStateConverter.java @@ -3,7 +3,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.NotificationTrackingState; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class NotificationTrackingStateConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/TenantConfigurationTypeConverter.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/TenantConfigurationTypeConverter.java index 2ade1f572..d0ed545cb 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/TenantConfigurationTypeConverter.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/conventers/TenantConfigurationTypeConverter.java @@ -3,7 +3,7 @@ package gr.cite.notification.data.conventers; import gr.cite.notification.common.enums.TenantConfigurationType; -import javax.persistence.Converter; +import jakarta.persistence.Converter; @Converter public class TenantConfigurationTypeConverter extends DatabaseEnumConverter { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantFilterAspect.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantFilterAspect.java index 5c6f90bab..468755369 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantFilterAspect.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantFilterAspect.java @@ -12,7 +12,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import javax.management.InvalidApplicationException; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; @Aspect @Component diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java index 57d59ae06..a7c9901d3 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java @@ -8,9 +8,9 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import javax.management.InvalidApplicationException; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; -import javax.persistence.PreUpdate; +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreRemove; +import jakarta.persistence.PreUpdate; import java.util.UUID; public class TenantListener { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantScopedBaseEntity.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantScopedBaseEntity.java index 01705eb10..070497032 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantScopedBaseEntity.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantScopedBaseEntity.java @@ -5,9 +5,9 @@ import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.ParamDef; -import javax.persistence.Column; -import javax.persistence.EntityListeners; -import javax.persistence.MappedSuperclass; +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; import java.io.Serializable; import java.util.UUID; @@ -15,17 +15,22 @@ import java.util.UUID; //@Getter //@Setter //@NoArgsConstructor -@FilterDef(name = TenantScopedBaseEntity.tenantFilter, parameters = {@ParamDef(name = TenantScopedBaseEntity.tenantFilterTenantParam, type = "string")}) +@FilterDef(name = TenantScopedBaseEntity.tenantFilter, parameters = {@ParamDef(name = TenantScopedBaseEntity.tenantFilterTenantParam, type = String.class)}) @Filter(name = "tenantFilter", condition = "tenant = (cast(:tenantId as uuid))") @EntityListeners(TenantListener.class) public abstract class TenantScopedBaseEntity implements TenantScoped, Serializable { + private static final long serialVersionUID = 1L; + public static final String tenantFilter = "tenantFilter"; + public static final String tenantFilterTenantParam = "tenantId"; @Column(name = "tenant", columnDefinition = "uuid", nullable = true) private UUID tenantId; + public static final String _tenantId = "tenantId"; + public UUID getTenantId() { return tenantId; } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/AppRabbitConfigurer.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/AppRabbitConfigurer.java new file mode 100644 index 000000000..753d7db09 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/AppRabbitConfigurer.java @@ -0,0 +1,51 @@ +package gr.cite.notification.integrationevent; + +import gr.cite.notification.integrationevent.inbox.InboxProperties; +import gr.cite.notification.integrationevent.outbox.OutboxProperties; +import gr.cite.queueinbox.repository.InboxRepository; +import gr.cite.rabbitmq.RabbitConfigurer; +import gr.cite.rabbitmq.consumer.InboxBindings; +import gr.cite.rabbitmq.consumer.InboxCreator; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@EnableConfigurationProperties({OutboxProperties.class, InboxProperties.class}) +@ConditionalOnProperty(prefix = "queue.rabbitmq", name = "listenerEnabled") +public class AppRabbitConfigurer extends RabbitConfigurer { + + private final ApplicationContext applicationContext; + + private final InboxProperties inboxProperties; + + public AppRabbitConfigurer(ApplicationContext applicationContext, InboxProperties inboxProperties) { + this.applicationContext = applicationContext; + this.inboxProperties = inboxProperties; + } + + @Bean + public InboxBindings inboxBindingsCreator() { + List bindingItems = new ArrayList<>(); + bindingItems.addAll(this.inboxProperties.getNotifyTopic()); + bindingItems.addAll(this.inboxProperties.getTenantRemovalTopic()); + bindingItems.addAll(this.inboxProperties.getTenantTouchedTopic()); + bindingItems.addAll(this.inboxProperties.getUserRemovalTopic()); + bindingItems.addAll(this.inboxProperties.getUserTouchedTopic()); + + return new InboxBindings(bindingItems); + } + + @Bean(name = "InboxCreator") + public InboxCreator inboxCreator() { + return (params) -> { + InboxRepository inboxRepository = this.applicationContext.getBean(InboxRepository.class); + return inboxRepository.create(params) != null; + }; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/InboxIntegrationEventConfigurer.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/InboxIntegrationEventConfigurer.java new file mode 100644 index 000000000..ec7abfd6a --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/InboxIntegrationEventConfigurer.java @@ -0,0 +1,34 @@ +package gr.cite.notification.integrationevent; + +import gr.cite.notification.integrationevent.inbox.InboxProperties; +import gr.cite.notification.integrationevent.inbox.InboxRepositoryImpl; +import gr.cite.queueinbox.InboxConfigurer; +import gr.cite.queueinbox.repository.InboxRepository; +import jakarta.persistence.EntityManagerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +@Configuration +@EnableConfigurationProperties({InboxProperties.class}) +@ConditionalOnProperty(prefix = "queue.task.listener", name = "enable", matchIfMissing = false) +public class InboxIntegrationEventConfigurer extends InboxConfigurer { + private ApplicationContext applicationContext; + private InboxProperties inboxProperties; + + public InboxIntegrationEventConfigurer(ApplicationContext applicationContext, InboxProperties inboxProperties) { + this.applicationContext = applicationContext; + this.inboxProperties = inboxProperties; + } + + @Bean + public InboxRepository inboxRepositoryCreator() { + return new InboxRepositoryImpl(this.applicationContext, this.inboxProperties); + } + +} + diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/IntegrationEventContextImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/IntegrationEventContextImpl.java new file mode 100644 index 000000000..fd8c02dc3 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/IntegrationEventContextImpl.java @@ -0,0 +1,24 @@ +package gr.cite.notification.integrationevent; + +import gr.cite.rabbitmq.IntegrationEventContext; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Component +public class IntegrationEventContextImpl implements IntegrationEventContext { + + private UUID tenant; + + public IntegrationEventContextImpl() { + } + + public UUID getTenant() { + return tenant; + } + + public void setTenant(UUID tenant) { + this.tenant = tenant; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/OutboxIntegrationEventConfigurer.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/OutboxIntegrationEventConfigurer.java new file mode 100644 index 000000000..70ebc5361 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/OutboxIntegrationEventConfigurer.java @@ -0,0 +1,68 @@ +package gr.cite.notification.integrationevent; + +import gr.cite.notification.integrationevent.outbox.OutboxProperties; +import gr.cite.notification.integrationevent.outbox.OutboxRepositoryImpl; +import gr.cite.queueoutbox.IntegrationEventContextCreator; +import gr.cite.queueoutbox.OutboxConfigurer; +import gr.cite.queueoutbox.repository.OutboxRepository; +import gr.cite.rabbitmq.IntegrationEventMessageConstants; +import gr.cite.rabbitmq.RabbitProperties; +import gr.cite.rabbitmq.broker.MessageHydrator; +import org.springframework.amqp.core.MessageProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.Date; +import java.util.UUID; + +@Configuration +@EnableConfigurationProperties({OutboxProperties.class}) +@ConditionalOnProperty(prefix = "queue.task.publisher", name = "enable", matchIfMissing = false) +public class OutboxIntegrationEventConfigurer extends OutboxConfigurer { + private ApplicationContext applicationContext; + private OutboxProperties outboxProperties; + + public OutboxIntegrationEventConfigurer(ApplicationContext applicationContext, OutboxProperties outboxProperties) { + this.applicationContext = applicationContext; + this.outboxProperties = outboxProperties; + } + + @Bean + public MessageHydrator messageHydrator(RabbitProperties rabbitProperties) { + return (message, event, eventContext) -> { + MessageProperties messageProperties = message.getMessageProperties(); + messageProperties.setAppId(rabbitProperties.getAppId()); + messageProperties.setContentEncoding(StandardCharsets.UTF_8.displayName()); + messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON); + //messageProperties.setUserId(userContext.getCurrentUser().toString()); + messageProperties.setTimestamp(Date.from(Instant.now())); + messageProperties.setMessageId(event.getMessageId().toString()); + + if (eventContext != null) { + UUID tenant = ((IntegrationEventContextImpl) eventContext).getTenant(); + if (tenant != null) { + messageProperties.setHeader(IntegrationEventMessageConstants.TENANT, tenant); + } + } + + return message; + }; + } + + @Bean + public IntegrationEventContextCreator integrationEventContextCreator() { + return (message) -> new IntegrationEventContextImpl(); + } + + @Bean + public OutboxRepository outboxRepositoryCreator() { + return new OutboxRepositoryImpl(this.applicationContext, this.outboxProperties); + } +} + + diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/TrackedEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/TrackedEvent.java new file mode 100644 index 000000000..c5ecb2542 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/TrackedEvent.java @@ -0,0 +1,18 @@ +package gr.cite.notification.integrationevent; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class TrackedEvent { + + public String trackingContextTag; + + public String getTrackingContextTag() { + return trackingContextTag; + } + + public void setTrackingContextTag(String trackingContextTag) { + this.trackingContextTag = trackingContextTag; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/ConsistencyHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/ConsistencyHandler.java new file mode 100644 index 000000000..78f4f7f67 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/ConsistencyHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox; + +public interface ConsistencyHandler { + + Boolean isConsistent(T consistencyPredicates); + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/ConsistencyPredicates.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/ConsistencyPredicates.java new file mode 100644 index 000000000..e77c546a2 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/ConsistencyPredicates.java @@ -0,0 +1,5 @@ +package gr.cite.notification.integrationevent.inbox; + +public interface ConsistencyPredicates { + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/EventProcessingStatus.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/EventProcessingStatus.java new file mode 100644 index 000000000..274049473 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/EventProcessingStatus.java @@ -0,0 +1,8 @@ +package gr.cite.notification.integrationevent.inbox; + +public enum EventProcessingStatus { + Error, + Success, + Postponed, + Discard +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxPrincipal.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxPrincipal.java new file mode 100644 index 000000000..9fbc1521e --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxPrincipal.java @@ -0,0 +1,60 @@ +package gr.cite.notification.integrationevent.inbox; + +import gr.cite.commons.web.oidc.principal.MyPrincipal; +import org.springframework.security.oauth2.core.ClaimAccessor; +import org.springframework.security.oauth2.jwt.JwtClaimNames; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class InboxPrincipal implements MyPrincipal, ClaimAccessor { + + private final Map claims; + + private final boolean isAuthenticated; + + public InboxPrincipal(Boolean isAuthenticated, String name) { + this.claims = new HashMap<>(); + this.put(JwtClaimNames.SUB, name); + this.isAuthenticated = isAuthenticated; + } + + public static InboxPrincipal build(IntegrationEventProperties properties) { + InboxPrincipal inboxPrincipal = new InboxPrincipal(true, "IntegrationEventQueueAppId"); + inboxPrincipal.put("client_id", properties.getAppId()); + inboxPrincipal.put("active", "true"); + inboxPrincipal.put("nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString()); + inboxPrincipal.put("exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString()); + return inboxPrincipal; + } + + @Override + public Boolean isAuthenticated() { + return this.isAuthenticated; + } + + @Override + public Map getClaims() { + return this.claims; + } + + @Override + public List getClaimAsStringList(String claim) { + if (claims == null) + return null; + return this.getClaimAsStringList(claim); + } + + @Override + public String getName() { + return this.getClaimAsString(JwtClaimNames.SUB); + } + + public void put(String key, Object value) { + this.claims.put(key, value); + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxProperties.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxProperties.java new file mode 100644 index 000000000..18e14699b --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxProperties.java @@ -0,0 +1,61 @@ +package gr.cite.notification.integrationevent.inbox; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +@ConfigurationProperties(prefix = "queue.task.listener.options") +public class InboxProperties { + + private final String exchange; + + private final List notifyTopic; + + private final List tenantRemovalTopic; + + private final List tenantTouchedTopic; + + private final List userRemovalTopic; + + private final List userTouchedTopic; + + public InboxProperties( + String exchange, + List notifyTopic, + List tenantRemovalTopic, + List tenantTouchedTopic, + List userRemovalTopic, + List userTouchedTopic) { + this.exchange = exchange; + this.notifyTopic = notifyTopic; + this.tenantRemovalTopic = tenantRemovalTopic; + this.tenantTouchedTopic = tenantTouchedTopic; + this.userRemovalTopic = userRemovalTopic; + this.userTouchedTopic = userTouchedTopic; + } + + public List getNotifyTopic() { + return notifyTopic; + } + + public List getTenantRemovalTopic() { + return tenantRemovalTopic; + } + + public List getTenantTouchedTopic() { + return tenantTouchedTopic; + } + + public List getUserRemovalTopic() { + return userRemovalTopic; + } + + public List getUserTouchedTopic() { + return userTouchedTopic; + } + + public String getExchange() { + return exchange; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxRepositoryImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxRepositoryImpl.java new file mode 100644 index 000000000..811725fbe --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/InboxRepositoryImpl.java @@ -0,0 +1,363 @@ +package gr.cite.notification.integrationevent.inbox; + +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.data.QueueInboxEntity; +import gr.cite.notification.integrationevent.TrackedEvent; +import gr.cite.notification.integrationevent.inbox.notify.NotifyIntegrationEventHandler; +import gr.cite.notification.integrationevent.inbox.tenantremoval.TenantRemovalIntegrationEventHandler; +import gr.cite.notification.integrationevent.inbox.tenanttouched.TenantTouchedIntegrationEventHandler; +import gr.cite.notification.integrationevent.inbox.userremoval.UserRemovalIntegrationEventHandler; +import gr.cite.notification.integrationevent.inbox.usertouched.UserTouchedIntegrationEventHandler; +import gr.cite.notification.query.QueueInboxQuery; +import gr.cite.queueinbox.entity.QueueInbox; +import gr.cite.queueinbox.entity.QueueInboxStatus; +import gr.cite.queueinbox.repository.CandidateInfo; +import gr.cite.queueinbox.repository.InboxRepository; +import gr.cite.queueinbox.task.MessageOptions; +import gr.cite.rabbitmq.consumer.InboxCreatorParams; +import gr.cite.tools.data.query.Ordering; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; + +import java.time.Instant; +import java.util.List; +import java.util.UUID; +import java.util.function.Function; + +public class InboxRepositoryImpl implements InboxRepository { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(InboxRepositoryImpl.class)); + + protected final ApplicationContext applicationContext; + + private final JsonHandlingService jsonHandlingService; + + private final InboxProperties inboxProperties; + + public InboxRepositoryImpl( + ApplicationContext applicationContext, + InboxProperties inboxProperties + ) { + this.applicationContext = applicationContext; + this.jsonHandlingService = this.applicationContext.getBean(JsonHandlingService.class); + this.inboxProperties = inboxProperties; + } + + @Override + public CandidateInfo candidate(Instant lastCandidateCreationTimestamp, MessageOptions options) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + CandidateInfo candidate = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class) + .isActives(IsActive.Active) + .status(QueueInboxStatus.PENDING, QueueInboxStatus.ERROR) + .retryThreshold(options.getRetryThreashold()) + .createdAfter(lastCandidateCreationTimestamp) + .ordering(new Ordering().addAscending(QueueInboxEntity._createdAt)) + .first(); + + if (item != null) { + QueueInboxStatus prevState = item.getStatus(); + item.setStatus(QueueInboxStatus.PROCESSING); + + entityManager.merge(item); + entityManager.flush(); + + candidate = new CandidateInfo(); + candidate.setId(item.getId()); + candidate.setCreatedAt(item.getCreatedAt()); + candidate.setPreviousState(prevState); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue inbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) + transaction.rollback(); + candidate = null; + } catch (Exception ex) { + logger.error("Problem getting list of queue inbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) + transaction.rollback(); + candidate = null; + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue inbox. Skipping: {}", ex.getMessage(), ex); + } + + return candidate; + } + + @Override + public Boolean shouldOmit(CandidateInfo candidate, Function shouldOmit) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first(); + + if (item == null) { + logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidate.getId()); + } else { + if (shouldOmit.apply(item)) { + item.setStatus(QueueInboxStatus.OMITTED); + + entityManager.merge(item); + entityManager.flush(); + success = true; + } + } + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) + transaction.rollback(); + success = false; + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return success; + } + + @Override + public boolean shouldWait(CandidateInfo candidate, Function itIsTimeFunc) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first(); + + if (item.getRetryCount() != null && item.getRetryCount() >= 1) { + Boolean itIsTime = itIsTimeFunc.apply(item); + + if (!itIsTime) { + item.setStatus(candidate.getPreviousState()); + + entityManager.merge(item); + entityManager.flush(); + success = true; + } + + success = !itIsTime; + } + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) + transaction.rollback(); + success = false; + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return success; + } + + @Override + public QueueInbox create(InboxCreatorParams inboxCreatorParams) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + QueueInboxEntity queueMessage = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + queueMessage = this.createQueueInboxEntity(inboxCreatorParams); + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + + transaction.begin(); + + entityManager.persist(queueMessage); + entityManager.flush(); + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) + transaction.rollback(); + success = false; + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return queueMessage; + } + + private QueueInboxEntity createQueueInboxEntity(InboxCreatorParams inboxCreatorParams) { + + QueueInboxEntity queueMessage = new QueueInboxEntity(); + queueMessage.setId(UUID.randomUUID()); + queueMessage.setTenantId(null); + queueMessage.setExchange(this.inboxProperties.getExchange()); + queueMessage.setRoute(inboxCreatorParams.getRoutingKey()); + queueMessage.setQueue(inboxCreatorParams.getQueueName()); + queueMessage.setApplicationId(inboxCreatorParams.getAppId()); + queueMessage.setMessageId(UUID.fromString(inboxCreatorParams.getMessageId())); + queueMessage.setMessage(inboxCreatorParams.getMessageBody()); + queueMessage.setIsActive(IsActive.Active); + queueMessage.setStatus(QueueInboxStatus.PENDING); + queueMessage.setRetryCount(0); + queueMessage.setCreatedAt(Instant.now()); + + return queueMessage; + } + + @Override + public Boolean emit(CandidateInfo candidateInfo) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + QueueInboxEntity queueInboxMessage = queryFactory.query(QueueInboxQuery.class).ids(candidateInfo.getId()).first(); + + if (queueInboxMessage == null) { + logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidateInfo.getId()); + } else { + + EventProcessingStatus status = this.processMessage(queueInboxMessage.getRoute(), queueInboxMessage.getMessageId().toString(), queueInboxMessage.getApplicationId(), queueInboxMessage.getMessage()); + switch (status) { + case Success: { + queueInboxMessage.setStatus(QueueInboxStatus.SUCCESSFUL); + break; + } + case Postponed: { + queueInboxMessage.setStatus(QueueInboxStatus.PARKED); + break; + } + case Error: { + queueInboxMessage.setStatus(QueueInboxStatus.ERROR); + queueInboxMessage.setRetryCount(queueInboxMessage.getRetryCount() != null ? queueInboxMessage.getRetryCount() + 1 : 0); + break; + } + case Discard: + default: { + queueInboxMessage.setStatus(QueueInboxStatus.DISCARD); + break; + } + } + success = status == EventProcessingStatus.Success; + + entityManager.merge(queueInboxMessage); + entityManager.flush(); + } + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) + transaction.rollback(); + success = false; + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return success; + } + + private EventProcessingStatus processMessage(String routingKey, String messageId, String appId, String message) { + IntegrationEventHandler handler; + if (this.routingKeyMatched(routingKey, this.inboxProperties.getNotifyTopic())) + handler = this.applicationContext.getBean(NotifyIntegrationEventHandler.class); + else if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantRemovalTopic())) + handler = this.applicationContext.getBean(TenantRemovalIntegrationEventHandler.class); + else if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantTouchedTopic())) + handler = this.applicationContext.getBean(TenantTouchedIntegrationEventHandler.class); + else if (this.routingKeyMatched(routingKey, this.inboxProperties.getUserRemovalTopic())) + handler = this.applicationContext.getBean(UserRemovalIntegrationEventHandler.class); + else if (this.routingKeyMatched(routingKey, this.inboxProperties.getUserTouchedTopic())) + handler = this.applicationContext.getBean(UserTouchedIntegrationEventHandler.class); + else + handler = null; + + if (handler == null) + return EventProcessingStatus.Discard; + + IntegrationEventProperties properties = new IntegrationEventProperties(); + properties.setAppId(appId); + properties.setMessageId(messageId); + + TrackedEvent event = this.jsonHandlingService.fromJsonSafe(TrackedEvent.class, message); +// using (LogContext.PushProperty(this._logTrackingConfig.LogTrackingContextName, @event.TrackingContextTag)) +// { + try { + return handler.handle(properties, message); + } catch (Exception ex) { + logger.error("problem handling event from routing key " + routingKey + ". Setting nack and continuing...", ex); + return EventProcessingStatus.Error; + } +// } + } + + private Boolean routingKeyMatched(String routingKey, List topics) { + if (topics == null || topics.isEmpty()) + return false; + return topics.stream().anyMatch(x -> x.equals(routingKey)); + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/IntegrationEventHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/IntegrationEventHandler.java new file mode 100644 index 000000000..729cd7642 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/IntegrationEventHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox; + +public interface IntegrationEventHandler { + + EventProcessingStatus handle(IntegrationEventProperties properties, String message); + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/IntegrationEventProperties.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/IntegrationEventProperties.java new file mode 100644 index 000000000..9d5fcea93 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/IntegrationEventProperties.java @@ -0,0 +1,25 @@ +package gr.cite.notification.integrationevent.inbox; + +public class IntegrationEventProperties { + + private String messageId; + + private String appId; + + public String getMessageId() { + return messageId; + } + + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyConsistencyHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyConsistencyHandler.java new file mode 100644 index 000000000..9af7e1cc8 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyConsistencyHandler.java @@ -0,0 +1,47 @@ +package gr.cite.notification.integrationevent.inbox.notify; + +import gr.cite.notification.common.StringUtils; +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.common.enums.NotificationContactType; +import gr.cite.notification.integrationevent.inbox.ConsistencyHandler; +import gr.cite.notification.model.User; +import gr.cite.notification.model.builder.UserBuilder; +import gr.cite.notification.query.UserQuery; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.fieldset.BaseFieldSet; +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 NotifyConsistencyHandler implements ConsistencyHandler { + + private final QueryFactory queryFactory; + + private final BuilderFactory builderFactory; + + public NotifyConsistencyHandler(QueryFactory queryFactory, BuilderFactory builderFactory) { + this.queryFactory = queryFactory; + this.builderFactory = builderFactory; + } + + @Override + public Boolean isConsistent(NotifyConsistencyPredicates consistencyPredicates) { + if (consistencyPredicates.getUserId() != null) { + UserQuery query = this.queryFactory.query(UserQuery.class).ids(consistencyPredicates.getUserId()).isActive(IsActive.Active); + + BaseFieldSet fieldSet = new BaseFieldSet( + User._id, + User._isActive + ); + User user = this.builderFactory.builder(UserBuilder.class).build(fieldSet, query.firstAs(fieldSet)); + if (user == null) + return false; + return consistencyPredicates.getContactTypeHint() == null || consistencyPredicates.getContactTypeHint() == NotificationContactType.IN_APP || !StringUtils.isNullOrEmpty(consistencyPredicates.getContactHint()); + } + return true; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyConsistencyPredicates.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyConsistencyPredicates.java new file mode 100644 index 000000000..9d87ad1ac --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyConsistencyPredicates.java @@ -0,0 +1,45 @@ +package gr.cite.notification.integrationevent.inbox.notify; + +import gr.cite.notification.common.enums.NotificationContactType; +import gr.cite.notification.integrationevent.inbox.ConsistencyPredicates; + +import java.util.UUID; + +public class NotifyConsistencyPredicates implements ConsistencyPredicates { + + private UUID userId; + + private NotificationContactType contactTypeHint; + + private String contactHint; + + public NotifyConsistencyPredicates(UUID userId, NotificationContactType contactTypeHint, String contactHint) { + this.userId = userId; + this.contactTypeHint = contactTypeHint; + this.contactHint = contactHint; + } + + public UUID getUserId() { + return userId; + } + + public void setUserId(UUID userId) { + this.userId = userId; + } + + public NotificationContactType getContactTypeHint() { + return contactTypeHint; + } + + public void setContactTypeHint(NotificationContactType contactTypeHint) { + this.contactTypeHint = contactTypeHint; + } + + public String getContactHint() { + return contactHint; + } + + public void setContactHint(String contactHint) { + this.contactHint = contactHint; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEvent.java new file mode 100644 index 000000000..d04106d74 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEvent.java @@ -0,0 +1,80 @@ +package gr.cite.notification.integrationevent.inbox.notify; + +import gr.cite.notification.common.enums.NotificationContactType; +import gr.cite.notification.integrationevent.TrackedEvent; + +import java.util.UUID; + +public class NotifyIntegrationEvent extends TrackedEvent { + + private UUID userId; + + private UUID tenantId; + + private UUID notificationType; + + private NotificationContactType contactTypeHint; + + private String contactHint; + + private String data; + + private String provenanceRef; + + public UUID getUserId() { + return userId; + } + + public void setUserId(UUID userId) { + this.userId = userId; + } + + public UUID getTenantId() { + return tenantId; + } + + public void setTenantId(UUID tenantId) { + this.tenantId = tenantId; + } + + public UUID getNotificationType() { + return notificationType; + } + + public void setNotificationType(UUID notificationType) { + this.notificationType = notificationType; + } + + public NotificationContactType getContactTypeHint() { + return contactTypeHint; + } + + public void setContactTypeHint(NotificationContactType contactTypeHint) { + this.contactTypeHint = contactTypeHint; + } + + public String getContactHint() { + return contactHint; + } + + public void setContactHint(String contactHint) { + this.contactHint = contactHint; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public String getProvenanceRef() { + return provenanceRef; + } + + public void setProvenanceRef(String provenanceRef) { + this.provenanceRef = provenanceRef; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandler.java new file mode 100644 index 000000000..fadf33f60 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox.notify; + +import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler; + +public interface NotifyIntegrationEventHandler extends IntegrationEventHandler { + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..9b304b7fc --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java @@ -0,0 +1,156 @@ +package gr.cite.notification.integrationevent.inbox.notify; + +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.notification.audit.AuditableAction; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.enums.NotificationNotifyState; +import gr.cite.notification.common.enums.NotificationTrackingProcess; +import gr.cite.notification.common.enums.NotificationTrackingState; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.common.scope.tenant.TenantScope; +import gr.cite.notification.data.TenantEntity; +import gr.cite.notification.errorcode.ErrorThesaurusProperties; +import gr.cite.notification.integrationevent.inbox.EventProcessingStatus; +import gr.cite.notification.integrationevent.inbox.InboxPrincipal; +import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties; +import gr.cite.notification.model.Tenant; +import gr.cite.notification.model.persist.NotificationPersist; +import gr.cite.notification.query.TenantQuery; +import gr.cite.notification.service.notification.NotificationService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyValidationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.AbstractMap; +import java.util.Map; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class NotifyIntegrationEventHandlerImpl implements NotifyIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotifyIntegrationEventHandlerImpl.class)); + + private final JsonHandlingService jsonHandlingService; + + private final ApplicationContext applicationContext; + + private final ErrorThesaurusProperties errors; + + private final MessageSource messageSource; + + public NotifyIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ApplicationContext applicationContext, ErrorThesaurusProperties errors, MessageSource messageSource) { + this.jsonHandlingService = jsonHandlingService; + this.applicationContext = applicationContext; + this.errors = errors; + this.messageSource = messageSource; + } + + @Override + public EventProcessingStatus handle(IntegrationEventProperties properties, String message) { + NotifyIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(NotifyIntegrationEvent.class, message); + if (event == null) + return EventProcessingStatus.Error; + if (event.getUserId() == null) { + throw new MyValidationException(this.errors.getModelValidation().getCode(), "userId", messageSource.getMessage("Validation_Required", new Object[]{"userId"}, LocaleContextHolder.getLocale())); + } + + NotificationPersist model = new NotificationPersist(); + model.setType(event.getNotificationType()); + model.setUserId(event.getUserId()); + model.setContactHint(event.getContactHint()); + model.setContactTypeHint(event.getContactTypeHint()); + model.setData(event.getData()); + model.setNotifyState(NotificationNotifyState.PENDING); + model.setNotifiedWith(event.getContactTypeHint()); + model.setRetryCount(0); + model.setTrackingState(NotificationTrackingState.UNDEFINED); + model.setTrackingProcess(NotificationTrackingProcess.PENDING); + model.setTrackingData(null); + model.setProvenanceRef(event.getProvenanceRef()); + model.setNotifiedAt(Instant.now()); + + EntityManager entityManager = null; + EntityTransaction transaction = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + TenantScope scope = this.applicationContext.getBean(TenantScope.class); + if (scope.isMultitenant() && event.getTenantId() != null) { + TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code)); + if (tenant == null) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } + scope.setTenant(event.getTenantId(), tenant.getCode()); + } else if (scope.isMultitenant()) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } + + CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + NotifyConsistencyHandler notifyConsistencyHandler = this.applicationContext.getBean(NotifyConsistencyHandler.class); + if (!(notifyConsistencyHandler.isConsistent(new NotifyConsistencyPredicates(event.getUserId(), event.getContactTypeHint(), event.getContactHint())))) + return EventProcessingStatus.Postponed; + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + try { + NotificationService notificationService = this.applicationContext.getBean(NotificationService.class); + notificationService.persist(model, new BaseFieldSet()); + + AuditService auditService = this.applicationContext.getBean(AuditService.class); + + auditService.track(AuditableAction.Notification_Persist, Map.ofEntries( + new AbstractMap.SimpleEntry("id", event.getUserId()) + )); + //auditService.trackIdentity(AuditableAction.IdentityTracking_Action); + + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + throw e; + } finally { + currentPrincipalResolver.pop(); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) + transaction.rollback(); + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) + transaction.rollback(); + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } + return null; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalConsistencyHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalConsistencyHandler.java new file mode 100644 index 000000000..685597a98 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalConsistencyHandler.java @@ -0,0 +1,26 @@ +package gr.cite.notification.integrationevent.inbox.tenantremoval; + +import gr.cite.notification.integrationevent.inbox.ConsistencyHandler; +import gr.cite.notification.query.TenantQuery; +import gr.cite.tools.data.query.QueryFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class TenantRemovalConsistencyHandler implements ConsistencyHandler { + + private final QueryFactory queryFactory; + + public TenantRemovalConsistencyHandler(QueryFactory queryFactory) { + this.queryFactory = queryFactory; + } + + @Override + public Boolean isConsistent(TenantRemovalConsistencyPredicates consistencyPredicates) { + long count = this.queryFactory.query(TenantQuery.class).ids(consistencyPredicates.getTenantId()).count(); + return count > 0; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalConsistencyPredicates.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalConsistencyPredicates.java new file mode 100644 index 000000000..f55869126 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalConsistencyPredicates.java @@ -0,0 +1,23 @@ +package gr.cite.notification.integrationevent.inbox.tenantremoval; + +import gr.cite.notification.integrationevent.inbox.ConsistencyPredicates; + +import java.util.UUID; + +public class TenantRemovalConsistencyPredicates implements ConsistencyPredicates { + + private UUID tenantId; + + public TenantRemovalConsistencyPredicates(UUID tenantId) { + this.tenantId = tenantId; + } + + public UUID getTenantId() { + return tenantId; + } + + public void setTenantId(UUID tenantId) { + this.tenantId = tenantId; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEvent.java new file mode 100644 index 000000000..cf1201688 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEvent.java @@ -0,0 +1,19 @@ +package gr.cite.notification.integrationevent.inbox.tenantremoval; + +import gr.cite.notification.integrationevent.TrackedEvent; + +import java.util.UUID; + +public class TenantRemovalIntegrationEvent extends TrackedEvent { + + private UUID id; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandler.java new file mode 100644 index 000000000..a6e5d27ed --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox.tenantremoval; + +import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler; + +public interface TenantRemovalIntegrationEventHandler extends IntegrationEventHandler { + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..c27824f3f --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenantremoval/TenantRemovalIntegrationEventHandlerImpl.java @@ -0,0 +1,111 @@ +package gr.cite.notification.integrationevent.inbox.tenantremoval; + +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.notification.audit.AuditableAction; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.errorcode.ErrorThesaurusProperties; +import gr.cite.notification.integrationevent.inbox.EventProcessingStatus; +import gr.cite.notification.integrationevent.inbox.InboxPrincipal; +import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties; +import gr.cite.notification.service.tenant.TenantService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.AbstractMap; +import java.util.Map; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class TenantRemovalIntegrationEventHandlerImpl implements TenantRemovalIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantRemovalIntegrationEventHandlerImpl.class)); + + private final JsonHandlingService jsonHandlingService; + + private final ApplicationContext applicationContext; + + private final ErrorThesaurusProperties errors; + + private final MessageSource messageSource; + + public TenantRemovalIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ApplicationContext applicationContext, ErrorThesaurusProperties errors, MessageSource messageSource) { + this.jsonHandlingService = jsonHandlingService; + this.applicationContext = applicationContext; + this.errors = errors; + this.messageSource = messageSource; + } + + @Override + public EventProcessingStatus handle(IntegrationEventProperties properties, String message) { + TenantRemovalIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(TenantRemovalIntegrationEvent.class, message); + if (event == null) + return EventProcessingStatus.Error; + + EntityManager entityManager = null; + EntityTransaction transaction = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + TenantRemovalConsistencyHandler tenantRemovalConsistencyHandler = this.applicationContext.getBean(TenantRemovalConsistencyHandler.class); + if (!(tenantRemovalConsistencyHandler.isConsistent(new TenantRemovalConsistencyPredicates(event.getId())))) + return EventProcessingStatus.Postponed; + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + try { + TenantService tenantService = this.applicationContext.getBean(TenantService.class); + tenantService.deleteAndSave(event.getId()); + + AuditService auditService = this.applicationContext.getBean(AuditService.class); + + auditService.track(AuditableAction.Tenant_Delete, Map.ofEntries( + new AbstractMap.SimpleEntry("id", event.getId()) + )); + //auditService.trackIdentity(AuditableAction.IdentityTracking_Action); + + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + throw e; + } finally { + currentPrincipalResolver.pop(); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) + transaction.rollback(); + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) + transaction.rollback(); + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } + return null; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEvent.java new file mode 100644 index 000000000..899d22db8 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEvent.java @@ -0,0 +1,29 @@ +package gr.cite.notification.integrationevent.inbox.tenanttouched; + +import gr.cite.notification.integrationevent.TrackedEvent; + +import java.util.UUID; + +public class TenantTouchedIntegrationEvent extends TrackedEvent { + + private UUID id; + + private String code; + + 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; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEventHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEventHandler.java new file mode 100644 index 000000000..f476601f3 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEventHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox.tenanttouched; + +import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler; + +public interface TenantTouchedIntegrationEventHandler extends IntegrationEventHandler { + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..a33114668 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/tenanttouched/TenantTouchedIntegrationEventHandlerImpl.java @@ -0,0 +1,103 @@ +package gr.cite.notification.integrationevent.inbox.tenanttouched; + +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.notification.audit.AuditableAction; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.integrationevent.inbox.EventProcessingStatus; +import gr.cite.notification.integrationevent.inbox.InboxPrincipal; +import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties; +import gr.cite.notification.model.persist.TenantTouchedIntegrationEventPersist; +import gr.cite.notification.service.tenant.TenantService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.AbstractMap; +import java.util.Map; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class TenantTouchedIntegrationEventHandlerImpl implements TenantTouchedIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantTouchedIntegrationEventHandlerImpl.class)); + + protected final ApplicationContext applicationContext; + + private final JsonHandlingService jsonHandlingService; + + public TenantTouchedIntegrationEventHandlerImpl(ApplicationContext applicationContext, JsonHandlingService jsonHandlingService) { + this.applicationContext = applicationContext; + this.jsonHandlingService = jsonHandlingService; + } + + @Override + public EventProcessingStatus handle(IntegrationEventProperties properties, String message) { + TenantTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(TenantTouchedIntegrationEvent.class, message); + if (event == null) + return EventProcessingStatus.Error; + + TenantTouchedIntegrationEventPersist model = new TenantTouchedIntegrationEventPersist(); + model.setId(event.getId()); + model.setCode(event.getCode()); + + EntityManager entityManager = null; + EntityTransaction transaction = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + try { + TenantService tenantService = this.applicationContext.getBean(TenantService.class); + tenantService.persist(model, null); + + AuditService auditService = this.applicationContext.getBean(AuditService.class); + + auditService.track(AuditableAction.Tenant_Persist, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + throw e; + } finally { + currentPrincipalResolver.pop(); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) + transaction.rollback(); + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) + transaction.rollback(); + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } + return null; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalConsistencyHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalConsistencyHandler.java new file mode 100644 index 000000000..958d00b84 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalConsistencyHandler.java @@ -0,0 +1,25 @@ +package gr.cite.notification.integrationevent.inbox.userremoval; + +import gr.cite.notification.integrationevent.inbox.ConsistencyHandler; +import gr.cite.notification.query.UserQuery; +import gr.cite.tools.data.query.QueryFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class UserRemovalConsistencyHandler implements ConsistencyHandler { + + private final QueryFactory queryFactory; + + public UserRemovalConsistencyHandler(QueryFactory queryFactory) { + this.queryFactory = queryFactory; + } + + @Override + public Boolean isConsistent(UserRemovalConsistencyPredicates consistencyPredicates) { + long count = this.queryFactory.query(UserQuery.class).ids(consistencyPredicates.getUserId()).count(); + return count != 0; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalConsistencyPredicates.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalConsistencyPredicates.java new file mode 100644 index 000000000..2c9974a7d --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalConsistencyPredicates.java @@ -0,0 +1,23 @@ +package gr.cite.notification.integrationevent.inbox.userremoval; + +import gr.cite.notification.integrationevent.inbox.ConsistencyPredicates; + +import java.util.UUID; + +public class UserRemovalConsistencyPredicates implements ConsistencyPredicates { + + private UUID userId; + + public UserRemovalConsistencyPredicates(UUID userId) { + this.userId = userId; + } + + public UUID getUserId() { + return userId; + } + + public void setUserId(UUID userId) { + this.userId = userId; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEvent.java new file mode 100644 index 000000000..2ce9f613d --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEvent.java @@ -0,0 +1,28 @@ +package gr.cite.notification.integrationevent.inbox.userremoval; + +import gr.cite.notification.integrationevent.TrackedEvent; + +import java.util.UUID; + +public class UserRemovalIntegrationEvent extends TrackedEvent { + + private UUID userId; + + private UUID tenant; + + public UUID getUserId() { + return userId; + } + + public void setUserId(UUID userId) { + this.userId = userId; + } + + public UUID getTenant() { + return tenant; + } + + public void setTenant(UUID tenant) { + this.tenant = tenant; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandler.java new file mode 100644 index 000000000..7bc8d1245 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox.userremoval; + +import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler; + +public interface UserRemovalIntegrationEventHandler extends IntegrationEventHandler { + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..791082ba8 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/userremoval/UserRemovalIntegrationEventHandlerImpl.java @@ -0,0 +1,139 @@ +package gr.cite.notification.integrationevent.inbox.userremoval; + +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.notification.audit.AuditableAction; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.common.scope.tenant.TenantScope; +import gr.cite.notification.data.TenantEntity; +import gr.cite.notification.errorcode.ErrorThesaurusProperties; +import gr.cite.notification.integrationevent.inbox.EventProcessingStatus; +import gr.cite.notification.integrationevent.inbox.InboxPrincipal; +import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties; +import gr.cite.notification.model.Tenant; +import gr.cite.notification.query.TenantQuery; +import gr.cite.notification.service.user.UserService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyValidationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; + +import java.util.AbstractMap; +import java.util.Map; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class UserRemovalIntegrationEventHandlerImpl implements UserRemovalIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserRemovalIntegrationEventHandlerImpl.class)); + + private final JsonHandlingService jsonHandlingService; + + private final ApplicationContext applicationContext; + + private final ErrorThesaurusProperties errors; + + private final MessageSource messageSource; + + public UserRemovalIntegrationEventHandlerImpl( + JsonHandlingService jsonHandlingService, + ApplicationContext applicationContext, + ErrorThesaurusProperties errors, + MessageSource messageSource + ) { + this.jsonHandlingService = jsonHandlingService; + this.applicationContext = applicationContext; + this.errors = errors; + this.messageSource = messageSource; + } + + @Override + public EventProcessingStatus handle(IntegrationEventProperties properties, String message) { + UserRemovalIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(UserRemovalIntegrationEvent.class, message); + if (event == null) + return EventProcessingStatus.Error; + if (event.getUserId() == null) + throw new MyValidationException(this.errors.getModelValidation().getCode(), "userId", messageSource.getMessage("Validation_Required", new Object[]{"userId"}, LocaleContextHolder.getLocale())); + + EntityManager entityManager = null; + EntityTransaction transaction = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + TenantScope scope = this.applicationContext.getBean(TenantScope.class); + if (scope.isMultitenant() && event.getTenant() != null) { + TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenant()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code)); + if (tenant == null) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } + scope.setTenant(event.getTenant(), tenant.getCode()); + } else if (scope.isMultitenant()) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } + + CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + UserRemovalConsistencyHandler userRemovalConsistencyHandler = this.applicationContext.getBean(UserRemovalConsistencyHandler.class); + if (!(userRemovalConsistencyHandler.isConsistent(new UserRemovalConsistencyPredicates(event.getUserId())))) + return EventProcessingStatus.Postponed; + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + try { + UserService userService = this.applicationContext.getBean(UserService.class); + userService.deleteAndSave(event.getUserId()); + + AuditService auditService = this.applicationContext.getBean(AuditService.class); + + auditService.track(AuditableAction.User_Delete, Map.ofEntries( + new AbstractMap.SimpleEntry("id", event.getUserId()) + )); + //auditService.trackIdentity(AuditableAction.IdentityTracking_Action); + + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + throw e; + } finally { + currentPrincipalResolver.pop(); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) + transaction.rollback(); + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) + transaction.rollback(); + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } + return null; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEvent.java new file mode 100644 index 000000000..113588fbf --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEvent.java @@ -0,0 +1,48 @@ +package gr.cite.notification.integrationevent.inbox.usertouched; + +import gr.cite.notification.integrationevent.TrackedEvent; + +import java.util.UUID; + +public class UserTouchedIntegrationEvent extends TrackedEvent { + + private UUID id; + + private UUID tenant; + + private String firstName; + + private String lastName; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public UUID getTenant() { + return tenant; + } + + public void setTenant(UUID tenant) { + this.tenant = tenant; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEventHandler.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEventHandler.java new file mode 100644 index 000000000..24b11d5f3 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEventHandler.java @@ -0,0 +1,7 @@ +package gr.cite.notification.integrationevent.inbox.usertouched; + +import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler; + +public interface UserTouchedIntegrationEventHandler extends IntegrationEventHandler { + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEventHandlerImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..4adc71d59 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/usertouched/UserTouchedIntegrationEventHandlerImpl.java @@ -0,0 +1,129 @@ +package gr.cite.notification.integrationevent.inbox.usertouched; + +import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; +import gr.cite.notification.audit.AuditableAction; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.common.scope.tenant.TenantScope; +import gr.cite.notification.data.TenantEntity; +import gr.cite.notification.integrationevent.inbox.EventProcessingStatus; +import gr.cite.notification.integrationevent.inbox.InboxPrincipal; +import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties; +import gr.cite.notification.model.Tenant; +import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist; +import gr.cite.notification.query.TenantQuery; +import gr.cite.notification.service.user.UserService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.AbstractMap; +import java.util.Map; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class UserTouchedIntegrationEventHandlerImpl implements UserTouchedIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserTouchedIntegrationEventHandlerImpl.class)); + + protected final ApplicationContext applicationContext; + + private final JsonHandlingService jsonHandlingService; + + public UserTouchedIntegrationEventHandlerImpl( + JsonHandlingService jsonHandlingService, + ApplicationContext applicationContext + ) { + this.jsonHandlingService = jsonHandlingService; + this.applicationContext = applicationContext; + } + + @Override + public EventProcessingStatus handle(IntegrationEventProperties properties, String message) { + UserTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(UserTouchedIntegrationEvent.class, message); + if (event == null) + return EventProcessingStatus.Error; + + UserTouchedIntegrationEventPersist model = new UserTouchedIntegrationEventPersist(); + model.setId(event.getId()); + model.setFirstName(event.getFirstName()); + model.setLastName(event.getLastName()); + + EntityManager entityManager = null; + EntityTransaction transaction = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + TenantScope scope = this.applicationContext.getBean(TenantScope.class); + if (scope.isMultitenant() && event.getTenant() != null) { + TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenant()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code)); + if (tenant == null) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } + scope.setTenant(event.getTenant(), tenant.getCode()); + } else if (scope.isMultitenant()) { + logger.error("missing tenant from event message"); + return EventProcessingStatus.Error; + } +// +// ValidationService validator = this.applicationContext.getBean(ValidationService.class); +// validator.validateForce(model); + + CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class); + currentPrincipalResolver.push(InboxPrincipal.build(properties)); + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + try { + UserService userService = this.applicationContext.getBean(UserService.class); + userService.persist(model, null); + + AuditService auditService = this.applicationContext.getBean(AuditService.class); + + auditService.track(AuditableAction.User_Persist, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + throw e; + } finally { + currentPrincipalResolver.pop(); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) + transaction.rollback(); + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) + transaction.rollback(); + } finally { + if (entityManager != null) + entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } + return null; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxIntegrationEvent.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxIntegrationEvent.java new file mode 100644 index 000000000..5961fe016 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxIntegrationEvent.java @@ -0,0 +1,19 @@ +package gr.cite.notification.integrationevent.outbox; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import gr.cite.notification.integrationevent.TrackedEvent; +import gr.cite.rabbitmq.IntegrationEvent; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OutboxIntegrationEvent extends IntegrationEvent { + private TrackedEvent event; + + public TrackedEvent getEvent() { + return event; + } + + public void setEvent(TrackedEvent event) { + this.event = event; + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxProperties.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxProperties.java new file mode 100644 index 000000000..af5e77173 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxProperties.java @@ -0,0 +1,58 @@ +package gr.cite.notification.integrationevent.outbox; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "queue.task.publisher.options") +public class OutboxProperties { + + private final String exchange; + + private final String tenantTouchTopic; + + private final String tenantRemovalTopic; + + private final String userTouchTopic; + + private final String userRemovalTopic; + + private final String notifyTopic; + + public OutboxProperties(String exchange, + String tenantTouchTopic, + String tenantRemovalTopic, + String userTouchTopic, + String userRemovalTopic, + String notifyTopic + ) { + this.exchange = exchange; + this.tenantTouchTopic = tenantTouchTopic; + this.tenantRemovalTopic = tenantRemovalTopic; + this.userTouchTopic = userTouchTopic; + this.userRemovalTopic = userRemovalTopic; + this.notifyTopic = notifyTopic; + } + + public String getExchange() { + return exchange; + } + + public String getTenantTouchTopic() { + return tenantTouchTopic; + } + + public String getTenantRemovalTopic() { + return tenantRemovalTopic; + } + + public String getUserTouchTopic() { + return userTouchTopic; + } + + public String getUserRemovalTopic() { + return userRemovalTopic; + } + + public String getNotifyTopic() { + return notifyTopic; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxRepositoryImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxRepositoryImpl.java new file mode 100644 index 000000000..8bdc8fdb0 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/outbox/OutboxRepositoryImpl.java @@ -0,0 +1,397 @@ +package gr.cite.notification.integrationevent.outbox; + +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.common.scope.fake.FakeRequestScope; +import gr.cite.notification.data.QueueOutboxEntity; +import gr.cite.notification.query.QueueOutboxQuery; +import gr.cite.queueoutbox.entity.QueueOutbox; +import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus; +import gr.cite.queueoutbox.repository.CandidateInfo; +import gr.cite.queueoutbox.repository.OutboxRepository; +import gr.cite.queueoutbox.task.MessageOptions; +import gr.cite.rabbitmq.IntegrationEvent; +import gr.cite.tools.data.query.Ordering; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.logging.LoggerService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class OutboxRepositoryImpl implements OutboxRepository { + + protected final ApplicationContext applicationContext; + private final Random random = new Random(); + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(OutboxRepositoryImpl.class)); + private final JsonHandlingService jsonHandlingService; + private final OutboxProperties outboxProperties; + + public OutboxRepositoryImpl( + ApplicationContext applicationContext, + OutboxProperties outboxProperties + ) { + this.applicationContext = applicationContext; + this.jsonHandlingService = this.applicationContext.getBean(JsonHandlingService.class); + this.outboxProperties = outboxProperties; + } + + @Override + public CandidateInfo candidate(Instant lastCandidateCreationTimestamp, MessageOptions messageOptions, Function onConfirmTimeout) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + CandidateInfo candidate = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + entityManager = entityManagerFactory.createEntityManager(); + + transaction = entityManager.getTransaction(); + transaction.begin(); + + QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class) + .isActives(IsActive.Active) + .notifyStatus(QueueOutboxNotifyStatus.PENDING, QueueOutboxNotifyStatus.WAITING_CONFIRMATION, QueueOutboxNotifyStatus.ERROR) + .retryThreshold(messageOptions.getRetryThreashold()) + .confirmTimeout(messageOptions.getConfirmTimeoutSeconds()) + .createdAfter(lastCandidateCreationTimestamp) + .ordering(new Ordering().addAscending(QueueOutboxEntity._createdAt)) + .first(); + + if (item != null) { + boolean confirmTimeout = onConfirmTimeout.apply(item); + + QueueOutboxNotifyStatus prevState = item.getNotifyStatus(); + item.setNotifyStatus(QueueOutboxNotifyStatus.PROCESSING); + + entityManager.merge(item); + entityManager.flush(); + + candidate = new CandidateInfo(); + candidate.setId(item.getId()); + candidate.setCreatedAt(item.getCreatedAt()); + candidate.setPreviousState(prevState); + } + + transaction.commit(); + } catch (OptimisticLockException ex) { + // we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working + logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage()); + if (transaction != null) transaction.rollback(); + candidate = null; + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + if (transaction != null) transaction.rollback(); + candidate = null; + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex); + } + + return candidate; + } + + @Override + public Boolean shouldOmit(CandidateInfo candidate, Function shouldOmit) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidate.getId()).first(); + + if (item == null) { + logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidate.getId()); + } else { + if (shouldOmit.apply(item)) { + item.setNotifyStatus(QueueOutboxNotifyStatus.OMITTED); + + entityManager.merge(item); + entityManager.flush(); + success = true; + } + } + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) transaction.rollback(); + success = false; + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return success; + } + + @Override + public Boolean shouldWait(CandidateInfo candidate, Function itIsTimeFunc) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidate.getId()).first(); + + if (item.getRetryCount() != null && item.getRetryCount() >= 1) { + Boolean itIsTime = itIsTimeFunc.apply(item); + + if (!itIsTime) { + item.setNotifyStatus(candidate.getPreviousState()); + + entityManager.merge(item); + entityManager.flush(); + success = true; + } + + success = !itIsTime; + } + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) transaction.rollback(); + success = false; + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return success; + } + + @Override + public Boolean process(CandidateInfo candidateInfo, Boolean isAutoconfirmOnPublish, Function publish) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + Boolean success = false; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidateInfo.getId()).first(); + + if (item == null) { + logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidateInfo.getId()); + } else { + + success = publish.apply(item); + if (success) { + if (isAutoconfirmOnPublish) { + item.setNotifyStatus(QueueOutboxNotifyStatus.CONFIRMED); + item.setConfirmedAt(Instant.now()); + } else { + item.setNotifyStatus(QueueOutboxNotifyStatus.WAITING_CONFIRMATION); + } + item.setPublishedAt(Instant.now()); + } else { + item.setNotifyStatus(QueueOutboxNotifyStatus.ERROR); + item.setRetryCount(item.getRetryCount() != null ? item.getRetryCount() + 1 : 0); + item.setPublishedAt(null); + } + + entityManager.merge(item); + entityManager.flush(); + } + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) transaction.rollback(); + success = false; + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return success; + } + + @Override + public void handleConfirm(List confirmedMessages) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + List queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(confirmedMessages).collect(); + + if (queueOutboxMessages == null) { + logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", confirmedMessages.stream().map(x -> x.toString()).collect(Collectors.toList()))); + } else { + + for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) { + queueOutboxMessage.setNotifyStatus(QueueOutboxNotifyStatus.CONFIRMED); + queueOutboxMessage.setConfirmedAt(Instant.now()); + entityManager.merge(queueOutboxMessage); + } + + entityManager.flush(); + } + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) transaction.rollback(); + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + } + + @Override + public void handleNack(List nackedMessages) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + transaction.begin(); + + QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); + List queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(nackedMessages).collect(); + + if (queueOutboxMessages == null) { + logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", nackedMessages.stream().map(x -> x.toString()).collect(Collectors.toList()))); + } else { + + for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) { + queueOutboxMessage.setNotifyStatus(QueueOutboxNotifyStatus.ERROR); + queueOutboxMessage.setRetryCount(queueOutboxMessage.getRetryCount() != null ? queueOutboxMessage.getRetryCount() + 1 : 0); + entityManager.merge(queueOutboxMessage); + } + + entityManager.flush(); + } + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) transaction.rollback(); + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + } + + @Override + public QueueOutbox create(IntegrationEvent item) { + EntityTransaction transaction = null; + EntityManager entityManager = null; + boolean success = false; + QueueOutboxEntity queueMessage = null; + try (FakeRequestScope ignored = new FakeRequestScope()) { + try { + queueMessage = this.mapEvent((OutboxIntegrationEvent) item); + EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); + + entityManager = entityManagerFactory.createEntityManager(); + transaction = entityManager.getTransaction(); + + transaction.begin(); + + entityManager.persist(queueMessage); + entityManager.flush(); + + transaction.commit(); + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + if (transaction != null) transaction.rollback(); + success = false; + } finally { + if (entityManager != null) entityManager.close(); + } + } catch (Exception ex) { + logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); + } + return queueMessage; + } + + private QueueOutboxEntity mapEvent(OutboxIntegrationEvent event) { + String routingKey; + switch (event.getType()) { + default: { + logger.error("unrecognized outgoing integration event {}. Skipping...", event.getType()); + return null; + } + } + +// UUID correlationId = UUID.randomUUID(); +// if (event.getEvent() != null) event.getEvent().setTrackingContextTag(correlationId.toString()); +// event.setMessage(this.jsonHandlingService.toJsonSafe(event.getEvent())); +// //this._logTrackingService.Trace(correlationId.ToString(), $"Correlating current tracking context with new correlationId {correlationId}"); +// +// QueueOutboxEntity queueMessage = new QueueOutboxEntity(); +// queueMessage.setId(UUID.randomUUID()); +// queueMessage.setTenantId(null); +// queueMessage.setExchange(this.outboxProperties.getExchange()); +// queueMessage.setRoute(routingKey); +// queueMessage.setMessageId(event.getMessageId()); +// queueMessage.setMessage(this.jsonHandlingService.toJsonSafe(event)); +// queueMessage.setIsActive(IsActive.Active); +// queueMessage.setNotifyStatus(QueueOutboxNotifyStatus.PENDING); +// queueMessage.setRetryCount(0); +// queueMessage.setCreatedAt(Instant.now()); +// queueMessage.setUpdatedAt(Instant.now()); +// +// return queueMessage; + } +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/InAppNotification.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/InAppNotification.java index 7af31d850..dc5569f72 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/InAppNotification.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/InAppNotification.java @@ -5,7 +5,7 @@ import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.NotificationInAppTracking; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; public class InAppNotification { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Notification.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Notification.java index 16248f64a..4d0d5b8b2 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Notification.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/Notification.java @@ -1,8 +1,12 @@ package gr.cite.notification.model; -import gr.cite.notification.common.enums.IsActive; -import gr.cite.notification.common.enums.NotificationContactType; +import gr.cite.notification.common.enums.*; +import gr.cite.notification.data.conventers.IsActiveConverter; +import gr.cite.notification.data.conventers.NotificationTrackingProcessConverter; +import gr.cite.notification.data.conventers.NotificationTrackingStateConverter; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; import java.time.Instant; import java.util.UUID; @@ -29,6 +33,21 @@ public class Notification { private Instant notifiedAt; public final static String _notifiedAt = "notifiedAt"; + private NotificationNotifyState notifyState; + public final static String _notifyState = "notifyState"; + + private NotificationContactType notifiedWith; + public final static String _notifiedWith = "notifiedWith"; + + private Integer retryCount; + public final static String _retryCount = "retryCount"; + + private NotificationTrackingState trackingState; + public final static String _trackingState = "trackingState"; + + private NotificationTrackingProcess trackingProcess; + public final static String _trackingProcess = "trackingProcess"; + private String hash; public final static String _hash = "hash"; @@ -97,6 +116,46 @@ public class Notification { this.notifiedAt = notifiedAt; } + public NotificationNotifyState getNotifyState() { + return notifyState; + } + + public void setNotifyState(NotificationNotifyState notifyState) { + this.notifyState = notifyState; + } + + public NotificationContactType getNotifiedWith() { + return notifiedWith; + } + + public void setNotifiedWith(NotificationContactType notifiedWith) { + this.notifiedWith = notifiedWith; + } + + public Integer getRetryCount() { + return retryCount; + } + + public void setRetryCount(Integer retryCount) { + this.retryCount = retryCount; + } + + public NotificationTrackingState getTrackingState() { + return trackingState; + } + + public void setTrackingState(NotificationTrackingState trackingState) { + this.trackingState = trackingState; + } + + public NotificationTrackingProcess getTrackingProcess() { + return trackingProcess; + } + + public void setTrackingProcess(NotificationTrackingProcess trackingProcess) { + this.trackingProcess = trackingProcess; + } + public String getHash() { return hash; } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/UserNotificationPreference.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/UserNotificationPreference.java index 797ad7b92..d36614e65 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/UserNotificationPreference.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/UserNotificationPreference.java @@ -4,7 +4,7 @@ import gr.cite.notification.common.enums.NotificationContactType; import gr.cite.notification.data.composite.CompositeUserNotificationPreferenceId; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java index 26082a3ae..e31e5e747 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java @@ -70,6 +70,11 @@ public class NotificationBuilder extends BaseBuilder { + private String like; private Collection ids; private List excludeIds; private List userId; @@ -37,6 +35,11 @@ public class InAppNotificationQuery extends QueryBase { private Instant to; private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + public InAppNotificationQuery like(String value) { + this.like = value; + return this; + } + public InAppNotificationQuery ids(UUID value) { this.ids = List.of(value); return this; @@ -161,19 +164,23 @@ public class InAppNotificationQuery extends QueryBase { protected Predicate applyFilters(QueryContext queryContext) { List predicates = new ArrayList<>(); if (this.ids != null) { - predicates.add(queryContext.Root.get(InAppNotificationEntity.Field.ID).in(ids)); + predicates.add(queryContext.Root.get(InAppNotificationEntity.Field._id).in(ids)); + } + + if (this.like != null && !this.like.isEmpty()) { + predicates.add(queryContext.CriteriaBuilder.like(queryContext.Root.get(InAppNotificationEntity.Field._subject), this.like)); } if (this.excludeIds != null) { - predicates.add(queryContext.CriteriaBuilder.not(queryContext.Root.get(InAppNotificationEntity.Field.ID).in(ids))); + predicates.add(queryContext.CriteriaBuilder.not(queryContext.Root.get(InAppNotificationEntity.Field._id).in(ids))); } if (this.userId != null) { - predicates.add(queryContext.Root.get(InAppNotificationEntity.Field.USER_ID).in(userId)); + predicates.add(queryContext.Root.get(InAppNotificationEntity.Field._userId).in(userId)); } if (this.isActives != null) { - predicates.add(queryContext.Root.get(InAppNotificationEntity.Field.IS_ACTIVE).in(isActives)); + predicates.add(queryContext.Root.get(InAppNotificationEntity.Field._isActive).in(isActives)); } if (this.tenantIds != null) { @@ -181,23 +188,23 @@ public class InAppNotificationQuery extends QueryBase { } if (this.type != null) { - predicates.add(queryContext.Root.get(InAppNotificationEntity.Field.TYPE).in(this.type)); + predicates.add(queryContext.Root.get(InAppNotificationEntity.Field._type).in(this.type)); } if (this.trackingState != null) { - predicates.add(queryContext.Root.get(InAppNotificationEntity.Field.TRACKING_STATE).in(trackingState)); + predicates.add(queryContext.Root.get(InAppNotificationEntity.Field._trackingState).in(trackingState)); } if (isRead != null) { - predicates.add(isRead ? queryContext.CriteriaBuilder.isNotNull(queryContext.Root.get(InAppNotificationEntity.Field.READ_TIME)) : queryContext.CriteriaBuilder.isNull(queryContext.Root.get(InAppNotificationEntity.Field.READ_TIME))); + predicates.add(isRead ? queryContext.CriteriaBuilder.isNotNull(queryContext.Root.get(InAppNotificationEntity.Field._readTime)) : queryContext.CriteriaBuilder.isNull(queryContext.Root.get(InAppNotificationEntity.Field._readTime))); } if (from != null) { - predicates.add(queryContext.CriteriaBuilder.greaterThanOrEqualTo(queryContext.Root.get(InAppNotificationEntity.Field.CREATED_AT), from)); + predicates.add(queryContext.CriteriaBuilder.greaterThanOrEqualTo(queryContext.Root.get(InAppNotificationEntity.Field._createdAt), from)); } if (to != null) { - predicates.add(queryContext.CriteriaBuilder.lessThanOrEqualTo(queryContext.Root.get(InAppNotificationEntity.Field.CREATED_AT), from)); + predicates.add(queryContext.CriteriaBuilder.lessThanOrEqualTo(queryContext.Root.get(InAppNotificationEntity.Field._createdAt), from)); } if (predicates.size() > 0) { @@ -211,37 +218,37 @@ public class InAppNotificationQuery extends QueryBase { @Override protected String fieldNameOf(FieldResolver item) { - if (item.match(InAppNotification.Field.ID)) return InAppNotificationEntity.Field.ID; - else if (item.match(InAppNotification.Field.CREATED_AT)) return InAppNotificationEntity.Field.CREATED_AT; - else if (item.match(InAppNotification.Field.USER)) return InAppNotificationEntity.Field.USER_ID; - else if (item.match(InAppNotification.Field.IS_ACTIVE)) return InAppNotificationEntity.Field.IS_ACTIVE; - else if (item.match(InAppNotification.Field.READ_TIME)) return InAppNotificationEntity.Field.READ_TIME; - else if (item.match(InAppNotification.Field.TRACKING_STATE)) return InAppNotificationEntity.Field.TRACKING_STATE; - else if (item.match(InAppNotification.Field.BODY)) return InAppNotificationEntity.Field.BODY; - else if (item.match(InAppNotification.Field.EXTRA_DATA)) return InAppNotificationEntity.Field.EXTRA_DATA; - else if (item.match(InAppNotification.Field.PRIORITY)) return InAppNotificationEntity.Field.PRIORITY; - else if (item.match(InAppNotification.Field.SUBJECT)) return InAppNotificationEntity.Field.SUBJECT; + if (item.match(InAppNotification.Field.ID)) return InAppNotificationEntity.Field._id; + else if (item.match(InAppNotification.Field.CREATED_AT)) return InAppNotificationEntity.Field._createdAt; + else if (item.match(InAppNotification.Field.USER)) return InAppNotificationEntity.Field._userId; + else if (item.match(InAppNotification.Field.IS_ACTIVE)) return InAppNotificationEntity.Field._isActive; + else if (item.match(InAppNotification.Field.READ_TIME)) return InAppNotificationEntity.Field._readTime; + else if (item.match(InAppNotification.Field.TRACKING_STATE)) return InAppNotificationEntity.Field._trackingState; + else if (item.match(InAppNotification.Field.BODY)) return InAppNotificationEntity.Field._body; + else if (item.match(InAppNotification.Field.EXTRA_DATA)) return InAppNotificationEntity.Field._extraData; + else if (item.match(InAppNotification.Field.PRIORITY)) return InAppNotificationEntity.Field._priority; + else if (item.match(InAppNotification.Field.SUBJECT)) return InAppNotificationEntity.Field._subject; else if (item.match(InAppNotification.Field.TENANT)) return InAppNotificationEntity._tenantId; - else if (item.match(InAppNotification.Field.TYPE)) return InAppNotificationEntity.Field.TYPE; - else if (item.match(InAppNotification.Field.UPDATED_AT)) return InAppNotificationEntity.Field.UPDATED_AT; + else if (item.match(InAppNotification.Field.TYPE)) return InAppNotificationEntity.Field._type; + else if (item.match(InAppNotification.Field.UPDATED_AT)) return InAppNotificationEntity.Field._updatedAt; else return null; } @Override protected InAppNotificationEntity convert(Tuple tuple, Set columns) { InAppNotificationEntity item = new InAppNotificationEntity(); - item.setId(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.ID, UUID.class)); - item.setType(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.TYPE, UUID.class)); - item.setUserId(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.USER_ID, UUID.class)); + item.setId(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._id, UUID.class)); + item.setType(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._type, UUID.class)); + item.setUserId(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._userId, UUID.class)); item.setTenantId(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity._tenantId, UUID.class)); - item.setTrackingState(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.TRACKING_STATE, NotificationInAppTracking.class)); - item.setCreatedAt(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.CREATED_AT, Instant.class)); - item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.UPDATED_AT, Instant.class)); - item.setIsActive(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.IS_ACTIVE, IsActive.class)); - item.setExtraData(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.EXTRA_DATA, String.class)); - item.setBody(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.BODY, String.class)); - item.setSubject(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.SUBJECT, String.class)); - item.setPriority(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field.PRIORITY, InAppNotificationPriority.class)); + item.setTrackingState(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._trackingState, NotificationInAppTracking.class)); + item.setCreatedAt(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._createdAt, Instant.class)); + item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._updatedAt, Instant.class)); + item.setIsActive(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._isActive, IsActive.class)); + item.setExtraData(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._extraData, String.class)); + item.setBody(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._body, String.class)); + item.setSubject(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._subject, String.class)); + item.setPriority(QueryBase.convertSafe(tuple, columns, InAppNotificationEntity.Field._priority, InAppNotificationPriority.class)); return item; } } 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 index 1cf2024e2..1aaef85a0 100644 --- 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 @@ -11,9 +11,9 @@ 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 jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationQuery.java index a7590183a..461b22c8a 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/NotificationQuery.java @@ -12,8 +12,8 @@ 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.Predicate; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; @@ -35,6 +35,8 @@ public class NotificationQuery extends QueryBase { private List trackingState; private List trackingProgress; + + private Collection userIds; private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); public NotificationQuery ids(UUID value) { @@ -172,6 +174,21 @@ public class NotificationQuery extends QueryBase { return this; } + public NotificationQuery userIds(UUID value) { + this.userIds = List.of(value); + return this; + } + + public NotificationQuery userIds(UUID... value) { + this.userIds = Arrays.asList(value); + return this; + } + + public NotificationQuery userIds(Collection values) { + this.userIds = values; + return this; + } + public NotificationQuery ordering(Ordering ordering) { this.setOrder(ordering); return this; @@ -246,6 +263,10 @@ public class NotificationQuery extends QueryBase { predicates.add(queryContext.Root.get(NotificationEntity.Field._trackingProcess).in(trackingProgress)); } + if (this.userIds != null) { + predicates.add(queryContext.Root.get(NotificationEntity.Field._userId).in(userIds)); + } + if (predicates.size() > 0) { Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); return queryContext.CriteriaBuilder.and(predicatesArray); @@ -264,9 +285,15 @@ public class NotificationQuery extends QueryBase { else if (item.match(Notification._contactTypeHint)) return NotificationEntity.Field._contactTypeHint; else if (item.match(Notification._updatedAt)) return NotificationEntity.Field._updatedAt; else if (item.match(Notification._notifiedAt)) return NotificationEntity.Field._notifiedAt; - else if (item.match(Notification._tenant)) return NotificationEntity.Field._tenantId; - else if (item.match(Notification._user)) return NotificationEntity.Field._userId; + else if (item.prefix(Notification._tenant)) return NotificationEntity.Field._tenantId; + else if (item.prefix(Notification._user)) return NotificationEntity.Field._userId; else if (item.match(Notification._type)) return NotificationEntity.Field._type; + else if (item.match(Notification._notifyState)) return NotificationEntity.Field._notifyState; + else if (item.match(Notification._notifiedWith)) return NotificationEntity.Field._notifiedWith; + else if (item.match(Notification._trackingState)) return NotificationEntity.Field._trackingState; + else if (item.match(Notification._trackingProcess)) return NotificationEntity.Field._trackingProcess; + else if (item.match(Notification._retryCount)) return NotificationEntity.Field._retryCount; + else return null; } @@ -283,6 +310,12 @@ public class NotificationQuery extends QueryBase { item.setCreatedAt(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._createdAt, Instant.class)); item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._updatedAt, Instant.class)); item.setIsActive(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._isActive, IsActive.class)); + item.setNotifyState(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._notifyState, NotificationNotifyState.class)); + item.setNotifiedWith(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._notifiedWith, NotificationContactType.class)); + item.setTrackingState(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._trackingState, NotificationTrackingState.class)); + item.setTrackingProcess(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._trackingProcess, NotificationTrackingProcess.class)); + item.setRetryCount(QueryBase.convertSafe(tuple, columns, NotificationEntity.Field._retryCount, Integer.class)); + return item; } } 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 index fb5535de4..e35dae690 100644 --- 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 @@ -12,10 +12,10 @@ 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 javax.persistence.criteria.Subquery; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Subquery; import java.time.Instant; import java.util.*; @@ -198,9 +198,8 @@ public class NotificationTemplateQuery extends QueryBase subQuery = queryContext.Query.subquery(this.languageQuery.entityClass()); - this.applySubQuery(this.languageQuery, queryContext.CriteriaBuilder, subQuery); - predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._languageId)).value(subQuery)); + QueryContext subQuery = this.applySubQuery(this.languageQuery, queryContext, UUID.class, root -> root.get(NotificationTemplateEntity._id)); + predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(NotificationTemplateEntity._languageId)).value(subQuery.Query)); } if (this.channels != null) { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueInboxQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueInboxQuery.java index 4e9e6ccbe..eb7278c68 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueInboxQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueInboxQuery.java @@ -11,9 +11,9 @@ 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 jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueOutboxQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueOutboxQuery.java index b8f6f78b9..4dbea999c 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueOutboxQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/QueueOutboxQuery.java @@ -12,9 +12,9 @@ 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 jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantConfigurationQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantConfigurationQuery.java index e3758f168..c279355ed 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantConfigurationQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantConfigurationQuery.java @@ -12,9 +12,9 @@ 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 jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantQuery.java index 0b0c2d653..b97498d12 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/TenantQuery.java @@ -11,8 +11,8 @@ 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.Predicate; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserContactInfoQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserContactInfoQuery.java index 3d4986146..6454117b3 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserContactInfoQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserContactInfoQuery.java @@ -17,10 +17,10 @@ import gr.cite.tools.data.query.QueryContext; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; -import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Subquery; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Subquery; import java.time.Instant; import java.util.*; @@ -226,12 +226,11 @@ public class UserContactInfoQuery extends QueryBase { predicates.add(inClause); } if (this.userQuery != null) { - Subquery subQuery = queryContext.Query.subquery(this.userQuery.entityClass()); - this.applySubQuery(this.userQuery, queryContext.CriteriaBuilder, subQuery); - predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._userId)).value(subQuery)); + QueryContext subQuery = this.applySubQuery(this.userQuery, queryContext, UUID.class, root -> root.get(UserContactInfoEntity._userId)); + predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._userId)).value(subQuery.Query)); } - if (predicates.size() > 0) { + if (!predicates.isEmpty()) { Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); return queryContext.CriteriaBuilder.and(predicatesArray); } else { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserCredentialQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserCredentialQuery.java index e07a4cd7d..30cb14f14 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserCredentialQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserCredentialQuery.java @@ -13,9 +13,9 @@ 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 jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java index 977d3baa4..1d7a7d65e 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java @@ -10,8 +10,8 @@ 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.Predicate; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserQuery.java index 9fb299b91..6de90a27b 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserQuery.java @@ -14,9 +14,9 @@ import gr.cite.tools.data.query.QueryContext; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.RequestScope; -import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.Predicate; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserRoleQuery.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserRoleQuery.java index 33e882f1e..907b69a7e 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserRoleQuery.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/UserRoleQuery.java @@ -14,9 +14,9 @@ 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 jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; import java.time.Instant; import java.util.*; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/InAppNotificationLookup.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/InAppNotificationLookup.java index 899908759..bafcf699d 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/InAppNotificationLookup.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/InAppNotificationLookup.java @@ -13,6 +13,8 @@ import java.util.List; import java.util.UUID; public class InAppNotificationLookup extends Lookup { + + private String like; private Collection ids; private List excludeIds; private List userId; @@ -24,6 +26,14 @@ public class InAppNotificationLookup extends Lookup { private Instant from; private Instant to; + public String getLike() { + return like; + } + + public void setLike(String like) { + this.like = like; + } + public Collection getIds() { return ids; } @@ -106,6 +116,7 @@ public class InAppNotificationLookup extends Lookup { public InAppNotificationQuery enrich(QueryFactory queryFactory) { InAppNotificationQuery query = queryFactory.query(InAppNotificationQuery.class); + if (this.like != null) query.like(this.like); if (this.isActive != null) query.isActive(this.isActive); if (this.ids != null) query.ids(this.ids); if (this.type != null) query.type(this.type); diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationLookup.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationLookup.java index 28f40fcfb..ca27d07f7 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationLookup.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/query/lookup/NotificationLookup.java @@ -1,8 +1,6 @@ package gr.cite.notification.query.lookup; -import gr.cite.notification.common.enums.IsActive; -import gr.cite.notification.common.enums.NotificationContactType; -import gr.cite.notification.common.enums.NotificationNotifyState; +import gr.cite.notification.common.enums.*; import gr.cite.notification.query.NotificationQuery; import gr.cite.notification.query.TenantQuery; import gr.cite.tools.data.query.Lookup; @@ -16,14 +14,17 @@ import java.util.UUID; public class NotificationLookup extends Lookup { private List isActive; private List ids; - private List notifyState = new ArrayList<>(); - private List notifiedWith = new ArrayList<>(); + private List notifyState; + private List notifiedWith; private Boolean notifiedWithHasValue; private Boolean notifiedAtHasValue; - private List type = new ArrayList<>(); - private List contactType = new ArrayList<>(); + private List type; + private List contactType; private Integer retryThreshold; private Instant createdAfter; + private List trackingState; + private List trackingProcess; + private List userIds; public List getIsActive() { @@ -106,6 +107,30 @@ public class NotificationLookup extends Lookup { this.createdAfter = createdAfter; } + public List getTrackingState() { + return trackingState; + } + + public void setTrackingState(List trackingState) { + this.trackingState = trackingState; + } + + public List getTrackingProcess() { + return trackingProcess; + } + + public void setTrackingProcess(List trackingProcess) { + this.trackingProcess = trackingProcess; + } + + public List getUserIds() { + return userIds; + } + + public void setUserIds(List userIds) { + this.userIds = userIds; + } + public NotificationQuery enrich(QueryFactory queryFactory) { NotificationQuery query = queryFactory.query(NotificationQuery.class); if (this.isActive != null) query.isActive(this.isActive); @@ -118,6 +143,9 @@ public class NotificationLookup extends Lookup { if (this.notifiedWith != null) query.notifiedWith(this.notifiedWith); if (this.retryThreshold != null) query.retryThreshold(this.retryThreshold); if (this.type != null) query.type(this.type); + if (this.trackingProcess != null) query.trackingProgress(this.trackingProcess); + if (this.trackingState != null) query.trackingState(this.trackingState); + if (this.userIds != null) query.userIds(this.userIds); this.enrichCommon(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 index 9625e3600..938531dfb 100644 --- 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 @@ -14,6 +14,8 @@ public class NotificationTemplateLookup extends Lookup { private List isActive; + private List notificationTypes; + private List channels; private List kinds; @@ -26,6 +28,14 @@ public class NotificationTemplateLookup extends Lookup { return isActive; } + public List getNotificationTypes() { + return notificationTypes; + } + + public void setNotificationTypes(List notificationTypes) { + this.notificationTypes = notificationTypes; + } + public void setIsActive(List isActive) { this.isActive = isActive; } @@ -66,6 +76,7 @@ public class NotificationTemplateLookup extends Lookup { NotificationTemplateQuery query = queryFactory.query(NotificationTemplateQuery.class); if (this.ids != null) query.ids(this.ids); if (this.excludedIds != null) query.excludedIds(this.excludedIds); + if (this.notificationTypes != null) query.notificationTypes(this.notificationTypes); if (this.isActive != null) query.isActive(this.isActive); if (this.channels != null) query.channels(this.channels); if (this.kinds != null) query.kinds(this.kinds); diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java index 9a0d4c17f..ce310daf6 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java @@ -18,6 +18,8 @@ import org.springframework.stereotype.Service; import org.springframework.web.context.annotation.RequestScope; import javax.management.InvalidApplicationException; +import jakarta.persistence.Column; +import jakarta.persistence.Query; import java.time.Instant; import java.util.List; import java.util.UUID; @@ -66,37 +68,26 @@ public class InAppNotificationServiceImpl implements InAppNotificationService{ } } - public void markAsReadAllUserNotification(UUID userId) - { - try { - logger.debug(new DataLogEntry("marking as read all user in-app notifications", userId)); + public void markAsReadAllUserNotification(UUID userId) { + String entity = InAppNotificationEntity.class.getSimpleName(); - if (userId == null || userId.equals(new UUID(0L, 0L))) return; + String sqlQuery = "UPDATE " + entity + " as e SET "+ InAppNotificationEntity.Field._trackingState +" = :trackingState, "+ InAppNotificationEntity.Field._updatedAt + "= :updatedAt, " + InAppNotificationEntity.Field._readTime + " = :readTime " + + "WHERE e." + InAppNotificationEntity.Field._trackingState + " = :trackingStateCondition AND e."+ InAppNotificationEntity.Field._userId + " = :userId"; - List inAppNotificationEntities = this.queryFactory.query(InAppNotificationQuery.class) - .userId(userId) - .trackingState(NotificationInAppTracking.STORED) - .collect(); - Instant now = Instant.now(); - int bulkSize = this.entityManager.getBulkSize(); - this.entityManager.setBulkSize(inAppNotificationEntities.size()); - for (InAppNotificationEntity entity : inAppNotificationEntities) { - entity.setReadTime(now); - entity.setUpdatedAt(now); - entity.setTrackingState(NotificationInAppTracking.DELIVERED); - this.entityManager.merge(entity); - this.entityManager.persist(entity); - } - this.entityManager.setBulkSize(bulkSize); - } catch (InvalidApplicationException e) { - logger.error(e.getMessage(), e); - } + Query query = this.entityManager.createQuery(sqlQuery) + .setParameter("trackingState", NotificationInAppTracking.DELIVERED) + .setParameter("updatedAt", Instant.now()) + .setParameter("readTime", Instant.now()) + .setParameter("userId", userId) + .setParameter("trackingStateCondition", NotificationInAppTracking.STORED); + + int updateCount = query.executeUpdate(); } public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { - logger.debug("deleting tenant: {}", id); - this.authService.authorizeForce(Permission.DeleteNotification); + logger.debug("deleting inapp notification: {}", id); + this.authService.authorizeForce(Permission.DeleteInAppNotification); this.deleterFactory.deleter(InAppNotificationDeleter.class).deleteAndSaveByIds(List.of(id)); } } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/EmailMessageBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/EmailMessageBuilder.java index d1ea07c83..3ae78942d 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/EmailMessageBuilder.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/EmailMessageBuilder.java @@ -71,10 +71,17 @@ public class EmailMessageBuilder extends MessageBuilderBase implements MessageBu @Override public Message buildMessage(NotificationEntity notification) { MessageInfo messageInfo = this.messageInfoBuilderService.buildMessageInfo(notification); - NotificationProperties.Flow flow = this.flowMap.get("email").getOrDefault(notification.getType(), null); - if (flow == null) return null; - + if (messageInfo == null) { + logger.error("Could not retrieve message info for notification " + notification.getId()); + return null; + } + NotificationProperties.Flow options = this.flowMap.get("email").getOrDefault(notification.getType(), null); NotificationTemplate template = notificationTemplateService.lookupOverriddenTemplates(notification.getType(), NotificationTemplateChannel.Email, this.queryFactory.query(LanguageQuery.class).codes(messageInfo.getLanguage()).isActive(IsActive.Active).first().getId()); + + if (options == null && template == null) { + logger.error("Could not retrieve flow options for notification " + notification.getId() + " of type " + notification.getType()); + return null; + } String subjectTemplate = null; ReplaceResult subjectResult = null; String bodyTemplate = null; @@ -92,15 +99,15 @@ public class EmailMessageBuilder extends MessageBuilderBase implements MessageBu FieldFormatting bodyFormatting = this.buildFieldFormatting(template.getValue().getBodyFieldOptions()); bodyResult = this.buildTemplate(notification.getId(), bodyTemplate, messageInfo, template.getValue().getBodyFieldOptions(), bodyFormatting, cipherFields.get(notification.getType())); }else { - if(!StringUtils.isNullOrEmpty(flow.getSubjectKey())) subjectTemplate = messageInfo.getFields().stream().filter(fieldInfo -> fieldInfo.getKey().equals(flow.getSubjectKey())).findFirst().orElse(new FieldInfo()).getValue(); - if (StringUtils.isNullOrEmpty(subjectTemplate)) subjectTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), flow.getSubjectPath(), messageInfo.getLanguage()); - FieldFormatting subjectFormatting = this.buildFieldFormatting(flow.getSubjectFieldOptions()); - subjectResult = this.buildTemplate(notification.getId(), subjectTemplate, messageInfo, flow.getSubjectFieldOptions(), subjectFormatting, cipherFields.get(notification.getType())); + if(!StringUtils.isNullOrEmpty(options.getSubjectKey())) subjectTemplate = messageInfo.getFields().stream().filter(fieldInfo -> fieldInfo.getKey().equals(options.getSubjectKey())).findFirst().orElse(new FieldInfo()).getValue(); + if (StringUtils.isNullOrEmpty(subjectTemplate)) subjectTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), options.getSubjectPath(), messageInfo.getLanguage()); + FieldFormatting subjectFormatting = this.buildFieldFormatting(options.getSubjectFieldOptions()); + subjectResult = this.buildTemplate(notification.getId(), subjectTemplate, messageInfo, options.getSubjectFieldOptions(), subjectFormatting, cipherFields.get(notification.getType())); - if(!StringUtils.isNullOrEmpty(flow.getBodyKey())) bodyTemplate = messageInfo.getFields().stream().filter(fieldInfo -> fieldInfo.getKey().equals(flow.getBodyKey())).findFirst().orElse(new FieldInfo()).getValue(); - if (StringUtils.isNullOrEmpty(bodyTemplate)) bodyTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), flow.getBodyPath(), messageInfo.getLanguage()); - FieldFormatting bodyFormatting = this.buildFieldFormatting(flow.getBodyFieldOptions()); - bodyResult = this.buildTemplate(notification.getId(), bodyTemplate, messageInfo, flow.getBodyFieldOptions(), bodyFormatting, cipherFields.get(notification.getType())); + if(!StringUtils.isNullOrEmpty(options.getBodyKey())) bodyTemplate = messageInfo.getFields().stream().filter(fieldInfo -> fieldInfo.getKey().equals(options.getBodyKey())).findFirst().orElse(new FieldInfo()).getValue(); + if (StringUtils.isNullOrEmpty(bodyTemplate)) bodyTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), options.getBodyPath(), messageInfo.getLanguage()); + FieldFormatting bodyFormatting = this.buildFieldFormatting(options.getBodyFieldOptions()); + bodyResult = this.buildTemplate(notification.getId(), bodyTemplate, messageInfo, options.getBodyFieldOptions(), bodyFormatting, cipherFields.get(notification.getType())); } if (bodyResult != null && subjectResult != null) { diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java index 986a49b5f..e2e75c86b 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java @@ -3,20 +3,26 @@ package gr.cite.notification.service.message.builder; import gr.cite.notification.cache.NotificationTemplateCache; import gr.cite.notification.common.StringUtils; import gr.cite.notification.common.enums.InAppNotificationPriority; +import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.NotificationContactType; +import gr.cite.notification.common.enums.NotificationTemplateChannel; import gr.cite.notification.common.types.notification.FieldInfo; import gr.cite.notification.config.notification.NotificationConfig; import gr.cite.notification.config.notification.NotificationProperties; import gr.cite.notification.data.NotificationEntity; import gr.cite.notification.errorcode.ErrorThesaurusProperties; +import gr.cite.notification.model.NotificationTemplate; +import gr.cite.notification.query.LanguageQuery; import gr.cite.notification.service.formatting.FormattingService; import gr.cite.notification.service.message.common.MessageBuilderBase; import gr.cite.notification.service.message.infobuilder.MessageInfoBuilderService; import gr.cite.notification.service.message.model.InAppMessage; import gr.cite.notification.service.message.model.Message; import gr.cite.notification.service.message.model.MessageInfo; +import gr.cite.notification.service.notificationtemplate.NotificationTemplateService; import gr.cite.tools.cipher.CipherService; import gr.cite.tools.cipher.config.CipherProfileProperties; +import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.logging.LoggerService; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -36,6 +42,8 @@ public class InAppMessageBuilder extends MessageBuilderBase implements MessageBu private final MessageInfoBuilderService messageInfoBuilderService; private final Map> flowMap; private final NotificationProperties properties; + private final NotificationTemplateService notificationTemplateService; + private final QueryFactory queryFactory; @Autowired public InAppMessageBuilder(MessageInfoBuilderService messageInfoBuilderService, @@ -45,54 +53,79 @@ public class InAppMessageBuilder extends MessageBuilderBase implements MessageBu CipherService cipherService, CipherProfileProperties cipherProfileProperties, FormattingService formattingService, - NotificationTemplateCache cache) { + NotificationTemplateCache cache, NotificationTemplateService notificationTemplateService, QueryFactory queryFactory) { super(logger, errors, cipherService, cipherProfileProperties, formattingService, cache); this.messageInfoBuilderService = messageInfoBuilderService; this.flowMap = flowMap; this.properties = properties; + this.notificationTemplateService = notificationTemplateService; + this.queryFactory = queryFactory; } @Override public Message buildMessage(NotificationEntity notification) { MessageInfo messageInfo = this.messageInfoBuilderService.buildMessageInfo(notification); - if (messageInfo == null) - { + if (messageInfo == null) { logger.error("Could not retrieve message info for notification " + notification.getId()); return null; } NotificationProperties.Flow options = this.flowMap.get("in-app").getOrDefault(notification.getType(), null); + NotificationTemplate template = notificationTemplateService.lookupOverriddenTemplates(notification.getType(), NotificationTemplateChannel.Email, this.queryFactory.query(LanguageQuery.class).codes(messageInfo.getLanguage()).isActive(IsActive.Active).first().getId()); - if (options == null) - { + if (options == null && template == null) { logger.error("Could not retrieve flow options for notification " + notification.getId() + " of type " + notification.getType()); return null; } MessageBuilderBase.FieldCiphering ciphering = options.getCipherFields() == null || options.getCipherFields().isEmpty() ? new MessageBuilderBase.FieldCiphering() : new MessageBuilderBase.FieldCiphering(options.getCipherFields()); - String subjectTemplate = null; - if (!StringUtils.isNullOrEmpty(options.getSubjectKey())) subjectTemplate = messageInfo.getFields().stream().filter(x -> x.getKey().equals(options.getSubjectKey())).findFirst().orElse(new FieldInfo()).getValue(); - if (StringUtils.isNullOrEmpty(subjectTemplate)) subjectTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), options.getSubjectPath(), messageInfo.getLanguage()); - FieldFormatting subjectFormatting = this.buildFieldFormatting(options.getSubjectFieldOptions()); - ReplaceResult subjectResult = this.buildTemplate(notification.getId(), subjectTemplate, messageInfo, options.getSubjectFieldOptions(), subjectFormatting, ciphering); - + ReplaceResult subjectResult = null; String bodyTemplate = null; - if (!StringUtils.isNullOrEmpty(options.getBodyKey())) bodyTemplate = messageInfo.getFields().stream().filter(x -> x.getKey().equals(options.getBodyKey())).findFirst().orElse(new FieldInfo()).getValue(); - if (StringUtils.isNullOrEmpty(bodyTemplate)) bodyTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), options.getBodyPath(), messageInfo.getLanguage()); - FieldFormatting bodyFormatting = this.buildFieldFormatting(options.getBodyFieldOptions()); - ReplaceResult bodyResult = this.buildTemplate(notification.getId(), bodyTemplate, messageInfo, options.getBodyFieldOptions(), bodyFormatting, ciphering); + ReplaceResult bodyResult = null; + + // fallback + if ( template != null && template.getValue() != null){ + if (!StringUtils.isNullOrEmpty(template.getValue().getSubjectKey())) subjectTemplate = messageInfo.getFields().stream().filter(fieldInfo -> fieldInfo.getKey().equals(template.getValue().getSubjectKey())).findFirst().orElse(new FieldInfo()).getValue(); + if (StringUtils.isNullOrEmpty(subjectTemplate)) subjectTemplate = template.getValue().getSubjectText(); + FieldFormatting subjectFormatting = this.buildFieldFormatting(template.getValue().getSubjectFieldOptions()); + subjectResult = this.buildTemplate(notification.getId(), subjectTemplate, messageInfo, template.getValue().getSubjectFieldOptions(), subjectFormatting, ciphering); + + if(!StringUtils.isNullOrEmpty(template.getValue().getBodyKey())) bodyTemplate = messageInfo.getFields().stream().filter(fieldInfo -> fieldInfo.getKey().equals(template.getValue().getBodyKey())).findFirst().orElse(new FieldInfo()).getValue(); + if (StringUtils.isNullOrEmpty(bodyTemplate)) bodyTemplate = template.getValue().getBodyText(); + FieldFormatting bodyFormatting = this.buildFieldFormatting(template.getValue().getBodyFieldOptions()); + bodyResult = this.buildTemplate(notification.getId(), bodyTemplate, messageInfo, template.getValue().getBodyFieldOptions(), bodyFormatting, ciphering); + }else{ + if (!StringUtils.isNullOrEmpty(options.getSubjectKey())) subjectTemplate = messageInfo.getFields().stream().filter(x -> x.getKey().equals(options.getSubjectKey())).findFirst().orElse(new FieldInfo()).getValue(); + if (StringUtils.isNullOrEmpty(subjectTemplate)) subjectTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), options.getSubjectPath(), messageInfo.getLanguage()); + FieldFormatting subjectFormatting = this.buildFieldFormatting(options.getSubjectFieldOptions()); + subjectResult = this.buildTemplate(notification.getId(), subjectTemplate, messageInfo, options.getSubjectFieldOptions(), subjectFormatting, ciphering); + + if (!StringUtils.isNullOrEmpty(options.getBodyKey())) bodyTemplate = messageInfo.getFields().stream().filter(x -> x.getKey().equals(options.getBodyKey())).findFirst().orElse(new FieldInfo()).getValue(); + if (StringUtils.isNullOrEmpty(bodyTemplate)) bodyTemplate = this.lookupOrReadLocalizedFile(this.getTemplate().getTemplateCache(), options.getBodyPath(), messageInfo.getLanguage()); + FieldFormatting bodyFormatting = this.buildFieldFormatting(options.getBodyFieldOptions()); + bodyResult = this.buildTemplate(notification.getId(), bodyTemplate, messageInfo, options.getBodyFieldOptions(), bodyFormatting, ciphering); + } String priorityString = ""; + if ( template != null && template.getValue() != null){ + if (!StringUtils.isNullOrEmpty(template.getValue().getPriorityKey())) priorityString = messageInfo.getFields().stream().filter(x -> x.getKey().equals(template.getValue().getPriorityKey())).findFirst().orElse(new FieldInfo()).getValue(); + }else { + if (!StringUtils.isNullOrEmpty(options.getPriorityKey())) priorityString = messageInfo.getFields().stream().filter(x -> x.getKey().equals(options.getPriorityKey())).findFirst().orElse(new FieldInfo()).getValue(); + } - if (!StringUtils.isNullOrEmpty(options.getPriorityKey())) priorityString = messageInfo.getFields().stream().filter(x -> x.getKey().equals(options.getPriorityKey())).findFirst().orElse(new FieldInfo()).getValue(); InAppNotificationPriority inAppNotificationPriority = InAppNotificationPriority.NORMAL; + if (!StringUtils.isNullOrEmpty(priorityString)) { inAppNotificationPriority = InAppNotificationPriority.valueOf(priorityString.toLowerCase()); } List extraData = null; - if (options.getExtraDataKeys() != null && !options.getExtraDataKeys().isEmpty()) extraData = messageInfo.getFields().stream().filter(x -> options.getExtraDataKeys().contains(x.getKey())).collect(Collectors.toList()); + if (template != null && template.getValue() != null){ + if (template.getValue().getExtraDataKeys() != null && !template.getValue().getExtraDataKeys().isEmpty()) extraData = messageInfo.getFields().stream().filter(x -> template.getValue().getExtraDataKeys().contains(x.getKey())).collect(Collectors.toList()); + }else { + if (options.getExtraDataKeys() != null && !options.getExtraDataKeys().isEmpty()) extraData = messageInfo.getFields().stream().filter(x -> options.getExtraDataKeys().contains(x.getKey())).collect(Collectors.toList()); + } return new InAppMessage(subjectResult.getText(), bodyResult.getText(), notification.getType(), inAppNotificationPriority, extraData); } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java index 26dc42061..a8b5fff5b 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java @@ -181,7 +181,7 @@ public class NotificationServiceImpl implements NotificationService { @Override public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { - logger.debug("deleting tenant: {}", id); + logger.debug("deleting notification: {}", id); this.authService.authorizeForce(Permission.DeleteNotification); this.deleterFactory.deleter(NotificationDeleter.class).deleteAndSaveByIds(List.of(id)); } diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java index 2f67e396f..b3616e466 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java @@ -24,10 +24,10 @@ import gr.cite.tools.logging.LoggerService; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.EntityTransaction; -import javax.persistence.OptimisticLockException; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.OptimisticLockException; import java.time.Instant; import java.util.List; import java.util.UUID; diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/EmailNotifier.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/EmailNotifier.java index 8d46a8f8e..0030bda27 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/EmailNotifier.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/EmailNotifier.java @@ -8,18 +8,14 @@ import gr.cite.notification.service.contact.model.EmailContact; import gr.cite.notification.service.message.model.EmailMessage; import gr.cite.notification.service.message.model.Message; import gr.cite.tools.logging.LoggerService; -import org.slf4j.Logger; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; -import java.nio.charset.Charset; - import static java.nio.charset.StandardCharsets.UTF_8; @Component diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java index 79e2d397b..e92995be7 100644 --- a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java @@ -17,9 +17,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.EntityTransaction; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; import java.time.Instant; import java.util.UUID; @@ -66,9 +66,9 @@ public class InAppNotifier implements Notify{ inApp.setBody(inAppMessage.getBody()); inApp.setExtraData(inAppMessage.getExtraData() != null ? this.jsonHandlingService.toJsonSafe(inAppMessage.getExtraData()) : null); inApp.setCreatedAt(Instant.now()); + inApp.setUpdatedAt(Instant.now()); inApp.setTenantId(tenantScope.getTenant()); - inApp = entityManager.merge(inApp); entityManager.persist(inApp); InAppTrackingData trackingData = new InAppTrackingData(inApp.getId()); diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/tenant/TenantService.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/tenant/TenantService.java new file mode 100644 index 000000000..5e20f9f22 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/tenant/TenantService.java @@ -0,0 +1,23 @@ +package gr.cite.notification.service.tenant; + +import com.fasterxml.jackson.core.JsonProcessingException; +import gr.cite.notification.model.Tenant; +import gr.cite.notification.model.User; +import gr.cite.notification.model.persist.TenantTouchedIntegrationEventPersist; +import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist; +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 TenantService { + + Tenant persist(TenantTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException; + + void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/tenant/TenantServiceImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/tenant/TenantServiceImpl.java new file mode 100644 index 000000000..8437565d8 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/tenant/TenantServiceImpl.java @@ -0,0 +1,105 @@ +package gr.cite.notification.service.tenant; + +import com.fasterxml.jackson.core.JsonProcessingException; +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.enums.IsActive; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.data.TenantEntity; +import gr.cite.notification.model.Tenant; +import gr.cite.notification.model.builder.TenantBuilder; +import gr.cite.notification.model.deleter.TenantDeleter; +import gr.cite.notification.model.persist.TenantTouchedIntegrationEventPersist; +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 jakarta.persistence.EntityManager; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.EnumSet; +import java.util.List; +import java.util.UUID; + +@Service +public class TenantServiceImpl implements TenantService { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantServiceImpl.class)); + + private final AuthorizationService authorizationService; + + private final DeleterFactory deleterFactory; + + private final ConventionService conventionService; + + private final EntityManager entityManager; + + private final BuilderFactory builderFactory; + + public TenantServiceImpl(AuthorizationService authorizationService, + DeleterFactory deleterFactory, + ConventionService conventionService, + EntityManager entityManager, + BuilderFactory builderFactory) { + this.authorizationService = authorizationService; + this.deleterFactory = deleterFactory; + this.conventionService = conventionService; + this.entityManager = entityManager; + this.builderFactory = builderFactory; + } + + @Override + public Tenant persist(TenantTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + logger.debug(new MapLogEntry("persisting tenant").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeForce(Permission.EditTenant); + + Boolean isValid = this.conventionService.isValidGuid(model.getId()); + + TenantEntity data; + if (isValid) { + data = this.entityManager.find(TenantEntity.class, model.getId()); + if (data == null) { + data = new TenantEntity(); + data.setId(model.getId()); + data.setCode(model.getCode()); + data.setIsActive(IsActive.Active); + data.setCreatedAt(Instant.now()); + + this.entityManager.persist(data); + } else { + data.setCode(model.getCode()); + data.setUpdatedAt(Instant.now()); + data.setIsActive(IsActive.Active); + + this.entityManager.merge(data); + } + } else { + throw new MyApplicationException("Not valid tenant id"); + } + + this.entityManager.flush(); + + return this.builderFactory.builder(TenantBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, Tenant._id), data); + } + + @Override + public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug("deleting Tenant: {}", id); + + this.authorizationService.authorizeForce(Permission.DeleteTenant); + + this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id)); + } + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/user/UserService.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/user/UserService.java new file mode 100644 index 000000000..088b95202 --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/user/UserService.java @@ -0,0 +1,21 @@ +package gr.cite.notification.service.user; + +import com.fasterxml.jackson.core.JsonProcessingException; +import gr.cite.notification.model.User; +import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist; +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 UserService { + + User persist(UserTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException; + + void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; + +} diff --git a/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/user/UserServiceImpl.java b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/user/UserServiceImpl.java new file mode 100644 index 000000000..5b8318aea --- /dev/null +++ b/dmp-backend/notification-service/notification/src/main/java/gr/cite/notification/service/user/UserServiceImpl.java @@ -0,0 +1,110 @@ +package gr.cite.notification.service.user; + +import com.fasterxml.jackson.core.JsonProcessingException; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.authorization.OwnedResource; +import gr.cite.notification.authorization.Permission; +import gr.cite.notification.common.JsonHandlingService; +import gr.cite.notification.common.enums.IsActive; +import gr.cite.notification.convention.ConventionService; +import gr.cite.notification.data.UserEntity; +import gr.cite.notification.model.User; +import gr.cite.notification.model.builder.UserBuilder; +import gr.cite.notification.model.deleter.UserDeleter; +import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist; +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 jakarta.persistence.EntityManager; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Service; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.EnumSet; +import java.util.List; +import java.util.UUID; + +@Service +public class UserServiceImpl implements UserService { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserServiceImpl.class)); + + private final AuthorizationService authorizationService; + + private final DeleterFactory deleterFactory; + + private final ConventionService conventionService; + + private final EntityManager entityManager; + + private final BuilderFactory builderFactory; + + public UserServiceImpl(AuthorizationService authorizationService, + DeleterFactory deleterFactory, + ConventionService conventionService, + EntityManager entityManager, + BuilderFactory builderFactory) { + this.authorizationService = authorizationService; + this.deleterFactory = deleterFactory; + this.conventionService = conventionService; + this.entityManager = entityManager; + this.builderFactory = builderFactory; + } + + @Override + public User persist(UserTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + logger.debug(new MapLogEntry("persisting user").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeAtLeastOneForce(model.getId() != null ? List.of(new OwnedResource(model.getId())) : null, Permission.EditUser); + + Boolean isValid = this.conventionService.isValidGuid(model.getId()); + + UserEntity data; + if (isValid) { + data = this.entityManager.find(UserEntity.class, model.getId()); + if (data == null) { + data = new UserEntity(); + data.setId(model.getId()); + data.setName(model.getFirstName() + " " + model.getLastName()); + data.setCreatedAt(Instant.now()); + data.setUpdatedAt(Instant.now()); + data.setIsActive(IsActive.Active); + + this.entityManager.persist(data); + } else { + data.setName(model.getFirstName() + " " + model.getLastName()); + data.setUpdatedAt(Instant.now()); + data.setIsActive(IsActive.Active); + + this.entityManager.merge(data); + } + } else { + throw new MyApplicationException("Not valid user id"); + } + + this.entityManager.flush(); + + return this.builderFactory.builder(UserBuilder.class).authorize(EnumSet.of(AuthorizationFlags.None)).build(BaseFieldSet.build(fields, User._id), data); + } + + @Override + public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug("deleting User: {}", id); + + this.authorizationService.authorizeForce(Permission.DeleteUser); + + this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id)); + } + +} diff --git a/dmp-backend/notification-service/pom.xml b/dmp-backend/notification-service/pom.xml index 63db37937..02ab51031 100644 --- a/dmp-backend/notification-service/pom.xml +++ b/dmp-backend/notification-service/pom.xml @@ -4,31 +4,135 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 2.6.4 - - - gr.cite notification-service-parent Argos Notification Parent 1.0.0 pom + + org.springframework.boot + spring-boot-starter-parent + 3.1.2 + + + notification notification-web - 11 - 11 + 21 + 21 + 21 + 21 + + org.springframework + spring-context-support + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.hibernate.orm + hibernate-core + compile + 6.3.1.Final + + + org.hibernate.orm + hibernate-c3p0 + compile + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + + + + com.fasterxml.jackson.core + jackson-core + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.13.3 + + + + com.fasterxml.jackson.module + jackson-module-jaxb-annotations + + + + + javax.xml.bind + jaxb-api + 2.3.1 + + + + + jakarta.annotation + jakarta.annotation-api + + + + + jakarta.validation + jakarta.validation-api + + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + + gr.cite + data-tools + 2.1.2 + + + + gr.cite + logging + 2.1.0 + + + + gr.cite + oidc-authn + 2.2.1 + + + gr.cite + oidc-authz + 2.1.0 + + + + gr.cite + rabbitmq-core + 1.0.0 + + gr.cite queue-inbox @@ -70,6 +174,20 @@ + + + cite-dev + + + cite-maven + CITE Maven Repository + https://crepo.cite.gr/repository/cite-maven/ + + + + true + + \ No newline at end of file diff --git a/dmp-backend/pom.xml b/dmp-backend/pom.xml index 8660d01cb..a84638b7f 100644 --- a/dmp-backend/pom.xml +++ b/dmp-backend/pom.xml @@ -330,7 +330,7 @@ gr.cite validation - 2.1.0 + 3.0.1 gr.cite diff --git a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java index 3015b3784..ba1dac251 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java +++ b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java @@ -1,28 +1,17 @@ package eu.eudat; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.databind.util.StdDateFormat; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import eu.eudat.data.BaseEntity; -import org.jetbrains.annotations.NotNull; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.scheduling.annotation.EnableAsync; -import java.util.List; - @SpringBootApplication(scanBasePackages = { "eu.eudat", "eu.eudat.depositinterface", @@ -35,7 +24,6 @@ import java.util.List; "eu.eudat.data"}) @EnableAsync public class EuDatApplication extends SpringBootServletInitializer { - @Bean @Primary public ObjectMapper primaryObjectMapper(Jackson2ObjectMapperBuilder builder) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/ExecutorServiceConfig.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/ExecutorServiceConfig.java deleted file mode 100644 index 78da24f79..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/ExecutorServiceConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.eudat.configurations; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.task.TaskExecutor; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Created by ikalyvas on 9/26/2018. - */ -@Configuration -public class ExecutorServiceConfig { - - @Bean - public Executor asyncExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setCorePoolSize(2); - executor.setMaxPoolSize(2); - executor.setQueueCapacity(500); - executor.setThreadNamePrefix("Rules-"); - executor.initialize(); - return executor; - } -} \ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java deleted file mode 100644 index 266c23ede..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package eu.eudat.configurations; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.Module; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.module.SimpleModule; -import eu.eudat.criteria.entities.Criteria; -import eu.eudat.criteria.serialzier.CriteriaSerializer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.ArrayList; - -@Configuration -public class JacksonConfiguration { - @Bean - public ObjectMapper buildObjectMapper() { - - ArrayList modules = new ArrayList<>(); - SimpleModule criteriaSerializerModule = new SimpleModule(); - criteriaSerializerModule.addDeserializer(Criteria.class, new CriteriaSerializer()); - modules.add(criteriaSerializerModule); - - return new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModules(modules); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfiguration.java deleted file mode 100644 index 4a7f08672..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfiguration.java +++ /dev/null @@ -1,12 +0,0 @@ -package eu.eudat.configurations.dynamicfunder; - -import eu.eudat.configurations.dynamicfunder.entities.Configuration; -import eu.eudat.models.data.dynamicfields.DynamicField; - -import java.util.List; - -public interface DynamicFunderConfiguration { - Configuration getConfiguration(); - - List getFields(); -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java deleted file mode 100644 index eca3ab522..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java +++ /dev/null @@ -1,85 +0,0 @@ -package eu.eudat.configurations.dynamicfunder; - -import eu.eudat.configurations.dynamicfunder.entities.Configuration; -import eu.eudat.configurations.dynamicfunder.entities.Property; -import eu.eudat.models.data.dynamicfields.Dependency; -import eu.eudat.models.data.dynamicfields.DynamicField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.LinkedList; -import java.util.List; - -@Service("dynamicFunderConfiguration") -@Profile("devel") -public class DynamicFunderConfigurationDevelImpl implements DynamicFunderConfiguration { - private static final Logger logger = LoggerFactory.getLogger(DynamicFunderConfigurationDevelImpl.class); - - private Configuration configuration; - private List fields; - private Environment environment; - - public DynamicFunderConfigurationDevelImpl(Environment environment) { - this.environment = environment; - } - - @Override - public Configuration getConfiguration() { - if (this.configuration != null) return this.configuration; - String fileUrl = this.environment.getProperty("configuration.dynamicFunderUrl"); - logger.info("Loaded also config file: " + fileUrl); - String current = null; - InputStream is = null; - try { - current = new java.io.File(".").getCanonicalPath(); - - JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///"+ current + "/web/src/main/resources/FunderConfiguration.xml").openStream(); - this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); - } catch (Exception ex) { - logger.error("Cannot find in folder" + current, ex); - } finally { - try { - if (is != null) is.close(); - } catch (IOException e) { - logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); - } - } - return this.configuration; - } - - @Override - public List getFields() { - if (this.fields != null) return this.fields; - Configuration configuration = this.getConfiguration(); - List fields = new LinkedList<>(); - List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { - DynamicField dynamicField = new DynamicField(); - dynamicField.setId(item.getId()); - dynamicField.setName(item.getName()); - dynamicField.setQueryProperty(item.getQueryProperty()); - dynamicField.setRequired(item.getRequired()); - List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { - Dependency modelDependency = new Dependency(); - modelDependency.setId(dependency.getId()); - modelDependency.setQueryProperty(dependency.getQueryProperty()); - dependencies.add(modelDependency); - }); - dynamicField.setDependencies(dependencies); - fields.add(dynamicField); - }); - this.fields = fields; - return fields; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java deleted file mode 100644 index 30f2124a5..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java +++ /dev/null @@ -1,86 +0,0 @@ -package eu.eudat.configurations.dynamicfunder; - -import eu.eudat.configurations.dynamicfunder.entities.Configuration; -import eu.eudat.configurations.dynamicfunder.entities.Property; -import eu.eudat.models.data.dynamicfields.Dependency; -import eu.eudat.models.data.dynamicfields.DynamicField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.file.Paths; -import java.util.LinkedList; -import java.util.List; - -@Service("dynamicFunderConfiguration") -@Profile({ "production", "staging", "docker" }) -public class DynamicFunderConfigurationProdImpl implements DynamicFunderConfiguration { - private static final Logger logger = LoggerFactory.getLogger(DynamicFunderConfigurationProdImpl.class); - - private Configuration configuration; - private List fields; - private Environment environment; - - public DynamicFunderConfigurationProdImpl(Environment environment) { - this.environment = environment; - } - - @Override - public Configuration getConfiguration() { - if (this.configuration != null) return this.configuration; - String fileUrl = this.environment.getProperty("configuration.dynamicFunderUrl"); - logger.info("Loaded also config file: " + fileUrl); - String current = null; - InputStream is = null; - try { - current = new java.io.File(".").getCanonicalPath(); - - JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); - this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); - } catch (Exception ex) { - logger.error("Cannot find in folder" + current, ex); - } finally { - try { - if (is != null) is.close(); - } catch (IOException e) { - logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); - } - } - return this.configuration; - } - - @Override - public List getFields() { - if (this.fields != null) return this.fields; - Configuration configuration = this.getConfiguration(); - List fields = new LinkedList<>(); - List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { - DynamicField dynamicField = new DynamicField(); - dynamicField.setId(item.getId()); - dynamicField.setName(item.getName()); - dynamicField.setQueryProperty(item.getQueryProperty()); - dynamicField.setRequired(item.getRequired()); - List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { - Dependency modelDependency = new Dependency(); - modelDependency.setId(dependency.getId()); - modelDependency.setQueryProperty(dependency.getQueryProperty()); - dependencies.add(modelDependency); - }); - dynamicField.setDependencies(dependencies); - fields.add(dynamicField); - }); - this.fields = fields; - return fields; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Configuration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Configuration.java deleted file mode 100644 index 3a65659c1..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Configuration.java +++ /dev/null @@ -1,31 +0,0 @@ -package eu.eudat.configurations.dynamicfunder.entities; - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import jakarta.xml.bind.annotation.XmlRootElement; -import java.util.List; - -@XmlRootElement -public class Configuration { - private List configurationProperties; - private MainProperty mainExternalField; - - public MainProperty getMainExternalField() { - return mainExternalField; - } - - @XmlElement(name = "mainExternalField") - public void setMainExternalField(MainProperty mainExternalField) { - this.mainExternalField = mainExternalField; - } - - public List getConfigurationProperties() { - return configurationProperties; - } - - @XmlElementWrapper - @XmlElement(name = "property") - public void setConfigurationProperties(List configurationProperties) { - this.configurationProperties = configurationProperties; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Dependency.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Dependency.java deleted file mode 100644 index 0d7288ec9..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Dependency.java +++ /dev/null @@ -1,26 +0,0 @@ -package eu.eudat.configurations.dynamicfunder.entities; - -import jakarta.xml.bind.annotation.XmlElement; - -public class Dependency { - private String id; - private String queryProperty; - - public String getId() { - return id; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Language.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Language.java deleted file mode 100644 index 1dfd36c00..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Language.java +++ /dev/null @@ -1,26 +0,0 @@ -package eu.eudat.configurations.dynamicfunder.entities; - -import jakarta.xml.bind.annotation.XmlElement; - -public class Language { - private String key; - private String languageKey; - - public String getKey() { - return key; - } - - @XmlElement(name = "key") - public void setKey(String key) { - this.key = key; - } - - public String getLanguageKey() { - return languageKey; - } - - @XmlElement(name = "languageKey") - public void setLanguageKey(String languageKey) { - this.languageKey = languageKey; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/MainProperty.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/MainProperty.java deleted file mode 100644 index d82646aaa..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/MainProperty.java +++ /dev/null @@ -1,103 +0,0 @@ -package eu.eudat.configurations.dynamicfunder.entities; - -import eu.eudat.service.reference.external.config.UrlConfiguration; - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import java.util.List; - -public class MainProperty { - private String id; - private String name; - private String queryProperty; - private String externalFieldId; - private List urlConfig; - private String externalFieldLabel; - private List dependencies; - private Boolean required; - private List language; - - - public String getId() { - return id; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - @XmlElement(name = "name") - public void setName(String name) { - this.name = name; - } - - public String getExternalFieldId() { - return externalFieldId; - } - - @XmlElement(name = "externalFieldId") - public void setExternalFieldId(String externalFieldId) { - this.externalFieldId = externalFieldId; - } - - public String getExternalFieldLabel() { - return externalFieldLabel; - } - - @XmlElement(name = "externalFieldLabel") - public void setExternalFieldLabel(String externalFieldLabel) { - this.externalFieldLabel = externalFieldLabel; - } - - public List getDependencies() { - return dependencies; - } - - @XmlElementWrapper - @XmlElement(name = "dependency") - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Boolean getRequired() { - return required; - } - - @XmlElement(name = "required") - public void setRequired(Boolean required) { - this.required = required; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } - - public List getUrlConfig() { - return urlConfig; - } - - @XmlElement(name = "urlConfig") - public void setUrlConfig(List urlConfig) { - this.urlConfig = urlConfig; - } - - public List getLanguage() { - return language; - } - - @XmlElementWrapper - @XmlElement(name = "languageProperty") - public void setLanguage(List language) { - this.language = language; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Property.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Property.java deleted file mode 100644 index 2f5172f0e..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/entities/Property.java +++ /dev/null @@ -1,91 +0,0 @@ -package eu.eudat.configurations.dynamicfunder.entities; - - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import java.util.List; - -public class Property { - private String id; - private String name; - private String sourceUrl; - private String queryProperty; - private String externalFieldId; - private String externalFieldLabel; - private List dependencies; - private Boolean required; - - - public String getId() { - return id; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - @XmlElement(name = "name") - public void setName(String name) { - this.name = name; - } - - public String getSourceUrl() { - return sourceUrl; - } - - @XmlElement(name = "sourceUrl") - public void setSourceUrl(String sourceUrl) { - this.sourceUrl = sourceUrl; - } - - public String getExternalFieldId() { - return externalFieldId; - } - - @XmlElement(name = "externalFieldId") - public void setExternalFieldId(String externalFieldId) { - this.externalFieldId = externalFieldId; - } - - public String getExternalFieldLabel() { - return externalFieldLabel; - } - - @XmlElement(name = "externalFieldLabel") - public void setExternalFieldLabel(String externalFieldLabel) { - this.externalFieldLabel = externalFieldLabel; - } - - public List getDependencies() { - return dependencies; - } - - @XmlElementWrapper - @XmlElement(name = "dependency") - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Boolean getRequired() { - return required; - } - - @XmlElement(name = "required") - public void setRequired(Boolean required) { - this.required = required; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfiguration.java deleted file mode 100644 index efe07f403..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package eu.eudat.configurations.dynamicgrant; - -import eu.eudat.configurations.dynamicgrant.entities.Configuration; -import eu.eudat.models.data.dynamicfields.DynamicField; - -import java.util.List; - -/** - * Created by ikalyvas on 3/23/2018. - */ -public interface DynamicGrantConfiguration { - Configuration getConfiguration(); - - List getFields(); -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java deleted file mode 100644 index eb4fc308c..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package eu.eudat.configurations.dynamicgrant; - -import eu.eudat.configurations.dynamicgrant.entities.Configuration; -import eu.eudat.configurations.dynamicgrant.entities.Property; -import eu.eudat.models.data.dynamicfields.Dependency; -import eu.eudat.models.data.dynamicfields.DynamicField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.LinkedList; -import java.util.List; - -/** - * Created by ikalyvas on 5/4/2018. - */ - -@Service("dynamicGrantConfiguration") -@Profile("devel") -public class DynamicGrantConfigurationDevelImpl implements DynamicGrantConfiguration { - private static final Logger logger = LoggerFactory.getLogger(DynamicGrantConfigurationDevelImpl.class); - - private Configuration configuration; - - private List fields; - - private Environment environment; - - @Autowired - public DynamicGrantConfigurationDevelImpl(Environment environment) { - this.environment = environment; - } - - @Override - public Configuration getConfiguration() { - if (this.configuration != null) return this.configuration; - String fileUrl = this.environment.getProperty("configuration.dynamicGrantUrl"); - logger.info("Loaded also config file: " + fileUrl); - String current = null; - InputStream is = null; - try { - current = new java.io.File(".").getCanonicalPath(); - - JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///"+ current + "/web/src/main/resources/GrantConfiguration.xml").openStream(); - this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); - } catch (Exception ex) { - logger.error("Cannot find in folder" + current, ex); - } finally { - try { - if (is != null) is.close(); - } catch (IOException e) { - logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); - } - } - return this.configuration; - } - - @Override - public List getFields() { - if (this.fields != null) return this.fields; - Configuration configuration = this.getConfiguration(); - List fields = new LinkedList<>(); - List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { - DynamicField dynamicField = new DynamicField(); - dynamicField.setId(item.getId()); - dynamicField.setName(item.getName()); - dynamicField.setQueryProperty(item.getQueryProperty()); - dynamicField.setRequired(item.getRequired()); - List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { - Dependency modelDependency = new Dependency(); - modelDependency.setId(dependency.getId()); - modelDependency.setQueryProperty(dependency.getQueryProperty()); - dependencies.add(modelDependency); - }); - dynamicField.setDependencies(dependencies); - fields.add(dynamicField); - }); - this.fields = fields; - return fields; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java deleted file mode 100644 index e23dd1240..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package eu.eudat.configurations.dynamicgrant; - -import eu.eudat.configurations.dynamicgrant.entities.Configuration; -import eu.eudat.configurations.dynamicgrant.entities.Property; -import eu.eudat.models.data.dynamicfields.Dependency; -import eu.eudat.models.data.dynamicfields.DynamicField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.file.Paths; -import java.util.LinkedList; -import java.util.List; - -/** - * Created by ikalyvas on 3/23/2018. - */ -@Service("dynamicGrantConfiguration") -@Profile({ "production", "staging", "docker" }) -public class DynamicGrantConfigurationProdImpl implements DynamicGrantConfiguration { - private static final Logger logger = LoggerFactory.getLogger(DynamicGrantConfigurationProdImpl.class); - - private Configuration configuration; - - private List fields; - - private Environment environment; - - @Autowired - public DynamicGrantConfigurationProdImpl(Environment environment) { - this.environment = environment; - } - - @Override - public Configuration getConfiguration() { - if (this.configuration != null) return this.configuration; - String fileUrl = this.environment.getProperty("configuration.dynamicGrantUrl"); - logger.info("Loaded also config file: " + fileUrl); - String current = null; - InputStream is = null; - try { - current = new java.io.File(".").getCanonicalPath(); - - JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); - this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); - } catch (Exception ex) { - logger.error("Cannot find in folder" + current, ex); - } finally { - try { - if (is != null) is.close(); - } catch (IOException e) { - logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); - } - } - return this.configuration; - } - - @Override - public List getFields() { - if (this.fields != null) return this.fields; - Configuration configuration = this.getConfiguration(); - List fields = new LinkedList<>(); - List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { - DynamicField dynamicField = new DynamicField(); - dynamicField.setId(item.getId()); - dynamicField.setName(item.getName()); - dynamicField.setQueryProperty(item.getQueryProperty()); - dynamicField.setRequired(item.getRequired()); - List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { - Dependency modelDependency = new Dependency(); - modelDependency.setId(dependency.getId()); - modelDependency.setQueryProperty(dependency.getQueryProperty()); - dependencies.add(modelDependency); - }); - dynamicField.setDependencies(dependencies); - fields.add(dynamicField); - }); - this.fields = fields; - return fields; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Configuration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Configuration.java deleted file mode 100644 index 1fede94fa..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Configuration.java +++ /dev/null @@ -1,34 +0,0 @@ -package eu.eudat.configurations.dynamicgrant.entities; - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import jakarta.xml.bind.annotation.XmlRootElement; -import java.util.List; - -/** - * Created by ikalyvas on 3/23/2018. - */ -@XmlRootElement -public class Configuration { - private List configurationProperties; - private MainProperty mainExternalField; - - public MainProperty getMainExternalField() { - return mainExternalField; - } - - @XmlElement(name = "mainExternalField") - public void setMainExternalField(MainProperty mainExternalField) { - this.mainExternalField = mainExternalField; - } - - public List getConfigurationProperties() { - return configurationProperties; - } - - @XmlElementWrapper - @XmlElement(name = "property") - public void setConfigurationProperties(List configurationProperties) { - this.configurationProperties = configurationProperties; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Dependency.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Dependency.java deleted file mode 100644 index 8eb96a9b1..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Dependency.java +++ /dev/null @@ -1,29 +0,0 @@ -package eu.eudat.configurations.dynamicgrant.entities; - -import jakarta.xml.bind.annotation.XmlElement; - -/** - * Created by ikalyvas on 3/23/2018. - */ -public class Dependency { - private String id; - private String queryProperty; - - public String getId() { - return id; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Language.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Language.java deleted file mode 100644 index 47c024643..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Language.java +++ /dev/null @@ -1,29 +0,0 @@ -package eu.eudat.configurations.dynamicgrant.entities; - -import jakarta.xml.bind.annotation.XmlElement; - -/** - * Created by ikalyvas on 3/28/2018. - */ -public class Language { - private String key; - private String languageKey; - - public String getKey() { - return key; - } - - @XmlElement(name = "key") - public void setKey(String key) { - this.key = key; - } - - public String getLanguageKey() { - return languageKey; - } - - @XmlElement(name = "languageKey") - public void setLanguageKey(String languageKey) { - this.languageKey = languageKey; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/MainProperty.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/MainProperty.java deleted file mode 100644 index cc0a834c0..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/MainProperty.java +++ /dev/null @@ -1,106 +0,0 @@ -package eu.eudat.configurations.dynamicgrant.entities; - -import eu.eudat.service.reference.external.config.UrlConfiguration; - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import java.util.List; - -/** - * Created by ikalyvas on 3/28/2018. - */ -public class MainProperty { - private String id; - private String name; - private String queryProperty; - private String externalFieldId; - private List urlConfig; - private String externalFieldLabel; - private List dependencies; - private Boolean required; - private List language; - - - public String getId() { - return id; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - @XmlElement(name = "name") - public void setName(String name) { - this.name = name; - } - - public String getExternalFieldId() { - return externalFieldId; - } - - @XmlElement(name = "externalFieldId") - public void setExternalFieldId(String externalFieldId) { - this.externalFieldId = externalFieldId; - } - - public String getExternalFieldLabel() { - return externalFieldLabel; - } - - @XmlElement(name = "externalFieldLabel") - public void setExternalFieldLabel(String externalFieldLabel) { - this.externalFieldLabel = externalFieldLabel; - } - - public List getDependencies() { - return dependencies; - } - - @XmlElementWrapper - @XmlElement(name = "dependency") - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Boolean getRequired() { - return required; - } - - @XmlElement(name = "required") - public void setRequired(Boolean required) { - this.required = required; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } - - public List getUrlConfig() { - return urlConfig; - } - - @XmlElement(name = "urlConfig") - public void setUrlConfig(List urlConfig) { - this.urlConfig = urlConfig; - } - - public List getLanguage() { - return language; - } - - @XmlElementWrapper - @XmlElement(name = "languageProperty") - public void setLanguage(List language) { - this.language = language; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Property.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Property.java deleted file mode 100644 index ec31ce285..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/entities/Property.java +++ /dev/null @@ -1,93 +0,0 @@ -package eu.eudat.configurations.dynamicgrant.entities; - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import java.util.List; - -/** - * Created by ikalyvas on 3/23/2018. - */ -public class Property { - private String id; - private String name; - private String sourceUrl; - private String queryProperty; - private String externalFieldId; - private String externalFieldLabel; - private List dependencies; - private Boolean required; - - - public String getId() { - return id; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - @XmlElement(name = "name") - public void setName(String name) { - this.name = name; - } - - public String getSourceUrl() { - return sourceUrl; - } - - @XmlElement(name = "sourceUrl") - public void setSourceUrl(String sourceUrl) { - this.sourceUrl = sourceUrl; - } - - public String getExternalFieldId() { - return externalFieldId; - } - - @XmlElement(name = "externalFieldId") - public void setExternalFieldId(String externalFieldId) { - this.externalFieldId = externalFieldId; - } - - public String getExternalFieldLabel() { - return externalFieldLabel; - } - - @XmlElement(name = "externalFieldLabel") - public void setExternalFieldLabel(String externalFieldLabel) { - this.externalFieldLabel = externalFieldLabel; - } - - public List getDependencies() { - return dependencies; - } - - @XmlElementWrapper - @XmlElement(name = "dependency") - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Boolean getRequired() { - return required; - } - - @XmlElement(name = "required") - public void setRequired(Boolean required) { - this.required = required; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfiguration.java deleted file mode 100644 index 825a00c9f..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfiguration.java +++ /dev/null @@ -1,12 +0,0 @@ -package eu.eudat.configurations.dynamicproject; - -import eu.eudat.configurations.dynamicproject.entities.Configuration; -import eu.eudat.models.data.dynamicfields.DynamicField; - -import java.util.List; - -public interface DynamicProjectConfiguration { - Configuration getConfiguration(); - - List getFields(); -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java deleted file mode 100644 index f385580bf..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -package eu.eudat.configurations.dynamicproject; - -import eu.eudat.configurations.dynamicproject.entities.Configuration; -import eu.eudat.configurations.dynamicproject.entities.Property; -import eu.eudat.models.data.dynamicfields.Dependency; -import eu.eudat.models.data.dynamicfields.DynamicField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.LinkedList; -import java.util.List; - -@Service("dynamicProjectConfiguration") -@Profile("devel") -public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfiguration{ - private static final Logger logger = LoggerFactory.getLogger(DynamicProjectConfigurationDevelImpl.class); - - private Configuration configuration; - private List fields; - private Environment environment; - - @Autowired - public DynamicProjectConfigurationDevelImpl(Environment environment) { - this.environment = environment; - } - - @Override - public Configuration getConfiguration() { - if (this.configuration != null) return this.configuration; - String fileUrl = this.environment.getProperty("configuration.dynamicProjectUrl"); - logger.info("Loaded also config file: " + fileUrl); - String current = null; - InputStream is = null; - try { - current = new java.io.File(".").getCanonicalPath(); - - JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///"+ current + "/web/src/main/resources/ProjectConfiguration.xml").openStream(); - this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); - } catch (Exception ex) { - logger.error("Cannot find in folder" + current, ex); - } finally { - try { - if (is != null) is.close(); - } catch (IOException e) { - logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); - } - } - return this.configuration; - } - - @Override - public List getFields() { - if (this.fields != null) return this.fields; - Configuration configuration = this.getConfiguration(); - List fields = new LinkedList<>(); - List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { - DynamicField dynamicField = new DynamicField(); - dynamicField.setId(item.getId()); - dynamicField.setName(item.getName()); - dynamicField.setQueryProperty(item.getQueryProperty()); - dynamicField.setRequired(item.getRequired()); - List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { - Dependency modelDependency = new Dependency(); - modelDependency.setId(dependency.getId()); - modelDependency.setQueryProperty(dependency.getQueryProperty()); - dependencies.add(modelDependency); - }); - dynamicField.setDependencies(dependencies); - fields.add(dynamicField); - }); - this.fields = fields; - return fields; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java deleted file mode 100644 index 0d0aeb607..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package eu.eudat.configurations.dynamicproject; - -import eu.eudat.configurations.dynamicproject.entities.Configuration; -import eu.eudat.configurations.dynamicproject.entities.Property; -import eu.eudat.models.data.dynamicfields.Dependency; -import eu.eudat.models.data.dynamicfields.DynamicField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.file.Paths; -import java.util.LinkedList; -import java.util.List; - -@Service("dynamicProjectConfiguration") -@Profile({ "production", "staging", "docker" }) -public class DynamicProjectConfigurationProdImpl implements DynamicProjectConfiguration{ - private static final Logger logger = LoggerFactory.getLogger(DynamicProjectConfigurationProdImpl.class); - - private Configuration configuration; - - private List fields; - - private Environment environment; - - @Autowired - public DynamicProjectConfigurationProdImpl(Environment environment) { - this.environment = environment; - } - - @Override - public Configuration getConfiguration() { - if (this.configuration != null) return this.configuration; - String fileUrl = this.environment.getProperty("configuration.dynamicProjectUrl"); - logger.info("Loaded also config file: " + fileUrl); - String current = null; - InputStream is = null; - try { - current = new java.io.File(".").getCanonicalPath(); - - JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); - this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); - } catch (Exception ex) { - logger.error("Cannot find in folder" + current, ex); - } finally { - try { - if (is != null) is.close(); - } catch (IOException e) { - logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); - } - } - return this.configuration; - } - - @Override - public List getFields() { - if (this.fields != null) return this.fields; - Configuration configuration = this.getConfiguration(); - List fields = new LinkedList<>(); - List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { - DynamicField dynamicField = new DynamicField(); - dynamicField.setId(item.getId()); - dynamicField.setName(item.getName()); - dynamicField.setQueryProperty(item.getQueryProperty()); - dynamicField.setRequired(item.getRequired()); - List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { - Dependency modelDependency = new Dependency(); - modelDependency.setId(dependency.getId()); - modelDependency.setQueryProperty(dependency.getQueryProperty()); - dependencies.add(modelDependency); - }); - dynamicField.setDependencies(dependencies); - fields.add(dynamicField); - }); - this.fields = fields; - return fields; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Configuration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Configuration.java deleted file mode 100644 index f207844c6..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Configuration.java +++ /dev/null @@ -1,32 +0,0 @@ -package eu.eudat.configurations.dynamicproject.entities; - - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import jakarta.xml.bind.annotation.XmlRootElement; -import java.util.List; - -@XmlRootElement -public class Configuration { - private List configurationProperties; - private MainProperty mainExternalField; - - public MainProperty getMainExternalField() { - return mainExternalField; - } - - @XmlElement(name = "mainExternalField") - public void setMainExternalField(MainProperty mainExternalField) { - this.mainExternalField = mainExternalField; - } - - public List getConfigurationProperties() { - return configurationProperties; - } - - @XmlElementWrapper - @XmlElement(name = "property") - public void setConfigurationProperties(List configurationProperties) { - this.configurationProperties = configurationProperties; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Dependency.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Dependency.java deleted file mode 100644 index 889444402..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Dependency.java +++ /dev/null @@ -1,26 +0,0 @@ -package eu.eudat.configurations.dynamicproject.entities; - -import jakarta.xml.bind.annotation.XmlElement; - -public class Dependency { - private String id; - private String queryProperty; - - public String getId() { - return id; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Language.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Language.java deleted file mode 100644 index 89fed26d6..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Language.java +++ /dev/null @@ -1,26 +0,0 @@ -package eu.eudat.configurations.dynamicproject.entities; - -import jakarta.xml.bind.annotation.XmlElement; - -public class Language { - private String key; - private String languageKey; - - public String getKey() { - return key; - } - - @XmlElement(name = "key") - public void setKey(String key) { - this.key = key; - } - - public String getLanguageKey() { - return languageKey; - } - - @XmlElement(name = "languageKey") - public void setLanguageKey(String languageKey) { - this.languageKey = languageKey; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/MainProperty.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/MainProperty.java deleted file mode 100644 index d1085a5d5..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/MainProperty.java +++ /dev/null @@ -1,103 +0,0 @@ -package eu.eudat.configurations.dynamicproject.entities; - -import eu.eudat.service.reference.external.config.UrlConfiguration; - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import java.util.List; - -public class MainProperty { - private String id; - private String name; - private String queryProperty; - private String externalFieldId; - private List urlConfig; - private String externalFieldLabel; - private List dependencies; - private Boolean required; - private List language; - - - public String getId() { - return id; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - @XmlElement(name = "name") - public void setName(String name) { - this.name = name; - } - - public String getExternalFieldId() { - return externalFieldId; - } - - @XmlElement(name = "externalFieldId") - public void setExternalFieldId(String externalFieldId) { - this.externalFieldId = externalFieldId; - } - - public String getExternalFieldLabel() { - return externalFieldLabel; - } - - @XmlElement(name = "externalFieldLabel") - public void setExternalFieldLabel(String externalFieldLabel) { - this.externalFieldLabel = externalFieldLabel; - } - - public List getDependencies() { - return dependencies; - } - - @XmlElementWrapper - @XmlElement(name = "dependency") - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Boolean getRequired() { - return required; - } - - @XmlElement(name = "required") - public void setRequired(Boolean required) { - this.required = required; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } - - public List getUrlConfig() { - return urlConfig; - } - - @XmlElement(name = "urlConfig") - public void setUrlConfig(List urlConfig) { - this.urlConfig = urlConfig; - } - - public List getLanguage() { - return language; - } - - @XmlElementWrapper - @XmlElement(name = "languageProperty") - public void setLanguage(List language) { - this.language = language; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Property.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Property.java deleted file mode 100644 index 40b919a8a..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/entities/Property.java +++ /dev/null @@ -1,91 +0,0 @@ -package eu.eudat.configurations.dynamicproject.entities; - - -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import java.util.List; - -public class Property { - private String id; - private String name; - private String sourceUrl; - private String queryProperty; - private String externalFieldId; - private String externalFieldLabel; - private List dependencies; - private Boolean required; - - - public String getId() { - return id; - } - - @XmlElement(name = "id") - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - @XmlElement(name = "name") - public void setName(String name) { - this.name = name; - } - - public String getSourceUrl() { - return sourceUrl; - } - - @XmlElement(name = "sourceUrl") - public void setSourceUrl(String sourceUrl) { - this.sourceUrl = sourceUrl; - } - - public String getExternalFieldId() { - return externalFieldId; - } - - @XmlElement(name = "externalFieldId") - public void setExternalFieldId(String externalFieldId) { - this.externalFieldId = externalFieldId; - } - - public String getExternalFieldLabel() { - return externalFieldLabel; - } - - @XmlElement(name = "externalFieldLabel") - public void setExternalFieldLabel(String externalFieldLabel) { - this.externalFieldLabel = externalFieldLabel; - } - - public List getDependencies() { - return dependencies; - } - - @XmlElementWrapper - @XmlElement(name = "dependency") - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Boolean getRequired() { - return required; - } - - @XmlElement(name = "required") - public void setRequired(Boolean required) { - this.required = required; - } - - public String getQueryProperty() { - return queryProperty; - } - - @XmlElement(name = "queryProperty") - public void setQueryProperty(String queryProperty) { - this.queryProperty = queryProperty; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/CommonController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/CommonController.java index f93b1f9f0..fc846c063 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/CommonController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/CommonController.java @@ -1,21 +1,16 @@ package eu.eudat.controllers; -import eu.eudat.configurations.dynamicgrant.DynamicGrantConfiguration; -import eu.eudat.configurations.dynamicgrant.entities.Language; import eu.eudat.logic.managers.CommonsManager; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; import eu.eudat.models.data.externalurl.ExternalSourcesConfiguration; import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.service.reference.external.ExternalUrlConfigProvider; -import eu.eudat.service.storage.StorageFileService; +import eu.eudat.service.remotefetcher.ExternalUrlConfigProvider; import eu.eudat.types.ApiMessageCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - /** * Created by ikalyvas on 3/28/2018. */ diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java index 428b8b971..eec034d9f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java @@ -2,7 +2,6 @@ package eu.eudat.controllers; import eu.eudat.authorization.Permission; -import eu.eudat.configurations.dynamicgrant.DynamicGrantConfiguration; import eu.eudat.criteria.DMPCriteria; import eu.eudat.data.DmpEntity; import eu.eudat.data.dao.criteria.DynamicFieldsCriteria; @@ -65,17 +64,15 @@ import static org.springframework.http.MediaType.*; public class DMPs extends BaseController { private static final Logger logger = LoggerFactory.getLogger(DMPs.class); - private DynamicGrantConfiguration dynamicGrantConfiguration; private Environment environment; private DataManagementPlanManager dataManagementPlanManager; private ConfigLoader configLoader; private final AuthorizationService authorizationService; @Autowired - public DMPs(ApiContext apiContext, DynamicGrantConfiguration dynamicGrantConfiguration, Environment environment, + public DMPs(ApiContext apiContext, Environment environment, DataManagementPlanManager dataManagementPlanManager, ConfigLoader configLoader, AuthorizationService authorizationService) { super(apiContext); - this.dynamicGrantConfiguration = dynamicGrantConfiguration; this.environment = environment; this.dataManagementPlanManager = dataManagementPlanManager; this.configLoader = configLoader; @@ -168,14 +165,14 @@ public class DMPs extends BaseController { // } } - @RequestMapping(method = RequestMethod.POST, value = {"/dynamic"}, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity>>> getWithCriteria(@RequestBody RequestItem criteriaRequestItem) throws InstantiationException, IllegalAccessException { - this.authorizationService.authorizeForce(Permission.AuthenticatedRole); - - List> dataTable = this.dataManagementPlanManager.getDynamicFields(criteriaRequestItem.getCriteria().getId(), this.dynamicGrantConfiguration, criteriaRequestItem.getCriteria()); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); - } +// @RequestMapping(method = RequestMethod.POST, value = {"/dynamic"}, consumes = "application/json", produces = "application/json") +// public @ResponseBody +// ResponseEntity>>> getWithCriteria(@RequestBody RequestItem criteriaRequestItem) throws InstantiationException, IllegalAccessException { +// this.authorizationService.authorizeForce(Permission.AuthenticatedRole); +// +// List> dataTable = this.dataManagementPlanManager.getDynamicFields(criteriaRequestItem.getCriteria().getId(), this.dynamicGrantConfiguration, criteriaRequestItem.getCriteria()); +// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); +// } @RequestMapping(method = RequestMethod.GET, value = {"/versions/{id}"}, consumes = "application/json", produces = "application/json") public @ResponseBody diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetProfileController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetProfileController.java index 77c0ed8f6..00b46626b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetProfileController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetProfileController.java @@ -6,7 +6,7 @@ import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.dao.criteria.RequestItem; import eu.eudat.logic.managers.DatasetProfileManager; import eu.eudat.logic.services.ApiContext; -import eu.eudat.models.data.externaldataset.ExternalAutocompleteFieldModel; +import eu.eudat.service.remotefetcher.models.ExternalAutocompleteFieldResult; import eu.eudat.models.data.helpers.common.AutoCompleteLookupItem; import eu.eudat.models.data.helpers.common.AutoCompleteOptionsLookupItem; import gr.cite.commons.web.authz.service.AuthorizationService; @@ -64,7 +64,7 @@ public class DatasetProfileController extends BaseController { DescriptionTemplateEntity descriptionTemplateEntity = this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(lookupItem.getCriteria().getProfileID())); FieldEntity modelfield = this.datasetProfileManager.queryForField(descriptionTemplateEntity.getDefinition(), lookupItem.getCriteria().getFieldID()); AutoCompleteDataEntity data = (AutoCompleteDataEntity) modelfield.getData(); - List items = this.datasetProfileManager.getAutocomplete(data, lookupItem.getCriteria().getLike()); + List items = this.datasetProfileManager.getAutocomplete(data, lookupItem.getCriteria().getLike()); return ResponseEntity.status(HttpStatus.OK).body(items); } @@ -72,7 +72,7 @@ public class DatasetProfileController extends BaseController { public ResponseEntity getDataForAutocompleteOptions(@RequestBody RequestItem lookupItem) { AutoCompleteDataEntity data = new AutoCompleteDataEntity(); data.setAutoCompleteSingleDataList(lookupItem.getCriteria().getAutoCompleteSingleDataList()); - List items = this.datasetProfileManager.getAutocomplete(data, lookupItem.getCriteria().getLike()); + List items = this.datasetProfileManager.getAutocomplete(data, lookupItem.getCriteria().getLike()); return ResponseEntity.status(HttpStatus.OK).body(items); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java index 2bdf34079..1ddacac47 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java @@ -9,7 +9,6 @@ import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.managers.DatasetManager; import eu.eudat.logic.managers.DatasetWizardManager; import eu.eudat.logic.managers.FileManager; -import eu.eudat.logic.managers.UserManager; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.forms.VisibilityRuleService; @@ -56,20 +55,18 @@ public class Datasets extends BaseController { private Environment environment; private DatasetManager datasetManager; private ConfigLoader configLoader; - private UserManager userManager; private FileManager fileManager; private final AuthorizationService authorizationService; private final UserScope userScope; private final QueryFactory queryFactory; @Autowired - public Datasets(ApiContext apiContext, Environment environment, DatasetManager datasetManager, ConfigLoader configLoader, UserManager userManager, + public Datasets(ApiContext apiContext, Environment environment, DatasetManager datasetManager, ConfigLoader configLoader, FileManager fileManager, AuthorizationService authorizationService, UserScope userScope, QueryFactory queryFactory) { super(apiContext); this.environment = environment; this.datasetManager = datasetManager; this.configLoader = configLoader; - this.userManager = userManager; this.fileManager = fileManager; this.authorizationService = authorizationService; this.userScope = userScope; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java deleted file mode 100644 index 4c4235ca1..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java +++ /dev/null @@ -1,66 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.authorization.Permission; -import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; -import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; -import eu.eudat.logic.managers.EmailConfirmationManager; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.types.ApiMessageCode; -import gr.cite.commons.web.authz.service.AuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import jakarta.transaction.Transactional; - -import javax.management.InvalidApplicationException; - -@RestController -@CrossOrigin -@RequestMapping(value = "/api/emailConfirmation/") -public class EmailConfirmation { - - private EmailConfirmationManager emailConfirmationManager; - private final AuthorizationService authorizationService; - - @Autowired - public EmailConfirmation(EmailConfirmationManager emailConfirmationManager, AuthorizationService authorizationService) { - this.emailConfirmationManager = emailConfirmationManager; - this.authorizationService = authorizationService; - } - - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"/{emailToken}"}) - public @ResponseBody - ResponseEntity emailConfirmation(@PathVariable(value = "emailToken") String token) { - try { - this.emailConfirmationManager.confirmEmail(token); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); - } catch - (HasConfirmedEmailException | TokenExpiredException | InvalidApplicationException ex) { - if (ex instanceof TokenExpiredException) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); - } else { - return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); - } - } - } - - @Transactional - @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity sendConfirmatioEmail(@RequestBody String email) { - this.authorizationService.authorizeForce(Permission.AuthenticatedRole); - - try { - this.emailConfirmationManager.sendConfirmationEmail(email); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); - } catch (Exception ex) { - if (ex instanceof HasConfirmedEmailException) { - return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); - } - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); - } - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java deleted file mode 100644 index dacb1186d..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java +++ /dev/null @@ -1,65 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.authorization.Permission; -import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; -import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; -import eu.eudat.logic.managers.MergeEmailConfirmationManager; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.types.ApiMessageCode; -import gr.cite.commons.web.authz.service.AuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import jakarta.transaction.Transactional; - -import javax.management.InvalidApplicationException; - -@RestController -@CrossOrigin -@RequestMapping(value = "api/emailMergeConfirmation") -public class EmailMergeConfirmation { - - private MergeEmailConfirmationManager emailConfirmationManager; - private final AuthorizationService authorizationService; - - @Autowired - public EmailMergeConfirmation(MergeEmailConfirmationManager emailConfirmationManager, AuthorizationService authorizationService) { - this.emailConfirmationManager = emailConfirmationManager; - this.authorizationService = authorizationService; - } - - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"/{emailToken}"}) - public @ResponseBody - ResponseEntity> emailConfirmation(@PathVariable(value = "emailToken") String token) { - try { - String emailToBeMerged = this.emailConfirmationManager.confirmEmail(token); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(emailToBeMerged).status(ApiMessageCode.SUCCESS_MESSAGE)); - } catch - (HasConfirmedEmailException | TokenExpiredException | InvalidApplicationException ex) { - if (ex instanceof TokenExpiredException) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); - } else { - return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); - } - } - } - -// @Transactional -// @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") -// public @ResponseBody -// ResponseEntity sendConfirmatioEmail(@RequestBody UserMergeRequestModel requestModel) { -// this.authorizationService.authorizeForce(Permission.AuthenticatedRole); -// try { -// this.emailConfirmationManager.sendConfirmationEmail(requestModel.getEmail(), requestModel.getUserId(), requestModel.getProvider()); -// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); -// } catch (Exception ex) { -// if (ex instanceof HasConfirmedEmailException) { -// return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); -// } -// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); -// } -// } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailUnlinkConfirmation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailUnlinkConfirmation.java deleted file mode 100644 index 92a246dda..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailUnlinkConfirmation.java +++ /dev/null @@ -1,62 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.authorization.Permission; -import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; -import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; -import eu.eudat.logic.managers.UnlinkEmailConfirmationManager; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.types.ApiMessageCode; -import gr.cite.commons.web.authz.service.AuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import jakarta.transaction.Transactional; - -import javax.management.InvalidApplicationException; - -@RestController -@CrossOrigin -@RequestMapping(value = "api/emailUnlinkConfirmation") -public class EmailUnlinkConfirmation { - - private UnlinkEmailConfirmationManager unlinkEmailConfirmationManager; - private final AuthorizationService authorizationService; - - @Autowired - public EmailUnlinkConfirmation(UnlinkEmailConfirmationManager unlinkEmailConfirmationManager, AuthorizationService authorizationService){ - this.unlinkEmailConfirmationManager = unlinkEmailConfirmationManager; - this.authorizationService = authorizationService; - } - - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"/{emailToken}"}) - public @ResponseBody - ResponseEntity emailConfirmation(@PathVariable(value = "emailToken") String token) { - try { - this.unlinkEmailConfirmationManager.confirmEmail(token); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); - } catch (TokenExpiredException | HasConfirmedEmailException | InvalidApplicationException ex) { - if (ex instanceof TokenExpiredException) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); - } - else { - return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); - } - } - } - -// @Transactional -// @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") -// public @ResponseBody -// ResponseEntity sendUnlinkConfirmationEmail(@RequestBody UserUnlinkRequestModel requestModel) { -// this.authorizationService.authorizeForce(Permission.AuthenticatedRole); -// try { -// this.unlinkEmailConfirmationManager.sendConfirmationEmail(requestModel.getEmail(), requestModel.getUserId(), requestModel.getProvider()); -// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); -// } catch (Exception ex) { -// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Could not send unlink email.")); -// } -// } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Prefillings.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Prefillings.java deleted file mode 100644 index 7d39c2630..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Prefillings.java +++ /dev/null @@ -1,46 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.logic.managers.PrefillingManager; -import eu.eudat.models.data.datasetwizard.DatasetWizardModel; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.models.data.prefilling.Prefilling; -import eu.eudat.types.ApiMessageCode; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -@RestController -@CrossOrigin -@RequestMapping(value = {"/api"}) -public class Prefillings { - - private final PrefillingManager prefillingManager; - - @Autowired - public Prefillings(PrefillingManager prefillingManager) { - this.prefillingManager = prefillingManager; - } - - @RequestMapping(method = RequestMethod.GET, value = {"/prefilling/list"}, produces = "application/json") - public ResponseEntity>> getPrefillingList(@RequestParam String like) { - List prefillingList = prefillingManager.getPrefillings(like); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(prefillingList).status(ApiMessageCode.NO_MESSAGE)); - } - - @RequestMapping(method = RequestMethod.GET, value = {"/prefilling/generate/{id}"}, produces = "application/json") - public ResponseEntity> getPrefillingDataset(@PathVariable String id, @RequestParam String configId, @RequestParam UUID profileId) throws Exception { - DatasetWizardModel datasetWizardModel = prefillingManager.getPrefilledDataset(id, configId, profileId); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(datasetWizardModel).status(ApiMessageCode.NO_MESSAGE)); - } - - @RequestMapping(method = RequestMethod.POST, value = {"/prefilling/generateUsingData"}, produces = "application/json") - public ResponseEntity> getPrefillingDataset(@RequestBody Map data, @RequestParam String configId, @RequestParam UUID profileId) throws Exception { - DatasetWizardModel datasetWizardModel = prefillingManager.getPrefilledDatasetUsingData(data, configId, profileId); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(datasetWizardModel).status(ApiMessageCode.NO_MESSAGE)); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java deleted file mode 100644 index dd179c592..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java +++ /dev/null @@ -1,68 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.authorization.Permission; -import eu.eudat.logic.managers.InvitationsManager; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.models.data.invitation.Invitation; -import eu.eudat.types.ApiMessageCode; -import gr.cite.commons.web.authz.service.AuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; - -import jakarta.xml.bind.JAXBException; - -import javax.management.InvalidApplicationException; -import java.io.IOException; -import java.util.List; -import java.util.UUID; - - -@RequestMapping("api/invite/") -@RestController -@CrossOrigin -public class UserInvitationController extends BaseController { - - private InvitationsManager invitationsManager; - private final AuthorizationService authorizationService; - @Autowired - public UserInvitationController(ApiContext apiContext, InvitationsManager invitationsManager, AuthorizationService authorizationService) { - super(apiContext); - this.invitationsManager = invitationsManager; - this.authorizationService = authorizationService; - } - - @Transactional - @RequestMapping(method = RequestMethod.POST, value = {"/users"}, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity> users(@RequestBody Invitation invitation) throws Exception { - this.authorizationService.authorizeForce(Permission.AuthenticatedRole); - - this.invitationsManager.inviteUsers(invitation); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Users have beeen invited")); - } - - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"/exchange/{invitationID}"}, produces = "application/json") - public @ResponseBody - ResponseEntity> exchange(@PathVariable UUID invitationID) throws JAXBException, IOException, InvalidApplicationException { - this.authorizationService.authorizeForce(Permission.AuthenticatedRole); - - UUID dmpId = invitationsManager.assignUserAcceptedInvitation(invitationID); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload(dmpId)); - } - -// @RequestMapping(method = RequestMethod.POST, value = {"/getUsers"}, consumes = "application/json", produces = "application/json") -// public @ResponseBody -//// ResponseEntity>> getUsers() throws IllegalAccessException, InstantiationException { -// ResponseEntity>> getUsers(@RequestBody UserInfoRequestItem userInfoRequestItem) throws IllegalAccessException, InstantiationException, InvalidApplicationException { -//// List users = invitationsManager.getUsers(principal); -// this.authorizationService.authorizeForce(Permission.AuthenticatedRole); -// -// List users = invitationsManager.getUsersWithCriteria(userInfoRequestItem); -// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.SUCCESS_MESSAGE).payload(users)); -// } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ValidatorRequestBodyAdvice.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ValidatorRequestBodyAdvice.java deleted file mode 100644 index 703127b3d..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ValidatorRequestBodyAdvice.java +++ /dev/null @@ -1,61 +0,0 @@ -package eu.eudat.controllers.controllerhandler; - -import eu.eudat.commons.validation.Validator; -import eu.eudat.commons.validation.ValidatorFactory; -import eu.eudat.commons.validation.ValidationFilterAnnotation; -import gr.cite.tools.exception.MyApplicationException; -import org.jetbrains.annotations.NotNull; -import org.springframework.core.MethodParameter; -import org.springframework.http.HttpInputMessage; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.Objects; - -@ControllerAdvice -@RestControllerAdvice -public class ValidatorRequestBodyAdvice implements RequestBodyAdvice { - private final ValidatorFactory validatorFactory; - - public ValidatorRequestBodyAdvice(ValidatorFactory validatorFactory) { - this.validatorFactory = validatorFactory; - } - - @Override - public @NotNull Object afterBodyRead(@NotNull Object body, @NotNull HttpInputMessage inputMessage, MethodParameter parameter, @NotNull Type targetType, - @NotNull Class> converterType) { - if (parameter.getMethod() != null) { - ValidationFilterAnnotation[] annotations = parameter.getMethod().getAnnotationsByType((ValidationFilterAnnotation.class)); - - if (annotations == null) return body; - for (ValidationFilterAnnotation annotation : annotations){ - if (!Objects.equals(parameter.getParameterName(), annotation.argumentName())) continue; - - Validator validator = validatorFactory.validator(annotation.validator()); - if (validator == null) throw new MyApplicationException("validator not provided"); - - validator.validateForce(body); - } - } - return body; - } - - @Override - public Object handleEmptyBody(Object body, @NotNull HttpInputMessage inputMessage, @NotNull MethodParameter parameter, @NotNull Type targetType, @NotNull Class> converterType) { - return body; - } - - @Override - public boolean supports(MethodParameter parameter, @NotNull Type targetType, @NotNull Class> converterType) { - return parameter.getMethod() != null && parameter.getMethod().isAnnotationPresent((ValidationFilterAnnotation.class)); - } - - @Override - public @NotNull HttpInputMessage beforeBodyRead(@NotNull HttpInputMessage inputMessage, @NotNull MethodParameter parameter, @NotNull Type targetType, @NotNull Class> converterType) throws IOException { - return inputMessage; - } -} \ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ContactSupportController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ContactSupportController.java index 58dc991d4..e817c49a9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ContactSupportController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ContactSupportController.java @@ -1,34 +1,20 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.commons.validation.ValidationFilterAnnotation; -import eu.eudat.model.DashboardStatistics; -import eu.eudat.model.RecentActivityItem; -import eu.eudat.model.RecentActivityItemLookup; -import eu.eudat.model.User; -import eu.eudat.model.censorship.MyDashboardStatisticsCensor; -import eu.eudat.model.censorship.PublicDashboardStatisticsCensor; -import eu.eudat.model.censorship.RecentActivityItemCensor; import eu.eudat.model.persist.ContactSupportPersist; -import eu.eudat.model.persist.DescriptionTemplateTypePersist; import eu.eudat.model.persist.PublicContactSupportPersist; import eu.eudat.service.contactsupport.ContactSupportService; -import eu.eudat.service.dashborad.DashboardService; import gr.cite.tools.auditing.AuditService; -import gr.cite.tools.data.censor.CensorFactory; -import gr.cite.tools.exception.MyApplicationException; -import gr.cite.tools.exception.MyForbiddenException; -import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; +import gr.cite.tools.validation.ValidationFilterAnnotation; import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.management.InvalidApplicationException; import java.util.AbstractMap; -import java.util.List; import java.util.Map; @RestController @@ -67,10 +53,10 @@ public class ContactSupportController { - @PostMapping("public/send") + @PostMapping(path = "public/send", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) @Transactional @ValidationFilterAnnotation(validator = PublicContactSupportPersist.PublicContactSupportPersistValidator.ValidatorName, argumentName ="model") - public void sendPublicContactEmail(@RequestBody PublicContactSupportPersist model) throws InvalidApplicationException { + public void sendPublicContactEmail(@ModelAttribute PublicContactSupportPersist model) throws InvalidApplicationException { logger.debug(new MapLogEntry("send public support email").And("model", model)); this.contactSupportService.sendPublicContactEmail(model); @@ -81,4 +67,17 @@ public class ContactSupportController { //this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action); } + @PostMapping("public/send") + @Transactional + @ValidationFilterAnnotation(validator = PublicContactSupportPersist.PublicContactSupportPersistValidator.ValidatorName, argumentName ="model") + public void sendPublicContactEmailJson(@RequestBody PublicContactSupportPersist model) throws InvalidApplicationException { + logger.debug(new MapLogEntry("send public support email").And("model", model)); + + this.contactSupportService.sendPublicContactEmail(model); + + this.auditService.track(AuditableAction.ContactSupport_PublicSent, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + //this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action); + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DepositController.java index eed980246..e14926c55 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DepositController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DepositController.java @@ -1,7 +1,7 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.controllers.BaseController; import eu.eudat.logic.services.ApiContext; import eu.eudat.model.EntityDoi; @@ -33,7 +33,6 @@ public class DepositController extends BaseController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DepositController.class)); - private final AuthorizationService authorizationService; private final DepositService depositService; @@ -44,7 +43,6 @@ public class DepositController extends BaseController { @Autowired public DepositController(ApiContext apiContext, AuthorizationService authorizationService, DepositService depositService, CensorFactory censorFactory, AuditService auditService) { super(apiContext); - this.authorizationService = authorizationService; this.depositService = depositService; this.censorFactory = censorFactory; this.auditService = auditService; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java index 757a2d9d1..2bb2e4309 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java @@ -6,7 +6,7 @@ import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.commons.enums.DmpAccessType; import eu.eudat.commons.enums.DmpStatus; import eu.eudat.commons.enums.IsActive; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.model.Description; import eu.eudat.model.Dmp; import eu.eudat.model.PublicDescription; @@ -63,7 +63,6 @@ public class DescriptionController { private final MessageSource messageSource; private final ElasticQueryHelperService elasticQueryHelperService; - private final FileTransformerService fileTransformerService; public DescriptionController( BuilderFactory builderFactory, AuditService auditService, @@ -71,7 +70,7 @@ public class DescriptionController { CensorFactory censorFactory, QueryFactory queryFactory, MessageSource messageSource, - ElasticQueryHelperService elasticQueryHelperService, FileTransformerService fileTransformerService) { + ElasticQueryHelperService elasticQueryHelperService) { this.builderFactory = builderFactory; this.auditService = auditService; this.descriptionService = descriptionService; @@ -79,7 +78,6 @@ public class DescriptionController { this.queryFactory = queryFactory; this.messageSource = messageSource; this.elasticQueryHelperService = elasticQueryHelperService; - this.fileTransformerService = fileTransformerService; } @PostMapping("public/query") @@ -151,7 +149,7 @@ public class DescriptionController { @PostMapping("persist") @Transactional @ValidationFilterAnnotation(validator = DescriptionPersist.DescriptionPersistValidator.ValidatorName, argumentName = "model") - public Description persist(@RequestBody DescriptionPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public Description persist(@RequestBody DescriptionPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException { logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); Description persisted = this.descriptionService.persist(model, fieldSet); @@ -166,7 +164,7 @@ public class DescriptionController { @PostMapping("persist-status") @Transactional @ValidationFilterAnnotation(validator = DescriptionStatusPersist.DescriptionStatusPersistValidator.ValidatorName, argumentName = "model") - public Description persistStatus(@RequestBody DescriptionStatusPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + public Description persistStatus(@RequestBody DescriptionStatusPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, IOException { logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); Description persisted = this.descriptionService.persistStatus(model, fieldSet); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateController.java index 5ed8c5326..c01f89863 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.model.DescriptionTemplate; import eu.eudat.model.DmpBlueprint; @@ -26,7 +26,6 @@ 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 jakarta.xml.bind.JAXBException; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeController.java index 527ee66a5..9477aa2fc 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeController.java @@ -3,7 +3,6 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.data.DescriptionTemplateTypeEntity; -import eu.eudat.commons.validation.ValidationFilterAnnotation; import eu.eudat.logic.services.ApiContext; import eu.eudat.model.DescriptionTemplateType; import eu.eudat.model.builder.DescriptionTemplateTypeBuilder; @@ -23,6 +22,7 @@ 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.ValidationFilterAnnotation; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpBlueprintController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpBlueprintController.java index 43182610f..3f3891810 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpBlueprintController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpBlueprintController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.DmpBlueprintEntity; import eu.eudat.model.DmpBlueprint; import eu.eudat.model.builder.DmpBlueprintBuilder; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java index bc2e64c43..9a6d476b5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java @@ -3,18 +3,21 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.DmpEntity; -import eu.eudat.model.Dmp; -import eu.eudat.model.DmpUser; +import eu.eudat.model.*; import eu.eudat.model.builder.DmpBuilder; import eu.eudat.model.censorship.DmpCensor; +import eu.eudat.model.censorship.PublicDescriptionCensor; +import eu.eudat.model.censorship.PublicDmpCensor; import eu.eudat.model.persist.*; import eu.eudat.model.result.QueryResult; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.query.DmpQuery; +import eu.eudat.query.lookup.DescriptionLookup; import eu.eudat.query.lookup.DmpLookup; import eu.eudat.service.dmp.DmpService; +import eu.eudat.service.elastic.ElasticQueryHelperService; import eu.eudat.service.transformer.FileTransformerService; import eu.eudat.types.ApiMessageCode; import gr.cite.tools.auditing.AuditService; @@ -42,6 +45,8 @@ import javax.xml.transform.TransformerException; import java.io.IOException; import java.util.*; +import static eu.eudat.authorization.AuthorizationFlags.Public; + @RestController @RequestMapping(path = "api/dmp") public class DmpController { @@ -59,23 +64,38 @@ public class DmpController { private final QueryFactory queryFactory; private final MessageSource messageSource; + private final ElasticQueryHelperService elasticQueryHelperService; - private final FileTransformerService fileTransformerService; public DmpController( - BuilderFactory builderFactory, - AuditService auditService, - DmpService dmpService, - CensorFactory censorFactory, - QueryFactory queryFactory, - MessageSource messageSource, FileTransformerService fileTransformerService) { + BuilderFactory builderFactory, + AuditService auditService, + DmpService dmpService, + CensorFactory censorFactory, + QueryFactory queryFactory, + MessageSource messageSource, + ElasticQueryHelperService elasticQueryHelperService) { this.builderFactory = builderFactory; this.auditService = auditService; this.dmpService = dmpService; this.censorFactory = censorFactory; this.queryFactory = queryFactory; this.messageSource = messageSource; - this.fileTransformerService = fileTransformerService; + this.elasticQueryHelperService = elasticQueryHelperService; + } + + @PostMapping("public/query") + public QueryResult publicQuery(@RequestBody DmpLookup lookup) throws MyApplicationException, MyForbiddenException { + logger.debug("querying {}", Dmp.class.getSimpleName()); + + this.censorFactory.censor(PublicDmpCensor.class).censor(lookup.getProject()); + + //DmpQuery query = lookup.enrich(this.queryFactory).authorize(EnumSet.of(Public)).dmpSubQuery(this.queryFactory.query(DmpQuery.class).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public)); + QueryResult queryResult = this.elasticQueryHelperService.collectPublic(lookup, EnumSet.of(Public), null); + + this.auditService.track(AuditableAction.Dmp_PublicQuery, "lookup", lookup); + + return queryResult; } @PostMapping("query") @@ -84,15 +104,12 @@ public class DmpController { this.censorFactory.censor(DmpCensor.class).censor(lookup.getProject(), null); - DmpQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic); - List data = query.collectAs(lookup.getProject()); - List models = this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(lookup.getProject(), data); - long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); + QueryResult queryResult = this.elasticQueryHelperService.collect(lookup, AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic, null); this.auditService.track(AuditableAction.Dmp_Query, "lookup", lookup); - return new QueryResult<>(models, count); + return queryResult; } @GetMapping("{id}") @@ -117,7 +134,7 @@ public class DmpController { @PostMapping("persist") @Transactional @ValidationFilterAnnotation(validator = DmpPersist.DmpPersistValidator.ValidatorName, argumentName = "model") - public Dmp Persist(@RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public Dmp Persist(@RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException { logger.debug(new MapLogEntry("persisting" + Dmp.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); Dmp persisted = this.dmpService.persist(model, fieldSet); @@ -143,7 +160,7 @@ public class DmpController { @PostMapping("clone") @Transactional @ValidationFilterAnnotation(validator = CloneDmpPersist.CloneDmpPersistValidator.ValidatorName, argumentName = "model") - public Dmp buildClone(@RequestBody CloneDmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + public Dmp buildClone(@RequestBody CloneDmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, IOException { logger.debug(new MapLogEntry("clone" + Dmp.class.getSimpleName()).And("model", model).And("fields", fieldSet)); this.censorFactory.censor(DmpCensor.class).censor(fieldSet, null); @@ -161,7 +178,7 @@ public class DmpController { @PostMapping("new-version") @Transactional @ValidationFilterAnnotation(validator = NewVersionDmpPersist.NewVersionDmpPersistValidator.ValidatorName, argumentName = "model") - public Dmp createNewVersion(@RequestBody NewVersionDmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, JsonProcessingException, TransformerException, InvalidApplicationException, ParserConfigurationException { + public Dmp createNewVersion(@RequestBody NewVersionDmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, IOException, TransformerException, InvalidApplicationException, ParserConfigurationException { logger.debug(new MapLogEntry("persisting" + NewVersionDmpPersist.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); Dmp persisted = this.dmpService.createNewVersion(model, fieldSet); @@ -177,7 +194,7 @@ public class DmpController { @PostMapping("{id}/assign-users") @Transactional @ValidationFilterAnnotation(validator = DmpUserPersist.DmpUserPersistValidator.ValidatorName, argumentName = "model") - public QueryResult assignUsers(@PathVariable("id") UUID id, @RequestBody List model, FieldSet fieldSet) throws InvalidApplicationException { + public QueryResult assignUsers(@PathVariable("id") UUID id, @RequestBody List model, FieldSet fieldSet) throws InvalidApplicationException, IOException { logger.debug(new MapLogEntry("assigning users to dmp").And("model", model).And("fieldSet", fieldSet)); List persisted = this.dmpService.assignUsers(id, model, fieldSet); @@ -193,7 +210,7 @@ public class DmpController { @PostMapping("remove-user") @Transactional @ValidationFilterAnnotation(validator = DmpUserRemovePersist.DmpUserRemovePersistValidator.ValidatorName, argumentName = "model") - public QueryResult removeUser(@RequestBody DmpUserRemovePersist model, FieldSet fieldSet) throws InvalidApplicationException { + public QueryResult removeUser(@RequestBody DmpUserRemovePersist model, FieldSet fieldSet) throws InvalidApplicationException, IOException { logger.debug(new MapLogEntry("remove user from dmp").And("model", model).And("fieldSet", fieldSet)); Dmp persisted = this.dmpService.removeUser(model, fieldSet); @@ -216,7 +233,7 @@ public class DmpController { @PostMapping("{id}/invite-users") @Transactional @ValidationFilterAnnotation(validator = DmpUserInvitePersist.DmpUserInvitePersistValidator.ValidatorName, argumentName = "model") - public ResponseEntity> inviteUsers(@PathVariable("id") UUID id, @RequestBody DmpUserInvitePersist model) throws InvalidApplicationException, JAXBException { + public ResponseEntity> inviteUsers(@PathVariable("id") UUID id, @RequestBody DmpUserInvitePersist model) throws InvalidApplicationException, JAXBException, IOException { logger.debug(new MapLogEntry("inviting users to dmp").And("model", model)); this.dmpService.inviteUsers(id, model); @@ -230,7 +247,7 @@ public class DmpController { @GetMapping("{id}/token/{token}/invite-accept") @Transactional - public ResponseEntity> acceptInvitation(@PathVariable("id") UUID id, @PathVariable("token") String token) throws InvalidApplicationException, JAXBException { + public ResponseEntity> acceptInvitation(@PathVariable("id") UUID id, @PathVariable("token") String token) throws InvalidApplicationException, JAXBException, IOException { logger.debug(new MapLogEntry("inviting users to dmp").And("id", id)); this.dmpService.dmpInvitationAccept(token); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/EntityDoiController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/EntityDoiController.java index 1de7e164a..31d0e87cd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/EntityDoiController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/EntityDoiController.java @@ -2,7 +2,7 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.EntityDoiEntity; import eu.eudat.model.DescriptionTemplateType; import eu.eudat.model.EntityDoi; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageController.java index e087cf1df..d7223edf5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.LanguageEntity; import eu.eudat.model.Language; import eu.eudat.model.UserContactInfo; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LockController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LockController.java index 69a66b93f..68b8c68e0 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LockController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LockController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.LockEntity; import eu.eudat.model.Lock; import eu.eudat.model.builder.LockBuilder; @@ -24,7 +24,6 @@ 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 jakarta.transaction.Transactional; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -118,7 +117,7 @@ public class LockController { @PostMapping("persist") @Transactional @ValidationFilterAnnotation(validator = LockPersist.LockPersistValidator.ValidatorName, argumentName = "model") - public Lock persist(@MyValidate @RequestBody LockPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + public Lock persist(@RequestBody LockPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting" + Lock.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); this.censorFactory.censor(LockCensor.class).censor(fieldSet, null); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/MaintenanceController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/MaintenanceController.java index d64d13867..644fa84b5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/MaintenanceController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/MaintenanceController.java @@ -1,11 +1,16 @@ package eu.eudat.controllers.v2; +import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.Permission; import eu.eudat.data.DescriptionEntity; +import eu.eudat.model.Lock; import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.service.maintance.MaintenanceService; +import eu.eudat.service.elastic.ElasticService; import eu.eudat.types.ApiMessageCode; import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -18,34 +23,36 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping(path = "api/maintenance") public class MaintenanceController { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(MaintenanceController.class)); private final AuthorizationService authorizationService; - private final MaintenanceService maintenanceService; + private final ElasticService elasticService; + private final AuditService auditService; @Autowired - public MaintenanceController(AuthorizationService authorizationService, MaintenanceService maintenanceService) { + public MaintenanceController(AuthorizationService authorizationService, ElasticService elasticService, AuditService auditService) { this.authorizationService = authorizationService; - this.maintenanceService = maintenanceService; + this.elasticService = elasticService; + this.auditService = auditService; } - /* - * Data Index - * */ @RequestMapping(method = RequestMethod.POST, value = {"/index/elastic"}) - public @ResponseBody - ResponseEntity> generateIndex() throws Exception { + public void generateIndex() throws Exception { + logger.debug("generate elastic "); this.authorizationService.authorizeForce(Permission.ManageElastic); - this.maintenanceService.generateElasticIndex(); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Generated").payload(null)); + elasticService.resetDmpIndex(); + elasticService.resetDescriptionIndex(); + this.auditService.track(AuditableAction.Maintenance_GenerateElastic); } @RequestMapping(method = RequestMethod.DELETE, value = {"/index/elastic"}) - public @ResponseBody - ResponseEntity> clearIndex() throws Exception { + public void clearIndex() throws Exception { + logger.debug("clear elastic"); this.authorizationService.authorizeForce(Permission.ManageElastic); - - this.maintenanceService.clearElasticIndex(); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Cleared").payload(null)); + + elasticService.deleteDescriptionIndex(); + elasticService.deleteDmpIndex(); + this.auditService.track(AuditableAction.Maintenance_ClearElastic); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrefillingController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrefillingController.java new file mode 100644 index 000000000..1505f8674 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrefillingController.java @@ -0,0 +1,105 @@ +package eu.eudat.controllers.v2; + +import eu.eudat.audit.AuditableAction; +import gr.cite.tools.validation.ValidationFilterAnnotation; +import eu.eudat.model.Description; +import eu.eudat.model.Prefilling; +import eu.eudat.model.PrefillingLookup; +import eu.eudat.model.censorship.DescriptionCensor; +import eu.eudat.model.censorship.PrefillingCensor; +import eu.eudat.model.persist.DescriptionProfilingRequest; +import eu.eudat.model.persist.DescriptionProfilingWithDataRequest; +import eu.eudat.service.prefilling.PrefillingService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import jakarta.xml.bind.JAXBException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping(path = "api/prefilling") +public class PrefillingController { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrefillingController.class)); + + @Autowired + + + private final AuditService auditService; + + private final PrefillingService prefillingService; + + private final CensorFactory censorFactory; + + + public PrefillingController( + AuditService auditService, + PrefillingService prefillingService, + CensorFactory censorFactory) { + this.auditService = auditService; + this.prefillingService = prefillingService; + this.censorFactory = censorFactory; + } + + @PostMapping("query") + public List query(@RequestBody PrefillingLookup model) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + this.censorFactory.censor(PrefillingCensor.class).censor(model.getProject(), null); + + logger.debug(new MapLogEntry("persisting" + Prefilling.class.getSimpleName()).And("model", model)); + List items = this.prefillingService.getPrefillings(model); + + this.auditService.track(AuditableAction.Prefilling_Query, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + + return items; + } + + @PostMapping("generate") + @ValidationFilterAnnotation(validator = DescriptionProfilingRequest.DescriptionProfilingRequestValidator.ValidatorName, argumentName = "model") + public Description generate(@RequestBody DescriptionProfilingRequest model) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException { + logger.debug(new MapLogEntry("persisting" + Prefilling.class.getSimpleName()).And("model", model)); + + this.censorFactory.censor(DescriptionCensor.class).censor(model.getProject(), null); + + Description item = this.prefillingService.getPrefilledDescription(model); + + this.auditService.track(AuditableAction.Prefilling_Generate, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + + return item; + } + + @PostMapping("generate-with-data") + @ValidationFilterAnnotation(validator = DescriptionProfilingWithDataRequest.DescriptionProfilingWithDataRequestValidator.ValidatorName, argumentName = "model") + public Description generateWithData(@RequestBody DescriptionProfilingWithDataRequest model) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException { + logger.debug(new MapLogEntry("persisting" + Prefilling.class.getSimpleName()).And("model", model)); + + this.censorFactory.censor(DescriptionCensor.class).censor(model.getProject(), null); + + Description item = this.prefillingService.getPrefilledDescriptionUsingData(model); + + this.auditService.track(AuditableAction.Prefilling_GenerateWithData, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + + return item; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java index c50e9f156..158e3996b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java @@ -1,5 +1,6 @@ package eu.eudat.controllers.v2; +import eu.eudat.audit.AuditableAction; import eu.eudat.models.data.dataset.DatasetOverviewModel; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.v2.AccountBuilder; @@ -40,7 +41,7 @@ public class PrincipalController { } @RequestMapping(path = "me", method = RequestMethod.GET ) - public ResponseEntity me(FieldSet fieldSet) throws InvalidApplicationException { + public Account me(FieldSet fieldSet) throws InvalidApplicationException { logger.debug("me"); if (fieldSet == null || fieldSet.isEmpty()) { @@ -68,10 +69,10 @@ public class PrincipalController { Account me = this.accountBuilder.build(fieldSet, principal); - //this.auditService.track(AuditableAction.Principal_Lookup); + this.auditService.track(AuditableAction.Principal_Lookup); //auditService.trackIdentity(AuditableAction.IdentityTracking_Action); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(me)); + return me; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java index 71426a411..93646f972 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceController.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.controllers.BaseController; import eu.eudat.data.ReferenceEntity; import eu.eudat.commons.exceptions.HugeResultSetException; @@ -68,7 +68,6 @@ public class ReferenceController extends BaseController { private final MessageSource messageSource; - private final AuthorizationService authorizationService; @Autowired public ReferenceController( @@ -78,7 +77,7 @@ public class ReferenceController extends BaseController { AuditService auditService, CensorFactory censorFactory, QueryFactory queryFactory, - MessageSource messageSource, AuthorizationService authorizationService) { + MessageSource messageSource) { super(apiContext); this.builderFactory = builderFactory; this.referenceService = referenceService; @@ -86,7 +85,6 @@ public class ReferenceController extends BaseController { this.censorFactory = censorFactory; this.queryFactory = queryFactory; this.messageSource = messageSource; - this.authorizationService = authorizationService; } @PostMapping("query") diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceTypeController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceTypeController.java index ebd7e322a..7103e7c7b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceTypeController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ReferenceTypeController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.controllers.BaseController; import eu.eudat.data.ReferenceTypeEntity; import eu.eudat.logic.services.ApiContext; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java index 0ac4ff908..f629a40f6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java @@ -1,48 +1,31 @@ package eu.eudat.controllers.v2; -import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; -import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; -import eu.eudat.commons.enums.*; +import eu.eudat.commons.enums.StorageType; import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.commons.validation.ValidatorFactory; import eu.eudat.convention.ConventionService; import eu.eudat.data.StorageFileEntity; -import eu.eudat.model.*; -import eu.eudat.model.builder.DescriptionBuilder; -import eu.eudat.model.censorship.DescriptionCensor; -import eu.eudat.model.censorship.PublicDescriptionCensor; -import eu.eudat.model.persist.DescriptionPersist; +import eu.eudat.model.StorageFile; import eu.eudat.model.persist.StorageFilePersist; -import eu.eudat.model.result.QueryResult; -import eu.eudat.query.DescriptionQuery; -import eu.eudat.query.DmpQuery; import eu.eudat.query.StorageFileQuery; -import eu.eudat.query.lookup.DescriptionLookup; -import eu.eudat.service.description.DescriptionService; -import eu.eudat.service.elastic.ElasticQueryHelperService; import eu.eudat.service.storage.StorageFileProperties; import eu.eudat.service.storage.StorageFileService; import gr.cite.commons.web.authz.service.AuthorizationService; 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.BaseFieldSet; -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 gr.cite.tools.validation.ValidatorFactory; import org.apache.commons.io.FilenameUtils; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -50,14 +33,11 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import javax.management.InvalidApplicationException; import java.io.IOException; import java.net.URLConnection; import java.time.Duration; import java.util.*; -import static eu.eudat.authorization.AuthorizationFlags.Public; - @RestController @RequestMapping(path = "api/storage-file") public class StorageFileController { diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java index edf5e57a1..266fe8985 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.SupportiveMaterialEntity; import eu.eudat.model.SupportiveMaterial; import eu.eudat.model.builder.SupportiveMaterialBuilder; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TagController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TagController.java index 1feec7d88..543b0e66c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TagController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TagController.java @@ -2,7 +2,7 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.TagEntity; import eu.eudat.logic.services.ApiContext; import eu.eudat.model.Tag; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TenantController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TenantController.java index 72ab40eb6..83f0b9456 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TenantController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/TenantController.java @@ -3,7 +3,7 @@ package eu.eudat.controllers.v2; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.TenantEntity; import eu.eudat.model.Tenant; import eu.eudat.model.builder.TenantBuilder; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserController.java index 2fdfdd710..1ab597f1a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserController.java @@ -5,7 +5,7 @@ import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.UserEntity; import eu.eudat.model.DmpAssociatedUser; import eu.eudat.model.User; @@ -14,15 +14,15 @@ import eu.eudat.model.builder.DmpAssociatedUserBuilder; import eu.eudat.model.builder.UserBuilder; import eu.eudat.model.censorship.DmpAssociatedUserCensor; import eu.eudat.model.censorship.UserCensor; +import eu.eudat.model.persist.actionconfirmation.RemoveCredentialRequestPersist; +import eu.eudat.model.persist.UserMergeRequestPersist; import eu.eudat.model.persist.UserPersist; import eu.eudat.model.persist.UserRolePatchPersist; import eu.eudat.model.result.QueryResult; -import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.query.UserQuery; import eu.eudat.query.lookup.UserLookup; import eu.eudat.service.responseutils.ResponseUtilsService; import eu.eudat.service.user.UserService; -import eu.eudat.types.ApiMessageCode; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.censor.CensorFactory; @@ -37,7 +37,6 @@ import jakarta.xml.bind.JAXBException; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -131,7 +130,7 @@ public class UserController { public User get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + User.class.getSimpleName()).And("id", id).And("fields", fieldSet)); - this.censorFactory.censor(UserCensor.class).censor(fieldSet, null); + this.censorFactory.censor(UserCensor.class).censor(fieldSet, id); UserQuery query = this.queryFactory.query(UserQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).ids(id); User model = this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(fieldSet, query.firstAs(fieldSet)); @@ -179,18 +178,17 @@ public class UserController { } @GetMapping("mine") - public User getMine(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { - logger.debug(new MapLogEntry("retrieving" + User.class.getSimpleName()).And("id", id).And("fields", fieldSet)); + public User getMine(FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + logger.debug(new MapLogEntry("retrieving me" + User.class.getSimpleName()).And("fields", fieldSet)); this.censorFactory.censor(UserCensor.class).censor(fieldSet, this.userScope.getUserId()); UserQuery query = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic); User model = this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(fieldSet, query.firstAs(fieldSet)); if (model == null) - throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, User.class.getSimpleName()}, LocaleContextHolder.getLocale())); + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{this.userScope.getUserId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale())); this.auditService.track(AuditableAction.User_Lookup, Map.ofEntries( - new AbstractMap.SimpleEntry("id", id), new AbstractMap.SimpleEntry("fields", fieldSet) )); @@ -270,23 +268,24 @@ public class UserController { this.auditService.track(AuditableAction.User_Delete, "id", id); } - @GetMapping("mine/merge-account-request/{email}") + @PostMapping("mine/merge-account-request") @Transactional - public ResponseEntity> mergeAccount(@PathVariable("email") String email) throws InvalidApplicationException, JAXBException { - logger.debug(new MapLogEntry("merge account to user").And("email", email)); + @ValidationFilterAnnotation(validator = UserMergeRequestPersist.UserMergeRequestPersistValidator.ValidatorName, argumentName = "model") + public Boolean mergeAccount(@RequestBody UserMergeRequestPersist model) throws InvalidApplicationException, JAXBException { + logger.debug(new MapLogEntry("merge account to user").And("email", model)); - this.userTypeService.sendMergeAccountConfirmation(email); + this.userTypeService.sendMergeAccountConfirmation(model); this.auditService.track(AuditableAction.User_MergeRequest, Map.ofEntries( - new AbstractMap.SimpleEntry("email", email) + new AbstractMap.SimpleEntry("model", model) )); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload("Merge Account Request Success")); + return true; } @GetMapping("mine/confirm-merge-account/token/{token}") @Transactional - public ResponseEntity> confirmMergeAccount(@PathVariable("token") String token) throws InvalidApplicationException, JAXBException { + public Boolean confirmMergeAccount(@PathVariable("token") String token) throws InvalidApplicationException, IOException { logger.debug(new MapLogEntry("confirm merge account to user").And("token", token)); this.userTypeService.confirmMergeAccount(token); @@ -295,26 +294,27 @@ public class UserController { new AbstractMap.SimpleEntry("token", token) )); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload("Merge Account Confirm Success")); + return true; } - @GetMapping("mine/remove-credential-request/{email}") + @PostMapping("mine/remove-credential-request") @Transactional - public ResponseEntity> removeCredentialAccount(@PathVariable("email") String email) throws InvalidApplicationException, JAXBException { - logger.debug(new MapLogEntry("remove credential request to user").And("email", email)); + @ValidationFilterAnnotation(validator = RemoveCredentialRequestPersist.RemoveCredentialRequestPersistValidator.ValidatorName, argumentName = "model") + public Boolean removeCredentialAccount(@RequestBody RemoveCredentialRequestPersist model) throws InvalidApplicationException, JAXBException { + logger.debug(new MapLogEntry("remove credential request to user").And("model", model)); - this.userTypeService.sendRemoveCredentialConfirmation(email); + this.userTypeService.sendRemoveCredentialConfirmation(model); this.auditService.track(AuditableAction.User_RemoveCredentialRequest, Map.ofEntries( - new AbstractMap.SimpleEntry("email", email) + new AbstractMap.SimpleEntry("email", model) )); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload("Remove Credential Request Success")); + return true; } @GetMapping("mine/confirm-remove-credential/token/{token}") @Transactional - public ResponseEntity> confirmRemoveCredentialAccount(@PathVariable("token") String token) throws InvalidApplicationException, JAXBException { + public Boolean confirmRemoveCredentialAccount(@PathVariable("token") String token) throws InvalidApplicationException, JAXBException { logger.debug(new MapLogEntry("confirm remove credential to user").And("token", token)); this.userTypeService.confirmRemoveCredential(token); @@ -323,6 +323,6 @@ public class UserController { new AbstractMap.SimpleEntry("model", token) )); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload("Remove Credential Account Success")); + return true; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserSettingsController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserSettingsController.java index 74e03a893..e674d3f81 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserSettingsController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/UserSettingsController.java @@ -2,7 +2,7 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.validation.ValidationFilterAnnotation; +import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.data.UserSettingsEntity; import eu.eudat.model.UserSettings; import eu.eudat.model.builder.UserSettingsBuilder; diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java index b81759a38..43aa1bb47 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java @@ -1,12 +1,15 @@ package eu.eudat.interceptors; +import eu.eudat.authorization.ClaimNames; import eu.eudat.commons.JsonHandlingService; import eu.eudat.commons.enums.ContactInfoType; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.lock.LockByKeyManager; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.types.user.AdditionalInfoEntity; +import eu.eudat.commons.types.usercredential.UserCredentialDataEntity; +import eu.eudat.configurations.locale.LocaleProperties; import eu.eudat.data.UserContactInfoEntity; import eu.eudat.data.UserCredentialEntity; import eu.eudat.data.UserEntity; @@ -14,7 +17,9 @@ import eu.eudat.data.UserRoleEntity; import eu.eudat.model.UserContactInfo; import eu.eudat.model.UserCredential; import eu.eudat.model.UserRole; -import eu.eudat.query.*; +import eu.eudat.query.UserContactInfoQuery; +import eu.eudat.query.UserCredentialQuery; +import eu.eudat.query.UserRoleQuery; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; import gr.cite.tools.data.query.QueryFactory; @@ -23,6 +28,7 @@ import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.logging.LoggerService; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import org.apache.commons.validator.routines.EmailValidator; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.NonNull; @@ -35,14 +41,11 @@ import org.springframework.ui.ModelMap; import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequestInterceptor; -import javax.management.InvalidApplicationException; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; @Component public class UserInterceptor implements WebRequestInterceptor { @@ -55,6 +58,7 @@ public class UserInterceptor implements WebRequestInterceptor { private final JsonHandlingService jsonHandlingService; private final QueryFactory queryFactory; private final LockByKeyManager lockByKeyManager; + private final LocaleProperties localeProperties; @PersistenceContext public EntityManager entityManager; @@ -65,9 +69,10 @@ public class UserInterceptor implements WebRequestInterceptor { CurrentPrincipalResolver currentPrincipalResolver, PlatformTransactionManager transactionManager, UserInterceptorCacheService userInterceptorCacheService, - JsonHandlingService jsonHandlingService, - QueryFactory queryFactory, - LockByKeyManager lockByKeyManager) { + JsonHandlingService jsonHandlingService, + QueryFactory queryFactory, + LockByKeyManager lockByKeyManager, + LocaleProperties localeProperties) { this.userScope = userScope; this.currentPrincipalResolver = currentPrincipalResolver; this.claimExtractor = claimExtractor; @@ -76,6 +81,7 @@ public class UserInterceptor implements WebRequestInterceptor { this.jsonHandlingService = jsonHandlingService; this.queryFactory = queryFactory; this.lockByKeyManager = lockByKeyManager; + this.localeProperties = localeProperties; } @Override @@ -84,15 +90,15 @@ public class UserInterceptor implements WebRequestInterceptor { if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) { String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal()); if (subjectId == null || subjectId.isBlank()) throw new MyForbiddenException("Empty subjects not allowed"); - + UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId)); - if (cacheValue != null && emailExistsToUser(cacheValue.getEmails()) && userRolesSynced(cacheValue.getRoles())) { + if (cacheValue != null && emailExistsToPrincipal(cacheValue.getProviderEmail()) && userRolesSynced(cacheValue.getRoles()) && providerExistsToPrincipal(cacheValue.getExternalProviderNames())) { userId = cacheValue.getUserId(); } else { boolean usedResource = false; try { usedResource = this.lockByKeyManager.tryLock(subjectId, 5000, TimeUnit.MILLISECONDS); - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); + String email = this.getEmailFromClaims(); DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); definition.setName(UUID.randomUUID().toString()); @@ -101,14 +107,18 @@ public class UserInterceptor implements WebRequestInterceptor { TransactionStatus status = null; try { status = transactionManager.getTransaction(definition); + userId = this.findExistingUserFromDb(subjectId); boolean isNewUser = userId == null; if (isNewUser) { UserEntity user = this.addNewUser(subjectId, email); userId = user.getId(); } - - if (!isNewUser) this.syncUserWithClaims(userId); + this.entityManager.flush(); + + if (!isNewUser){ + this.syncUserWithClaims(userId, subjectId); + } this.entityManager.flush(); transactionManager.commit(status); @@ -118,9 +128,13 @@ public class UserInterceptor implements WebRequestInterceptor { } cacheValue = new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId); - cacheValue.setEmails(new ArrayList<>()); - if (email != null && !email.isBlank()) cacheValue.getEmails().add(email); - cacheValue.setRoles(claimExtractor.roles(currentPrincipalResolver.currentPrincipal())); + cacheValue.setRoles(this.getRolesFromClaims()); + if (email != null && !email.isBlank()) cacheValue.setProviderEmail(email); + UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).externalIds(subjectId).firstAs(new BaseFieldSet().ensure(UserCredential._data)); + if (userCredential != null && userCredential.getData() != null){ + UserCredentialDataEntity userCredentialDataEntity = this.jsonHandlingService.fromJsonSafe(UserCredentialDataEntity.class, userCredential.getData()); + if (userCredentialDataEntity != null) cacheValue.setExternalProviderNames(userCredentialDataEntity.getExternalProviderNames()); + } this.userInterceptorCacheService.put(cacheValue); } finally { @@ -132,11 +146,10 @@ public class UserInterceptor implements WebRequestInterceptor { this.userScope.setUserId(userId); } - private void syncUserWithClaims(UUID userId){ + private void syncUserWithClaims(UUID userId, String subjectId){ List existingUserEmails = this.collectUserEmails(userId); - List existingUserRoles = this.collectUserRoles(userId); - if (!this.emailExistsToUser(existingUserEmails)){ - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); + if (!this.containsPrincipalEmail(existingUserEmails)){ + String email = this.getEmailFromClaims(); long contactUsedByOthersCount = this.queryFactory.query(UserContactInfoQuery.class).excludedUserIds(userId).types(ContactInfoType.Email).values(email).count(); if (contactUsedByOthersCount > 0) { logger.warn("user contact exists to other user" + email); @@ -148,9 +161,37 @@ public class UserInterceptor implements WebRequestInterceptor { } } + List existingUserRoles = this.collectUserRoles(userId); if (!this.userRolesSynced(existingUserRoles)){ this.syncRoles(userId); } + + UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).externalIds(subjectId).first(); + if (userCredential == null) { + throw new MyForbiddenException("UserCredential not found"); + } + else { + boolean updatedUserCredential = false; + UserCredentialDataEntity userCredentialDataEntity = this.jsonHandlingService.fromJsonSafe(UserCredentialDataEntity.class, userCredential.getData()); + if (userCredentialDataEntity == null) userCredentialDataEntity = new UserCredentialDataEntity(); + if (userCredentialDataEntity.getExternalProviderNames() == null) userCredentialDataEntity.setExternalProviderNames(new ArrayList<>()); + + String email = this.getEmailFromClaims(); + String provider = this.getProviderFromClaims(); + + if (email != null && !email.equalsIgnoreCase(userCredentialDataEntity.getEmail())) { + userCredentialDataEntity.setEmail(email); + updatedUserCredential = true; + } + if (provider != null && !provider.isBlank() && userCredentialDataEntity.getExternalProviderNames().stream().noneMatch(provider::equalsIgnoreCase)) { + userCredentialDataEntity.getExternalProviderNames().add(provider); + updatedUserCredential = true; + } + if (updatedUserCredential) { + userCredential.setData(this.jsonHandlingService.toJsonSafe(userCredentialDataEntity)); + this.entityManager.persist(userCredential); + } + } } private UUID findExistingUserFromDb(String subjectId){ @@ -158,7 +199,7 @@ public class UserInterceptor implements WebRequestInterceptor { if (userCredential != null) { return userCredential.getUserId(); } else { - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); + String email = this.getEmailFromClaims(); if (email != null && !email.isBlank()) { UserContactInfoEntity userContactInfo = this.queryFactory.query(UserContactInfoQuery.class).types(ContactInfoType.Email).values(email).firstAs(new BaseFieldSet().ensure(UserContactInfo._user)); if (userContactInfo != null) { @@ -174,14 +215,17 @@ public class UserInterceptor implements WebRequestInterceptor { return null; } - private void syncRoles(UUID userId){ + private List getRolesFromClaims(){ List claimsRoles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal()); if (claimsRoles == null) claimsRoles = new ArrayList<>(); claimsRoles = claimsRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().toList(); - + return claimsRoles; + } + + private void syncRoles(UUID userId){ List existingUserRoles = this.queryFactory.query(UserRoleQuery.class).userIds(userId).collect(); List foundRoles = new ArrayList<>(); - for (String claimRole : claimsRoles) { + for (String claimRole : this.getRolesFromClaims()) { UserRoleEntity roleEntity = existingUserRoles.stream().filter(x-> x.getRole().equals(claimRole)).findFirst().orElse(null); if (roleEntity == null) { roleEntity = this.buildRole(userId, claimRole); @@ -206,17 +250,26 @@ public class UserInterceptor implements WebRequestInterceptor { return items == null ? new ArrayList<>() : items.stream().map(UserContactInfoEntity::getValue).toList(); } - private boolean emailExistsToUser(List existingUserEmails){ - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); + private boolean containsPrincipalEmail(List existingUserEmails){ + String email = this.getEmailFromClaims(); return email == null || email.isBlank() || (existingUserEmails != null && existingUserEmails.stream().anyMatch(email::equals)); } + private boolean emailExistsToPrincipal(String existingUserEmail){ + String email = this.getEmailFromClaims(); + return email == null || email.isBlank() || email.equalsIgnoreCase(existingUserEmail); + } + + private boolean providerExistsToPrincipal(List principalCredentialProviders){ + String provider = this.getProviderFromClaims(); + return provider == null || provider.isBlank() || + (principalCredentialProviders != null && principalCredentialProviders.stream().anyMatch(provider::equalsIgnoreCase)); + } + private boolean userRolesSynced(List existingUserRoles){ - List claimsRoles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal()); - if (claimsRoles == null) claimsRoles = new ArrayList<>(); + List claimsRoles = this.getRolesFromClaims(); if (existingUserRoles == null) existingUserRoles = new ArrayList<>(); - claimsRoles = claimsRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().toList(); existingUserRoles = existingUserRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().toList(); if (claimsRoles.size() != existingUserRoles.size()) return false; @@ -225,9 +278,29 @@ public class UserInterceptor implements WebRequestInterceptor { } return true; } + + private String getEmailFromClaims(){ + String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); + if (email == null || email.isBlank() || !EmailValidator.getInstance().isValid(email)) return null; + return email.trim(); + } + + private String getProviderFromClaims(){ + String provider = this.claimExtractor.asString(this.currentPrincipalResolver.currentPrincipal(), ClaimNames.ExternalProviderName); + if (provider == null || provider.isBlank()) return null; + return provider.trim(); + } private UserCredentialEntity buildCredential(UUID userId, String subjectId){ UserCredentialEntity data = new UserCredentialEntity(); + UserCredentialDataEntity userCredentialDataEntity = new UserCredentialDataEntity(); + + String email = this.getEmailFromClaims(); + String provider = this.getProviderFromClaims(); + if (email != null && !email.isBlank()) userCredentialDataEntity.setEmail(email); + if (provider != null && !provider.isBlank()) userCredentialDataEntity.setExternalProviderNames(List.of(provider)); + data.setData(this.jsonHandlingService.toJsonSafe(userCredentialDataEntity)); + data.setId(UUID.randomUUID()); data.setUserId(userId); data.setCreatedAt(Instant.now()); @@ -258,7 +331,7 @@ public class UserInterceptor implements WebRequestInterceptor { private UserEntity addNewUser(String subjectId, String email){ - List roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal()); + List roles = this.getRolesFromClaims(); String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal()); UserEntity user = new UserEntity(); @@ -267,7 +340,11 @@ public class UserInterceptor implements WebRequestInterceptor { user.setCreatedAt(Instant.now()); user.setUpdatedAt(Instant.now()); user.setIsActive(IsActive.Active); - user.setAdditionalInfo(this.jsonHandlingService.toJsonSafe(new AdditionalInfoEntity())); + AdditionalInfoEntity additionalInfoEntity = new AdditionalInfoEntity(); + additionalInfoEntity.setCulture(this.localeProperties.getCulture()); + additionalInfoEntity.setLanguage(this.localeProperties.getLanguage()); + additionalInfoEntity.setTimezone(this.localeProperties.getTimezone()); + user.setAdditionalInfo(this.jsonHandlingService.toJsonSafe(additionalInfoEntity)); this.entityManager.persist(user); UserCredentialEntity credential = this.buildCredential(user.getId(), subjectId); diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java index d2cbb225f..f742041a8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptorCacheService.java @@ -23,7 +23,6 @@ public class UserInterceptorCacheService extends CacheService roles; - private List emails; + private String providerEmail; + private List externalProviderNames; public UUID getUserId() { return userId; @@ -53,12 +54,20 @@ public class UserInterceptorCacheService extends CacheService getEmails() { - return emails; + public String getProviderEmail() { + return providerEmail; } - public void setEmails(List emails) { - this.emails = emails; + public void setProviderEmail(String providerEmail) { + this.providerEmail = providerEmail; + } + + public List getExternalProviderNames() { + return externalProviderNames; + } + + public void setExternalProviderNames(List externalProviderNames) { + this.externalProviderNames = externalProviderNames; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/CommonsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/CommonsManager.java index b791ee2d2..1c5a6a69a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/CommonsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/CommonsManager.java @@ -2,15 +2,8 @@ package eu.eudat.logic.managers; import eu.eudat.models.data.externalurl.ExternalSourcesConfiguration; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; -import eu.eudat.service.reference.external.ExternalUrlConfigProvider; -import eu.eudat.service.reference.external.config.ExternalUrls; -import eu.eudat.service.storage.StorageFileService; -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import eu.eudat.service.remotefetcher.ExternalUrlConfigProvider; -import java.io.ByteArrayInputStream; import java.util.stream.Collectors; /** diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 63dc03155..7071a0afa 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -6,8 +6,6 @@ import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.*; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.types.dmpblueprint.*; -import eu.eudat.configurations.dynamicgrant.DynamicGrantConfiguration; -import eu.eudat.configurations.dynamicgrant.entities.Property; import eu.eudat.data.*; import eu.eudat.data.dao.criteria.*; import eu.eudat.data.dao.entities.*; @@ -102,7 +100,6 @@ public class DataManagementPlanManager { private DatabaseRepository databaseRepository; private Environment environment; private RDAManager rdaManager; - private UserManager userManager; private final MetricsManager metricsManager; private final ConfigLoader configLoader; private DepositService repositoriesDeposit; @@ -113,7 +110,7 @@ public class DataManagementPlanManager { private final XmlHandlingService xmlHandlingService; @Autowired - public DataManagementPlanManager(XmlHandlingService xmlHandlingService, ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager, + public DataManagementPlanManager(XmlHandlingService xmlHandlingService, ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, MetricsManager metricsManager, ConfigLoader configLoader, DepositService repositoriesDeposit, UserScope userScope, AuthorizationService authorizationService, DmpBlueprintService dmpBlueprintService, QueryFactory queryFactory) { this.xmlHandlingService = xmlHandlingService; this.apiContext = apiContext; @@ -121,7 +118,6 @@ public class DataManagementPlanManager { this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); this.environment = environment; this.rdaManager = rdaManager; - this.userManager = userManager; this.metricsManager = metricsManager; this.configLoader = configLoader; this.userScope = userScope; @@ -368,48 +364,48 @@ public class DataManagementPlanManager { return datamanagementPlan; } - public List> getDynamicFields(String id, DynamicGrantConfiguration dynamicGrantConfiguration, DynamicFieldsCriteria criteria) throws IllegalAccessException, InstantiationException { - List> result = new LinkedList<>(); - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity entity = new HttpEntity<>("parameters", headers); - - Property property = dynamicGrantConfiguration.getConfiguration().getConfigurationProperties().stream() - .filter(item -> item.getId().equals(id)).findFirst().orElse(null); - StringBuilder stringBuilder = new StringBuilder(); - if (criteria.getLike() != null) stringBuilder.append("?search=" + criteria.getLike()); - if (property.getDependencies() != null && !property.getDependencies().isEmpty() && criteria.getDynamicFields() != null && !criteria.getDynamicFields().isEmpty()) { - property.getDependencies().stream().forEach(item -> { - DynamicFieldsCriteria.DynamicFieldDependencyCriteria dependencyCriteria = criteria.getDynamicFields().stream().filter(dfield -> dfield.getProperty().equals(item.getId())) - .findFirst().orElse(null); - if (dependencyCriteria != null) { - if (criteria.getLike() != null || property.getDependencies().indexOf(item) > 0) - stringBuilder.append("&"); - stringBuilder.append(item.getQueryProperty() + "=" + dependencyCriteria.getValue()); - } - }); - - ResponseEntity response = restTemplate.exchange(property.getSourceUrl() + stringBuilder.toString(), HttpMethod.GET, entity, ArrayList.class); - response.getBody().forEach(item -> { - Tuple tuple = new Tuple<>(); - tuple.setId((String) (((Map) item).get(property.getExternalFieldId()))); - tuple.setLabel((String) (((Map) item).get(property.getExternalFieldLabel()))); - result.add(tuple); - }); - - } else { - ResponseEntity response = restTemplate.exchange(property.getSourceUrl() + stringBuilder.toString(), HttpMethod.GET, entity, ArrayList.class); - response.getBody().forEach(item -> { - Tuple tuple = new Tuple<>(); - tuple.setId((String) (((Map) item).get(property.getExternalFieldId()))); - tuple.setLabel((String) (((Map) item).get(property.getExternalFieldLabel()))); - result.add(tuple); - }); - } - return result; - } +// public List> getDynamicFields(String id, DynamicGrantConfiguration dynamicGrantConfiguration, DynamicFieldsCriteria criteria) throws IllegalAccessException, InstantiationException { +// List> result = new LinkedList<>(); +// RestTemplate restTemplate = new RestTemplate(); +// HttpHeaders headers = new HttpHeaders(); +// headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); +// headers.setContentType(MediaType.APPLICATION_JSON); +// HttpEntity entity = new HttpEntity<>("parameters", headers); +// +// Property property = dynamicGrantConfiguration.getConfiguration().getConfigurationProperties().stream() +// .filter(item -> item.getId().equals(id)).findFirst().orElse(null); +// StringBuilder stringBuilder = new StringBuilder(); +// if (criteria.getLike() != null) stringBuilder.append("?search=" + criteria.getLike()); +// if (property.getDependencies() != null && !property.getDependencies().isEmpty() && criteria.getDynamicFields() != null && !criteria.getDynamicFields().isEmpty()) { +// property.getDependencies().stream().forEach(item -> { +// DynamicFieldsCriteria.DynamicFieldDependencyCriteria dependencyCriteria = criteria.getDynamicFields().stream().filter(dfield -> dfield.getProperty().equals(item.getId())) +// .findFirst().orElse(null); +// if (dependencyCriteria != null) { +// if (criteria.getLike() != null || property.getDependencies().indexOf(item) > 0) +// stringBuilder.append("&"); +// stringBuilder.append(item.getQueryProperty() + "=" + dependencyCriteria.getValue()); +// } +// }); +// +// ResponseEntity response = restTemplate.exchange(property.getSourceUrl() + stringBuilder.toString(), HttpMethod.GET, entity, ArrayList.class); +// response.getBody().forEach(item -> { +// Tuple tuple = new Tuple<>(); +// tuple.setId((String) (((Map) item).get(property.getExternalFieldId()))); +// tuple.setLabel((String) (((Map) item).get(property.getExternalFieldLabel()))); +// result.add(tuple); +// }); +// +// } else { +// ResponseEntity response = restTemplate.exchange(property.getSourceUrl() + stringBuilder.toString(), HttpMethod.GET, entity, ArrayList.class); +// response.getBody().forEach(item -> { +// Tuple tuple = new Tuple<>(); +// tuple.setId((String) (((Map) item).get(property.getExternalFieldId()))); +// tuple.setLabel((String) (((Map) item).get(property.getExternalFieldLabel()))); +// result.add(tuple); +// }); +// } +// return result; +// } public DataTableData getDatasetProfilesUsedByDMP(DatasetProfileTableRequestItem datasetProfileTableRequestItem) throws InvalidApplicationException { datasetProfileTableRequestItem.getCriteria().setFilter(DatasetProfileCriteria.DatasetProfileFilter.DMPs.getValue()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java index 4a83e1363..8f4817134 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java @@ -104,7 +104,6 @@ public class DatasetManager { private DatabaseRepository databaseRepository; // private DatasetRepository datasetRepository; private BuilderFactory builderFactory; - private UserManager userManager; private ConfigLoader configLoader; private Environment environment; private final MetricsManager metricsManager; @@ -114,13 +113,12 @@ public class DatasetManager { private final QueryFactory queryFactory; @Autowired - public DatasetManager(ApiContext apiContext, UserManager userManager, ConfigLoader configLoader, Environment environment, MetricsManager metricsManager, + public DatasetManager(ApiContext apiContext, ConfigLoader configLoader, Environment environment, MetricsManager metricsManager, FileManager fileManager, UserScope userScope, AuthorizationService authorizationService, QueryFactory queryFactory) { this.apiContext = apiContext; this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); // this.datasetRepository = apiContext.getOperationsContext().getElasticRepository().getDatasetRepository(); this.builderFactory = apiContext.getOperationsContext().getBuilderFactory(); - this.userManager = userManager; this.configLoader = configLoader; this.environment = environment; this.metricsManager = metricsManager; @@ -400,15 +398,15 @@ public class DatasetManager { } public PagedDatasetProfile getPagedProfile(DatasetWizardModel dataset, DescriptionEntity descriptionEntityEntity) { - eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(this.queryFactory.query(DescriptionTemplateQuery.class).ids(descriptionEntityEntity.getDescriptionTemplateId()).first()); - datasetprofile.setStatus(dataset.getStatus().getValue()); - if (descriptionEntityEntity.getProperties() != null) { - JSONObject jObject = new JSONObject(descriptionEntityEntity.getProperties()); - Map properties = jObject.toMap(); - datasetprofile.fromJsonObject(properties); - } +// eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(this.queryFactory.query(DescriptionTemplateQuery.class).ids(descriptionEntityEntity.getDescriptionTemplateId()).first()); +// datasetprofile.setStatus(dataset.getStatus().getValue()); +// if (descriptionEntityEntity.getProperties() != null) { +// JSONObject jObject = new JSONObject(descriptionEntityEntity.getProperties()); +// Map properties = jObject.toMap(); +// datasetprofile.fromJsonObject(properties); +// } PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); - pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); +// pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); return pagedDatasetProfile; } @@ -1069,18 +1067,18 @@ public class DatasetManager { } - public PagedDatasetProfile getLatestDatasetProfile(DescriptionEntity descriptionEntityEntity, DescriptionTemplateEntity profile) { - eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(profile); - datasetprofile.setStatus(descriptionEntityEntity.getStatus().getValue()); - if (descriptionEntityEntity.getProperties() != null) { - JSONObject jobject = new JSONObject(descriptionEntityEntity.getProperties()); - Map properties = jobject.toMap(); - datasetprofile.fromJsonObject(properties); - } - PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); - pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); - return pagedDatasetProfile; - } +// public PagedDatasetProfile getLatestDatasetProfile(DescriptionEntity descriptionEntityEntity, DescriptionTemplateEntity profile) { +// eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(profile); +// datasetprofile.setStatus(descriptionEntityEntity.getStatus().getValue()); +// if (descriptionEntityEntity.getProperties() != null) { +// JSONObject jobject = new JSONObject(descriptionEntityEntity.getProperties()); +// Map properties = jobject.toMap(); +// datasetprofile.fromJsonObject(properties); +// } +// PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); +// pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); +// return pagedDatasetProfile; +// } public DataTableData getDatasetProfilesUsedByDatasets(DatasetProfileTableRequestItem datasetProfileTableRequestItem) throws InvalidApplicationException { datasetProfileTableRequestItem.getCriteria().setFilter(DatasetProfileCriteria.DatasetProfileFilter.Datasets.getValue()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java index 78e7ec9ff..e4cf8cba6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java @@ -5,17 +5,17 @@ import eu.eudat.commons.types.descriptiontemplate.fielddata.AutoCompleteDataEnti import eu.eudat.commons.types.xml.XmlBuilder; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; -import eu.eudat.service.reference.external.config.entities.GeneralUrls; -import eu.eudat.service.reference.external.RemoteFetcher; +import eu.eudat.service.remotefetcher.config.entities.GeneralUrls; +import eu.eudat.service.remotefetcher.RemoteFetcherService; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.operations.DatabaseRepository; -import eu.eudat.models.data.externaldataset.ExternalAutocompleteFieldModel; -import eu.eudat.service.reference.external.config.AuthenticationConfiguration; -import eu.eudat.service.reference.external.config.DataFieldsUrlConfiguration; -import eu.eudat.service.reference.external.config.DataUrlConfiguration; -import eu.eudat.service.reference.external.config.UrlConfiguration; -import eu.eudat.service.reference.external.criteria.ExternalReferenceCriteria; -import eu.eudat.service.reference.external.criteria.FetchStrategy; +import eu.eudat.service.remotefetcher.models.ExternalAutocompleteFieldResult; +import eu.eudat.service.remotefetcher.config.AuthenticationConfiguration; +import eu.eudat.service.remotefetcher.config.DataFieldsUrlConfiguration; +import eu.eudat.service.remotefetcher.config.DataUrlConfiguration; +import eu.eudat.service.remotefetcher.config.UrlConfiguration; +import eu.eudat.service.remotefetcher.criteria.ExternalReferenceCriteria; +import eu.eudat.service.remotefetcher.criteria.FetchStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -50,13 +50,13 @@ public class DatasetProfileManager { private final DatabaseRepository databaseRepository; private final ConfigLoader configLoader; - private final RemoteFetcher remoteFetcher; + private final RemoteFetcherService remoteFetcherService; @Autowired - public DatasetProfileManager(ApiContext apiContext, ConfigLoader configLoader, RemoteFetcher remoteFetcher) { + public DatasetProfileManager(ApiContext apiContext, ConfigLoader configLoader, RemoteFetcherService remoteFetcherService) { this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); this.configLoader = configLoader; - this.remoteFetcher = remoteFetcher; + this.remoteFetcherService = remoteFetcherService; } public FieldEntity queryForField(String xml, String fieldId) throws XPathExpressionException { @@ -71,7 +71,7 @@ public class DatasetProfileManager { return fieldEntity; } - public List getAutocomplete(AutoCompleteDataEntity data, String like) { + public List getAutocomplete(AutoCompleteDataEntity data, String like) { /*List result = new LinkedList<>(); SimpleClientHttpRequestFactory simpleFactory = new SimpleClientHttpRequestFactory(); @@ -136,7 +136,7 @@ public class DatasetProfileManager { return result.stream().sorted(Comparator.comparing(ExternalAutocompleteFieldModel::getLabel)).collect(Collectors.toList()); */ - List result = new LinkedList<>(); + List result = new LinkedList<>(); ExternalReferenceCriteria urlCriteria = new ExternalReferenceCriteria(); GeneralUrls genericUrls = new GeneralUrls(); int ordinal = 1; @@ -189,7 +189,7 @@ public class DatasetProfileManager { urlConfiguration.setAuth(authenticationConfiguration); } genericUrls.getUrls().add(urlConfiguration); - List> singleResults = this.remoteFetcher.getExternalGeneric(urlCriteria, genericUrls); + List> singleResults = this.remoteFetcherService.getExternalGeneric(urlCriteria, genericUrls); if (!singleResults.isEmpty() && !singleResults.get(0).containsKey("source") && !singleData.getAutoCompleteOptions().getSource().isEmpty()) { singleResults.forEach(singleResult -> singleResult.put("source", singleData.getAutoCompleteOptions().getSource())); } @@ -199,7 +199,7 @@ public class DatasetProfileManager { logger.error(e.getMessage(), e); } } - rawResults.forEach(item -> result.add(new ExternalAutocompleteFieldModel(parseItem(item.get("pid")), parseItem(item.get("name")), parseItem(item.get("source")), parseItem(item.get("uri"))))); + rawResults.forEach(item -> result.add(new ExternalAutocompleteFieldResult(parseItem(item.get("pid")), parseItem(item.get("name")), parseItem(item.get("source")), parseItem(item.get("uri"))))); return result; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java deleted file mode 100644 index 28bb63842..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java +++ /dev/null @@ -1,86 +0,0 @@ -package eu.eudat.logic.managers; - -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.data.old.EmailConfirmation; -import eu.eudat.data.UserEntity; -import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; -import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.logic.services.operations.DatabaseRepository; -import eu.eudat.query.UserQuery; -import gr.cite.tools.data.query.QueryFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.management.InvalidApplicationException; -import java.util.Date; -import java.util.UUID; - -@Component -public class EmailConfirmationManager { - private ApiContext apiContext; - private DatabaseRepository databaseRepository; - private final UserScope userScope; - private final QueryFactory queryFactory; - - @Autowired - public EmailConfirmationManager(ApiContext apiContext, UserScope userScope, QueryFactory queryFactory) { - this.apiContext = apiContext; - this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); - this.userScope = userScope; - this.queryFactory = queryFactory; - } - - public void confirmEmail(String token) throws TokenExpiredException, HasConfirmedEmailException, InvalidApplicationException { - EmailConfirmation loginConfirmationEmail = apiContext.getOperationsContext() - .getDatabaseRepository().getLoginConfirmationEmailDao().asQueryable() - .where((builder, root) -> builder.equal(root.get("token"), UUID.fromString(token))).getSingle(); - - UserEntity user = this.queryFactory.query(UserQuery.class).ids(loginConfirmationEmail.getUserId()).first(); - -// if (user.getEmail() != null) //TODO -// throw new HasConfirmedEmailException("User already has confirmed his Email."); - - if (loginConfirmationEmail.getExpiresAt().compareTo(new Date()) < 0) - throw new TokenExpiredException("Token has expired."); - - loginConfirmationEmail.setIsConfirmed(true); - - // Checks if mail is used by another user. If it is, merges the new the old. - Long existingUsers = this.queryFactory.query(UserQuery.class).emails(loginConfirmationEmail.getEmail()).count(); - if (existingUsers > 0) { -// UserCredentialEntity credential = databaseRepository.getCredentialDao().asQueryable().where((builder, root) -> builder.equal(root.get("userId"), user.getId())).getSingle(); -// credential.setEmail(loginConfirmationEmail.getEmail()); //TODO -// databaseRepository.getCredentialDao().createOrUpdate(credential); - UserEntity oldUser = this.queryFactory.query(UserQuery.class).emails(loginConfirmationEmail.getEmail()).first(); - mergeNewUserToOld(user, oldUser); -// expireUserToken(user); //TODO: Authn - databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail); - return; - } - -// user.setEmail(loginConfirmationEmail.getEmail()); //TODO -// databaseRepository.getUserInfoDao().createOrUpdate(user); -// UserCredentialEntity credential = databaseRepository.getCredentialDao().asQueryable() -// .where((builder, root) -> builder.equal(root.get("userId"), user.getId())).getSingle(); -// if(credential.getEmail() == null){//TODO -// credential.setEmail(user.getEmail()); -// databaseRepository.getCredentialDao().createOrUpdate(credential); -// } - databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail); - } - - public void sendConfirmationEmail(String email) throws HasConfirmedEmailException, InvalidApplicationException { - UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first(); -// if (user.getEmail() != null) //TODO -// throw new HasConfirmedEmailException("User already has confirmed his Email."); - - apiContext.getUtilitiesService().getConfirmationEmailService().sentConfirmationEmail(databaseRepository.getLoginConfirmationEmailDao(), email, user); - } - - private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser) throws InvalidApplicationException { -// UserCredentialEntity credential = databaseRepository.getCredentialDao().asQueryable().where((builder, root) -> builder.equal(root.get("userId"), newUser.getId())).getSingle(); -// credential.setUserId(oldUser.getId()); -// databaseRepository.getCredentialDao().createOrUpdate(credential); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java deleted file mode 100644 index 64204938e..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java +++ /dev/null @@ -1,177 +0,0 @@ -package eu.eudat.logic.managers; - -import eu.eudat.commons.enums.DmpUserRole; -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.data.DmpEntity; -import eu.eudat.data.DmpUserEntity; -import eu.eudat.data.UserEntity; -import eu.eudat.exceptions.security.UnauthorisedException; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.model.User; -import eu.eudat.models.data.invitation.Invitation; -import eu.eudat.query.DmpQuery; -import eu.eudat.query.UserQuery; -import gr.cite.tools.data.query.QueryFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import jakarta.xml.bind.JAXBException; - -import javax.management.InvalidApplicationException; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -@Component -public class InvitationsManager { - - private ApiContext apiContext; - private DataManagementPlanManager dataManagementPlanManager; - private final UserScope userScope; - private final QueryFactory queryFactory; - - @Autowired - public InvitationsManager(ApiContext apiContext, DataManagementPlanManager dataManagementPlanManager, UserScope userScope, QueryFactory queryFactory) { - this.apiContext = apiContext; - this.dataManagementPlanManager = dataManagementPlanManager; - this.userScope = userScope; - this.queryFactory = queryFactory; - } - - public void inviteUsers(Invitation invitation) throws Exception { - UserEntity principalUser = new UserEntity(); - principalUser.setId(this.userScope.getUserIdSafe()); - invitation.getUsers().stream().filter(item -> item.getId() == null).forEach(item -> { - UserEntity existingUser = null; -// try { -// //TODO: email -// //existingUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), item.getEmail())).getSingleOrDefault(); -// } catch (InvalidApplicationException e) { -// throw new RuntimeException(e); -// } - if (existingUser != null) { - item.setId(existingUser.getId()); - } - }); - List alreadySignedInUsers = invitation.getUsers().stream().filter(item -> item.getId() != null).collect(Collectors.toList()); - List alreadySignedInUsersEntities = new ArrayList<>(); //alreadySignedInUsers.stream().map(User::toDataModel).collect(Collectors.toList()); - List userInfoToUserDmp = new LinkedList<>(); - for (UserEntity userInfo : alreadySignedInUsersEntities) { - DmpUserEntity userDMP = new DmpUserEntity(); - userDMP.setUserId(userInfo.getId()); - userDMP.setRole(DmpUserRole.of(invitation.getRole().shortValue())); - userInfoToUserDmp.add(userDMP); - /*if (!apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().areAssociated(principalUser, userInfo)) { - UserAssociation userAssociation = new UserAssociation(); - userAssociation.setFirstUser(principalUser); - userAssociation.setSecondUser(userInfo); - apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation); - }*/ - } - DmpQuery dmpQuery = this.queryFactory.query(DmpQuery.class).ids(invitation.getDataManagementPlan()); - if(dmpQuery != null){ -// DmpEntity dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan()); - DmpEntity dmpEntity = dmpQuery.first(); - UserQuery userQuery = this.queryFactory.query(UserQuery.class).ids(invitation.getUsers().stream().map(user -> user.getId()).collect(Collectors.toList())); - if (userQuery != null){ - List userEntities = userQuery.collect(); -// apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), invitation.getUsers().stream().map(UserInfoInvitationModel::toDataModel).collect(Collectors.toList()), dmpEntity, invitation.getRole(), principalUser); - apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), userEntities, dmpEntity, invitation.getRole(), principalUser); - apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userInfoToUserDmp, dmpEntity); - } - } - - } - - public List getUsers() throws InstantiationException, IllegalAccessException, InvalidApplicationException { - /*UserInfo principalUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); - List users = apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().getAssociated(principalUser).stream().map(userAssociation -> { - if (userAssociation.getFirstUser().getId().equals(principal.getId())) { - return userAssociation.getSecondUser(); - } else { - return userAssociation.getFirstUser(); - } - }).collect(Collectors.toList());*/ - List users = new ArrayList<>(); - //TODO -// apiContext.getOperationsContext().getDatabaseRepository().getDmpDao() -// .getAuthenticated(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().asQueryable() -// .where(((builder, root) -> builder.notEqual(root.get("isActive"), IsActive.Inactive))), this.userScope.getUserId(), Stream.of(0, 1).collect(Collectors.toList())) -// .toList().stream().map(DmpEntity::getUsers).flatMap(Collection::stream).map(DmpUser::getUser) -// .filter(userInfo -> !userInfo.getId().equals(this.userScope.getUserIdSafe())).filter(StreamDistinctBy.distinctByKey(UserInfo::getId)).collect(Collectors.toList()); - List userModels = new ArrayList<>(); //users.stream().map(userInfo -> new User().fromDataModel(userInfo)).collect(Collectors.toList()); - return userModels; - } - -// public List getUsersWithCriteria(UserInfoRequestItem userInfoRequestItem) throws IllegalAccessException, InstantiationException, InvalidApplicationException { -// //TODO -//// List users = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao() -//// .getAuthenticated(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().asQueryable() -//// .where(((builder, root) -> -//// builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue()))), this.userScope.getUserId(), Stream.of(0, 1).collect(Collectors.toList())) -//// .toList().stream().map(DMP::getUsers).flatMap(Collection::stream).map(UserDMP::getUser) -//// .filter(userInfo -> !userInfo.getId().equals(this.userScope.getUserIdSafe())).filter(StreamDistinctBy.distinctByKey(UserInfo::getId)) -//// .filter(userInfo -> (userInfoRequestItem == null || userInfoRequestItem.getCriteria() == null || userInfoRequestItem.getCriteria().getLike() == null -//// || userInfo.getName().toLowerCase().contains(userInfoRequestItem.getCriteria().getLike().toLowerCase()) -//// || (userInfo.getEmail().toLowerCase().contains(userInfoRequestItem.getCriteria().getLike().toLowerCase())))) -//// .collect(Collectors.toList()); -////// .where((builder, root) -> builder.like(builder.upper(root.get("name")), "%" + userInfoRequestItem.getCriteria().getLike().toUpperCase() + "%")) -//// -//// List userModels = users.stream().map(userInfo -> new UserInfoInvitationModel().fromDataModel(userInfo)).collect(Collectors.toList()); -//// return userModels; -// return new ArrayList<>(); -// } - - public UUID assignUserAcceptedInvitation(UUID invitationID) throws UnauthorisedException, JAXBException, IOException, InvalidApplicationException { - //TODO -// eu.eudat.data.old.Invitation invitation = apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().find(invitationID); -// if (invitation == null) -// throw new UnauthorisedException("There is no Data Management Plan assigned to this Link"); -// if (invitation.getAcceptedInvitation()) return invitation.getDmp().getId(); //throw new UnauthorisedException("This Url Has Expired"); -// JAXBContext context = JAXBContext.newInstance(Properties.class); -// Unmarshaller unmarshaller = context.createUnmarshaller(); -// Properties properties = (Properties) unmarshaller.unmarshal(new StringReader(invitation.getProperties())); -// UserInfo invitedUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(this.userScope.getUserId()); -// QueryableList userDMPQueryableList = apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().asQueryable().where(((builder, root) -> builder.and(builder.equal(root.get("dmp").get("id"), invitation.getDmp().getId()), builder.equal(root.get("user").get("id"), invitedUser.getId())))); -// UserDMP existingUserDMP = userDMPQueryableList.getSingleOrDefault(); -// if (existingUserDMP != null) { -// if (properties.getRole() != null && existingUserDMP.getRole() > properties.getRole()) { -// existingUserDMP.setRole(properties.getRole()); -// DMP datamanagementPlan = invitation.getDmp(); -// apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(existingUserDMP); -// apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), existingUserDMP, datamanagementPlan); -// invitation.setAcceptedInvitation(true); -// apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().createOrUpdate(invitation); -// datamanagementPlan.setUsers(new HashSet<>(apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().asQueryable().where((builder, root) -> builder.equal(root.get("dmp").get("id"), datamanagementPlan.getId())).toList())); -// //dataManagementPlanManager.updateIndex(datamanagementPlan); //TODO -// return datamanagementPlan.getId(); -// } -// } else { -// UserDMP userDMP = new UserDMP(); -// userDMP.setUser(invitedUser); -// userDMP.setDmp(invitation.getDmp()); -// -// if (properties.getRole() != null) { -// userDMP.setRole(properties.getRole()); -// } else { -// userDMP.setRole(UserDMP.UserDMPRoles.USER.getValue()); -// } -// /*if (!apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().areAssociated(invitedUser, invitation.getUser())) { -// UserAssociation userAssociation = new UserAssociation(); -// userAssociation.setFirstUser(invitedUser); -// userAssociation.setSecondUser(invitation.getUser()); -// apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation); -// }*/ -// DmpEntity datamanagementPlan = invitation.getDmp(); -// apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(userDMP); -// apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userDMP, datamanagementPlan); -// invitation.setAcceptedInvitation(true); -// apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().createOrUpdate(invitation); -// datamanagementPlan.setUsers(new HashSet<>(apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().asQueryable().where((builder, root) -> builder.equal(root.get("dmp").get("id"), datamanagementPlan.getId())).toList())); -//// dataManagementPlanManager.updateIndex(datamanagementPlan); //TODo -// return datamanagementPlan.getId(); -// } -// return invitation.getDmp().getId(); - return null; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java deleted file mode 100644 index 6f813a5e4..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java +++ /dev/null @@ -1,144 +0,0 @@ -package eu.eudat.logic.managers; - -import eu.eudat.commons.enums.IsActive; -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.data.DmpUserEntity; -import eu.eudat.data.old.EmailConfirmation; -import eu.eudat.data.UserEntity; -import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; -import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.logic.services.operations.DatabaseRepository; - -import eu.eudat.model.UserContactInfo; -import eu.eudat.query.UserContactInfoQuery; -import eu.eudat.query.UserQuery; -import gr.cite.tools.data.query.Ordering; -import gr.cite.tools.data.query.QueryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import jakarta.transaction.Transactional; - -import javax.management.InvalidApplicationException; -import java.util.*; - -@Component -public class MergeEmailConfirmationManager { - private static Logger logger = LoggerFactory.getLogger(MergeEmailConfirmationManager.class); - private ApiContext apiContext; - private DatabaseRepository databaseRepository; -// private DmpRepository dmpRepository; - private final UserScope userScope; - private final QueryFactory queryFactory; - - @Autowired - public MergeEmailConfirmationManager(ApiContext apiContext, UserScope userScope, QueryFactory queryFactory) { - this.apiContext = apiContext; - this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); -// this.dmpRepository = apiContext.getOperationsContext().getElasticRepository().getDmpRepository(); - this.userScope = userScope; - this.queryFactory = queryFactory; - } - - @Transactional - public String confirmEmail(String token) throws TokenExpiredException, HasConfirmedEmailException, InvalidApplicationException { - EmailConfirmation loginConfirmationEmail = apiContext.getOperationsContext() - .getDatabaseRepository().getLoginConfirmationEmailDao().asQueryable() - .where((builder, root) -> builder.equal(root.get("token"), UUID.fromString(token))).getSingle(); - - if (loginConfirmationEmail.getExpiresAt().compareTo(new Date()) < 0) - throw new TokenExpiredException("Token has expired."); - - UserEntity userToBeMerged = this.queryFactory.query(UserQuery.class).ids(loginConfirmationEmail.getUserId()).first(); - String userToBeMergedEmail = ""; //TODO userToBeMerged.getEmail(); - try { - Map map = new ObjectMapper().readValue(loginConfirmationEmail.getData(), HashMap.class); - UUID otherUserId = UUID.fromString((String) map.get("userId")); - UserEntity user = this.queryFactory.query(UserQuery.class).ids(otherUserId).first(); - - // Checks if mail is used by another user. If it is, merges the new the old. - mergeNewUserToOld(user, userToBeMerged, Integer.valueOf((String) map.get("provider"))); - //expireUserToken(userToBeMerged); //TODO: Authn - loginConfirmationEmail.setIsConfirmed(true); - databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - - return userToBeMergedEmail; - } - - public void sendMergeConfirmationEmail(String email, Integer provider) throws HasConfirmedEmailException, InvalidApplicationException { - UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first(); - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - if (query.first().getValue() != null && !query.first().getValue().equals(email)) { - apiContext.getUtilitiesService().getConfirmationEmailService().sentMergeConfirmationEmail( - databaseRepository.getLoginConfirmationEmailDao(), - email, - user, - provider - ); - } - } - - @Transactional - private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser, Integer provider) throws InvalidApplicationException { -// UserCredentialEntity credential = databaseRepository.getCredentialDao().asQueryable().where((builder, root) -> builder.and(builder.equal(root.get("userId"), oldUser.getId()), builder.equal(root.get("provider"), provider))).getSingle(); -// credential.setUserId(newUser.getId()); -// databaseRepository.getCredentialDao().createOrUpdate(credential); -// List userDmps = databaseRepository.getUserDmpDao().asQueryable().where((builder, root) -> builder.equal(root.get("user"), oldUser)).toList(); -// userDmps.forEach(userDmp -> { -// userDmp.setUserId(newUser.getId()); -// databaseRepository.getUserDmpDao().createOrUpdate(userDmp); -// }); - //TODO -// try { -// -// DmpCriteria dmpCriteria = new DmpCriteria(); -// dmpCriteria.setCollaborators(Collections.singletonList(oldUser.getId())); -// List elasticDmpsIds = dmpRepository.query(dmpCriteria); -// for(Dmp dmpId: elasticDmpsIds){ -// Dmp dmp = dmpRepository.findDocument(dmpId.getId().toString()); -// if(dmp.getDatasets() != null) { -// dmp.getDatasets().forEach(dataset -> { -// if(dataset.getCollaborators() != null) { -// for (Collaborator collaborator : dataset.getCollaborators()) { -// if (collaborator.getId().equals(oldUser.getId().toString())) { -// collaborator.setId(newUser.getId().toString()); -// collaborator.setName(newUser.getName()); -// } -// } -// } -// }); -// } -// if(dmp.getCollaborators() != null) { -// for (Collaborator collaborator : dmp.getCollaborators()) { -// if (collaborator.getId().equals(oldUser.getId().toString())) { -// collaborator.setId(newUser.getId().toString()); -// collaborator.setName(newUser.getName()); -// } -// } -// } -// dmpRepository.createOrUpdate(dmp); -// } -// } -// catch (IOException e){ -// logger.warn("Warning: Could not fetch dmps from elastic.", e); -// } - oldUser.setIsActive(IsActive.Inactive); - //TODO oldUser.setEmail(null); -// List credentials = databaseRepository.getCredentialDao().asQueryable().where((builder, root) -> builder.equal(root.get("userId"), oldUser.getId())).toList(); -// credentials.forEach(cred -> { -// if (cred.getId() != credential.getId()) { -// databaseRepository.getCredentialDao().delete(cred); -// } -// }); -// databaseRepository.getUserInfoDao().createOrUpdate(oldUser); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MetricsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MetricsManager.java index 919a7ecc7..cecf1c854 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MetricsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MetricsManager.java @@ -78,14 +78,12 @@ public class MetricsManager { } private final ApiContext apiContext; - private final UserManager userManager; private final Environment environment; private final QueryFactory queryFactory; @Autowired - public MetricsManager(ApiContext apiContext, UserManager userManager, Environment environment, PrometheusMeterRegistry registry, QueryFactory queryFactory) { + public MetricsManager(ApiContext apiContext, Environment environment, PrometheusMeterRegistry registry, QueryFactory queryFactory) { this.apiContext = apiContext; - this.userManager = userManager; this.environment = environment; this.queryFactory = queryFactory; registry.clear(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/NotificationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/NotificationManager.java deleted file mode 100644 index b4c414887..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/NotificationManager.java +++ /dev/null @@ -1,115 +0,0 @@ -package eu.eudat.logic.managers; - -import eu.eudat.logic.services.ApiContext; -import gr.cite.tools.data.query.QueryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; - -@Component -public class NotificationManager { - private static final Logger logger = LoggerFactory.getLogger(NotificationManager.class); - - private ApiContext apiContext; - private Environment environment; - private final QueryFactory queryFactory; - - @Autowired - public NotificationManager(ApiContext apiContext, Environment environment, -// MailService mailService, - QueryFactory queryFactory) { - this.apiContext = apiContext; - this.environment = environment; - this.queryFactory = queryFactory; - } - -// @Transactional -// public void sendNotification(Notification notification) throws Exception { -// if (notification.getNotifyState() == NotifyState.ERROR) { -// if (notification.getRetryCount() == null) { -// notification.setRetryCount(0); -// } -// notification.setRetryCount(notification.getRetryCount() + 1); -// if (notification.getRetryCount() >= this.environment.getProperty("notification.maxRetries", Integer.class)) { -// notification.setIsActive(ActiveStatus.INACTIVE); -// notification.setUpdatedAt(new Date()); -// return; -// } -// } -// notification.setNotifyState(NotifyState.PROCESSING); -// notification.setNotifiedAt(new Date()); -// notification.setUpdatedAt(new Date()); -// try { -// Map data = new ObjectMapper().readValue(notification.getData(), HashMap.class); -// UserEntity userInfo = this.queryFactory.query(UserQuery.class).ids(UUID.fromString(data.get("userId"))).first(); -// String subjectTemplate = ""; -// String contentTemplate = ""; -// -// switch (notification.getType()) { -// case DMP_MODIFIED: -// case DATASET_MODIFIED: -// subjectTemplate = this.environment.getProperty("notification.modified.subject"); -//// contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.modified.template")); -// break; -// case DMP_PUBLISH: -// subjectTemplate = this.environment.getProperty("notification.publish.subject"); -//// contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.publish.template")); -// break; -// case DMP_FINALISED: -// subjectTemplate = this.environment.getProperty("notification.finalised.subject"); -//// contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.finalised.template")); -// break; -// case DMP_MODIFIED_FINALISED: -// case DATASET_MODIFIED_FINALISED: -// subjectTemplate = this.environment.getProperty("notification.modifiedFinalised.subject"); -//// contentTemplate = mailService.getMailTemplateContent(this.environment.getProperty("notification.modified_finalised.template")); -// break; -// } -// -// -// switch (notification.getContactTypeHint()) { -// case EMAIL: -// this.sendEmailNotification(notification, userInfo, data, subjectTemplate, contentTemplate); -// break; -// } -// }catch (Exception e) { -// notification.setNotifyState(NotifyState.ERROR); -// notification.setUpdatedAt(new Date()); -// logger.error(e.getMessage(), e); -// } -// } -// -// private void sendEmailNotification(Notification notification, UserEntity userInfo, Map data, String subjectTemplate, String contentTemplate) throws IOException { -//// SimpleMail simpleMail = new SimpleMail(); -//// simpleMail.setFrom(this.environment.getProperty("mail.from")); -//// simpleMail.setSubject(makeSubject(data, subjectTemplate)); -//// simpleMail.setTo(notification.getContactHint()); -//// simpleMail.setContent(makeContent(data, notification, userInfo, contentTemplate)); -//// try { -//// mailService.sendSimpleMail(simpleMail); -//// notification.setNotifyState(NotifyState.SUCCEEDED); -//// notification.setUpdatedAt(new Date()); -//// } catch (MessagingException e) { -//// notification.setNotifyState(NotifyState.ERROR); -//// notification.setUpdatedAt(new Date()); -//// logger.error(e.getMessage(), e); -//// } -// } -// -// private String makeSubject(Map data, String subjectTemplate) { -// return subjectTemplate.replace("{name}", data.get("name")); -// } -// -// private String makeContent(Map data, Notification notification, UserEntity userInfo, String template) { -// String content = template; -// content = content.replace("{recipient}", userInfo.getName()); -// for (String key : data.keySet()) { -// content = content.replace("{" + key +"}", data.get(key)); -// } -// content = content.replace("{host}", this.environment.getProperty("dmp.domain")); -// content = content.replace("{reasonName}", notification.getUserId().getName()); -// return content; -// } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/PrefillingManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/PrefillingManager.java deleted file mode 100644 index 78966a461..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/PrefillingManager.java +++ /dev/null @@ -1,96 +0,0 @@ -package eu.eudat.logic.managers; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import eu.eudat.data.DescriptionTemplateEntity; -import eu.eudat.logic.mapper.prefilling.PrefillingMapper; -import eu.eudat.service.reference.external.ExternalUrlConfigProvider; -import eu.eudat.service.reference.external.RemoteFetcher; -import eu.eudat.service.reference.external.config.ExternalUrls; -import eu.eudat.service.reference.external.criteria.ExternalReferenceCriteria; -import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; -import eu.eudat.service.reference.external.config.entities.PrefillingConfig; -import eu.eudat.service.reference.external.config.entities.PrefillingGet; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.models.data.datasetwizard.DatasetWizardModel; -import eu.eudat.models.data.prefilling.Prefilling; -import eu.eudat.service.storage.StorageFileService; -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.io.ByteArrayInputStream; -import java.util.*; -import java.util.stream.Collectors; - -@Service -public class PrefillingManager { - private static final Logger logger = LoggerFactory.getLogger(PrefillingManager.class); - - private final ApiContext apiContext; - private final ObjectMapper objectMapper; - private final DatasetManager datasetManager; -// private final LicenseManager licenseManager; - private final PrefillingMapper prefillingMapper; - private final ExternalUrlConfigProvider externalUrlConfigProvider; - - @Autowired - public PrefillingManager(ApiContext apiContext, DatasetManager datasetManager /*, LicenseManager licenseManager*/, PrefillingMapper prefillingMapper, ExternalUrlConfigProvider externalUrlConfigProvider) { - this.apiContext = apiContext; - this.prefillingMapper = prefillingMapper; - this.externalUrlConfigProvider = externalUrlConfigProvider; - this.objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.datasetManager = datasetManager; -// this.licenseManager = licenseManager; - } - - public List getPrefillings(String like) { - ExternalReferenceCriteria externalReferenceCriteria = new ExternalReferenceCriteria(); - externalReferenceCriteria.setLike(like); - List prefillings = new ArrayList<>(); - List> map; - Map prefillingConfigs = this.externalUrlConfigProvider.getExternalUrls().getPrefillings(); - for (PrefillingConfig prefillingConfig: prefillingConfigs.values()) { - map = apiContext.getOperationsContext().getRemoteFetcher().getExternalGeneric(externalReferenceCriteria, prefillingConfig.getPrefillingSearch()); - prefillings.addAll(map.stream().map(submap -> objectMapper.convertValue(submap, Prefilling.class)).collect(Collectors.toList())); - if (prefillingConfig.getPrefillingSearch().getUrlConfig().isDataInListing()) { - List> mapData = apiContext.getOperationsContext().getRemoteFetcher().getExternalGenericWithData(externalReferenceCriteria, prefillingConfig.getPrefillingSearch()); - for (int i = 0; i < mapData.size(); i++) { - prefillings.get(i).setData(mapData.get(i)); - } - prefillings = prefillings.stream().filter(prefilling -> prefilling.getData() != null).collect(Collectors.toList()); - } - } - return prefillings; - } - - public DatasetWizardModel getPrefilledDataset(String prefillId, String configId, UUID profileId) throws Exception { - PrefillingConfig prefillingConfig = this.externalUrlConfigProvider.getExternalUrls().getPrefillings().get(configId); - PrefillingGet prefillingGet = prefillingConfig.getPrefillingGet(); - Map prefillingEntity = getSingle(prefillingGet.getUrl(), prefillId); - DescriptionTemplateEntity descriptionTemplateEntity = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(profileId); - return prefillingMapper.mapPrefilledEntityToDatasetWizard(prefillingEntity, prefillingGet, prefillingConfig.getType(), descriptionTemplateEntity, datasetManager/*, licenseManager*/); - } - - public DatasetWizardModel getPrefilledDatasetUsingData(Map data, String configId, UUID profileId) throws Exception { - PrefillingConfig prefillingConfig = this.externalUrlConfigProvider.getExternalUrls().getPrefillings().get(configId); - PrefillingGet prefillingGet = prefillingConfig.getPrefillingGet(); - DescriptionTemplateEntity descriptionTemplateEntity = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(profileId); - return prefillingMapper.mapPrefilledEntityToDatasetWizard(data, prefillingGet, prefillingConfig.getType(), descriptionTemplateEntity, datasetManager/*, licenseManager*/); - } - - private Map getSingle(String url, String id) { - RestTemplate restTemplate = new RestTemplate(); - String parsedUrl = url.replace("{id}", id); - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - HttpEntity entity = new HttpEntity("", headers); - - return restTemplate.exchange(parsedUrl, HttpMethod.GET, entity, LinkedHashMap.class).getBody(); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UnlinkEmailConfirmationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UnlinkEmailConfirmationManager.java deleted file mode 100644 index 281390c78..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UnlinkEmailConfirmationManager.java +++ /dev/null @@ -1,97 +0,0 @@ -package eu.eudat.logic.managers; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.data.old.EmailConfirmation; -import eu.eudat.data.UserEntity; -import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; -import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.logic.services.operations.DatabaseRepository; -import eu.eudat.model.UserContactInfo; -import eu.eudat.query.UserContactInfoQuery; -import eu.eudat.query.UserQuery; -import gr.cite.tools.data.query.Ordering; -import gr.cite.tools.data.query.QueryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import jakarta.transaction.Transactional; - -import javax.management.InvalidApplicationException; -import java.util.*; - -@Component -public class UnlinkEmailConfirmationManager { - - private static Logger logger = LoggerFactory.getLogger(UnlinkEmailConfirmationManager.class); - - private ApiContext apiContext; - private DatabaseRepository databaseRepository; - private final QueryFactory queryFactory; - private final UserScope userScope; - - @Autowired - public UnlinkEmailConfirmationManager(ApiContext apiContext, QueryFactory queryFactory, UserScope userScope) { - this.apiContext = apiContext; - this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); - this.queryFactory = queryFactory; - this.userScope = userScope; - } - - @Transactional - public void confirmEmail(String token) throws TokenExpiredException, HasConfirmedEmailException, InvalidApplicationException { - EmailConfirmation loginConfirmationEmail = apiContext.getOperationsContext() - .getDatabaseRepository().getLoginConfirmationEmailDao().asQueryable() - .where((builder, root) -> builder.equal(root.get("token"), UUID.fromString(token))).getSingle(); - - if (loginConfirmationEmail.getExpiresAt().compareTo(new Date()) < 0) - throw new TokenExpiredException("Token has expired."); - - if(loginConfirmationEmail.getIsConfirmed()) - throw new HasConfirmedEmailException("Email is already confirmed."); - -// UserInfo userAskingForUnlink = databaseRepository.getUserInfoDao().asQueryable() -// .where((builder, root) -> builder.equal(root.get("id"), loginConfirmationEmail.getUserId())).getSingle(); - - try { - Map map = new ObjectMapper().readValue(loginConfirmationEmail.getData(), new TypeReference>() {}); - String emailTobeUnlinked = (String) map.get("email"); - Integer provider = Integer.valueOf((String) map.get("provider")); - - unlinkUser(emailTobeUnlinked, provider); - - loginConfirmationEmail.setIsConfirmed(true); - databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail); - } - catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - - @Transactional - private void unlinkUser(String emailTobeUnlinked, Integer provider) throws InvalidApplicationException { -// UserCredentialEntity credential = databaseRepository.getCredentialDao().asQueryable() -// .where((builder, root) -> builder.and(builder.equal(root.get("email"), emailTobeUnlinked), builder.equal(root.get("provider"), provider))).getSingle(); -// if(credential != null) { -// databaseRepository.getCredentialDao().delete(credential); -// } - } - - public void sendUnlinkConfirmationEmail(String email, Integer provider) throws InvalidApplicationException { - UserEntity user = this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first(); - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - if (query.first().getValue() != null && !query.first().getValue().equals(email)) { - apiContext.getUtilitiesService().getConfirmationEmailService().sentUnlinkConfirmationEmail( - databaseRepository.getLoginConfirmationEmailDao(), - email, - user, - provider - ); - } - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java deleted file mode 100644 index 73cdf98a9..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java +++ /dev/null @@ -1,177 +0,0 @@ -package eu.eudat.logic.managers; - -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; -import eu.eudat.commons.types.xml.XmlBuilder; -import eu.eudat.data.DescriptionTemplateEntity; -import eu.eudat.data.UserCredentialEntity; -import eu.eudat.data.UserEntity; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.query.UserCredentialQuery; -import gr.cite.commons.web.authz.service.AuthorizationService; -import gr.cite.tools.data.query.QueryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.management.InvalidApplicationException; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -@Component -public class UserManager { - private static final Logger logger = LoggerFactory.getLogger(UserManager.class); - - private final ApiContext apiContext; - private final Environment environment; - private final UserScope userScope; - private final QueryFactory queryFactory; - private final AuthorizationService authorizationService; - - @Autowired - public UserManager(ApiContext apiContext, Environment environment, UserScope userScope, QueryFactory queryFactory, AuthorizationService authorizationService) { - this.apiContext = apiContext; - this.environment = environment; - this.userScope = userScope; - this.queryFactory = queryFactory; - this.authorizationService = authorizationService; - } - - public eu.eudat.models.data.user.composite.DatasetProfile generateDatasetProfileModel(DescriptionTemplateEntity profile) { - Document viewStyleDoc = XmlBuilder.fromXml(profile.getDefinition()); - Element root = (Element) viewStyleDoc.getDocumentElement(); - DefinitionEntity viewstyle = new DefinitionEntity().fromXml(root); - - eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = new eu.eudat.models.data.user.composite.DatasetProfile(); - datasetprofile.buildProfile(viewstyle); - - return datasetprofile; - } - -// public DataTableData getPaged(UserInfoTableRequestItem userInfoTableRequestItem) throws Exception { -// QueryableList users = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().getWithCriteria(userInfoTableRequestItem.getCriteria()).withHint(HintedModelFactory.getHint(UserListingModel.class)); -// QueryableList pagedUsers = PaginationManager.applyPaging(users, userInfoTableRequestItem); -// -// List modelUsers = pagedUsers.select(item -> new UserListingModel().fromDataModel(item)); -// return apiContext.getOperationsContext().getBuilderFactory().getBuilder(DataTableDataBuilder.class).totalCount(users.count()).data(modelUsers).build(); -// } - -// public List getCredentials(UUID userId) throws InvalidApplicationException { -// List results = new ArrayList<>(); -// UserEntity user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userId); -// List credentials = this.queryFactory.query(UserCredentialQuery.class).userIds(user.getId()).collect(); -// credentials.forEach(credential -> { -// UserCredential userCredential = new UserCredential(); -// results.add(userCredential); -// }); -// return results; -// } - -// public UserProfile getSingle(UUID userId) throws Exception { -// UserEntity user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userId); -// UserProfile profile = new UserProfile().fromDataModel(user); -// List roles = new LinkedList<>(); -// DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); -// criteria.setAllVersions(false); -// QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria); -// List dmps = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getAuthenticated(items, userId, roles).take(5).toList(); -// profile.setAssociatedDmps(dmps.stream().map(x -> new DataManagementPlan().fromDataModel(x)).collect(Collectors.toList())); -// return profile; -// } - -// public void editRoles(UserListingModel user) throws InvalidApplicationException { -// UserEntity userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(user.getId()); -// //userInfo.getUserRoles().stream().forEach(item -> apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().delete(item)); //TODO -// for (String role : user.getAppRoles()) { -// UserRoleEntity userRole = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserRoleBuilder.class).role(role).userInfo(userInfo).build(); -// apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().createOrUpdate(userRole); -// } -// } - -// public void updateSettings(Map settings) throws IOException, InvalidApplicationException { -// UserEntity userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(this.userScope.getUserId()); -// apiContext.getOperationsContext().getDatabaseRepository().detachEntity(userInfo); -// HashMap result = -// new ObjectMapper().readValue(userInfo.getAdditionalInfo(), HashMap.class); -// userInfo.setName(settings.entrySet().stream().filter(entry -> entry.getKey().equals("name")).filter(Objects::nonNull).map(entry -> entry.getValue().toString()).findFirst().orElse(userInfo.getName())); -// settings.remove("name"); -// result.putAll(settings); -// userInfo.setAdditionalInfo(new JSONObject(result).toString()); -// apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao() -// .createOrUpdate(userInfo); -// } -// -// public DataTableData getCollaboratorsPaged(UserInfoTableRequestItem userInfoTableRequestItem) throws Exception { -// UserInfoDao userInfoDao = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao(); -// QueryableList users = userInfoDao.getWithCriteria(userInfoTableRequestItem.getCriteria()); -// -// List colaborators = userInfoDao.getAuthenticated(users, this.userScope.getUserId()) -// .withHint(HintedModelFactory.getHint(UserListingModel.class)) -// .select(colaborator -> new UserListingModel().fromDataModel(colaborator)); -// -// DataTableData dataTableData = new DataTableData<>(); -// dataTableData.setData(colaborators); -// dataTableData.setTotalCount((long) colaborators.size()); -// return dataTableData; -// } -// -// public ResponseEntity exportToCsv() throws IOException, InvalidApplicationException { -// -// this.authorizationService.authorizeForce(Permission.AdminRole); -// -// List users = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().toList(); -// StringBuilder resultBuilder = new StringBuilder(); -// resultBuilder.append("User Id").append(",").append("User Name").append(",").append("User Email").append("\n"); -// users.stream().forEach(user -> resultBuilder.append(user.getId().toString()).append(",") -// .append(user.getName()).append(",") -////TODO .append(user.getEmail()).append("\n") -// ); -// String result = resultBuilder.toString(); -// String fileName = "Users_dump";//dmp.getLabel(); -// fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); -// String uuid = UUID.randomUUID().toString(); -// File file = new File(this.environment.getProperty("temp.temp") + uuid + ".csv"); -// OutputStream output = new FileOutputStream(file); -// try { -//// mapper.writeValue(file, rdaExportModel); -// output.write(result.getBytes()); -// output.flush(); -// output.close(); -// } catch (IOException e) { -// logger.error(e.getMessage(), e); -// } -// -// InputStream resource = new FileInputStream(file); -// HttpHeaders responseHeaders = new HttpHeaders(); -// responseHeaders.setContentLength(file.length()); -// responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); -// responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName + ".csv"); -// responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); -// responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); -// -// byte[] content = org.apache.poi.util.IOUtils.toByteArray(resource); -// resource.close(); -// Files.deleteIfExists(file.toPath()); -// return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); -// } -// -// public UserProfile getFromEmail(String email) throws InvalidApplicationException { -// UserEntity user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), email)).getSingle(); -// return new UserProfile().fromDataModel(user); -// } -// -// public Long countActiveUsers(){ //TODO: Authn -// return 0L; -// //return apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().asQueryable().where(((builder, root) -> builder.greaterThan(root.get("expiresAt"), new Date()))).count(); -// } -// -// public Long countAllUsers() throws InvalidApplicationException { -// return apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().count(); -// } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ValidationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ValidationManager.java index 6c5451b09..e96958ef7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ValidationManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ValidationManager.java @@ -5,26 +5,26 @@ import gr.cite.tools.exception.MyNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import eu.eudat.service.reference.external.criteria.ExternalReferenceCriteria; +import eu.eudat.service.remotefetcher.criteria.ExternalReferenceCriteria; import eu.eudat.commons.exceptions.HugeResultSetException; -import eu.eudat.service.reference.external.RemoteFetcher; +import eu.eudat.service.remotefetcher.RemoteFetcherService; @Component public class ValidationManager { - private RemoteFetcher remoteFetcher; + private RemoteFetcherService remoteFetcherService; private final UserScope userScope; @Autowired - public ValidationManager(RemoteFetcher remoteFetcher, UserScope userScope) { + public ValidationManager(RemoteFetcherService remoteFetcherService, UserScope userScope) { super(); - this.remoteFetcher = remoteFetcher; + this.remoteFetcherService = remoteFetcherService; this.userScope = userScope; } public Boolean validateIdentifier(String identifier, String type) throws MyNotFoundException, HugeResultSetException { ExternalReferenceCriteria externalReferenceCriteria = new ExternalReferenceCriteria(identifier); - Integer count = this.remoteFetcher.countEntries(externalReferenceCriteria, type); + Integer count = this.remoteFetcherService.countEntries(externalReferenceCriteria, type); return this.userScope.isSet() && count > 0; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/prefilling/PrefillingMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/prefilling/PrefillingMapper.java index 5d212ddbd..02c681ec3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/prefilling/PrefillingMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/prefilling/PrefillingMapper.java @@ -9,18 +9,16 @@ import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.TagEntity; import eu.eudat.logic.managers.DatasetManager; import eu.eudat.logic.managers.DatasetProfileManager; -import eu.eudat.service.reference.external.config.entities.DefaultPrefillingMapping; -import eu.eudat.service.reference.external.config.entities.PrefillingFixedMapping; -import eu.eudat.service.reference.external.config.entities.PrefillingGet; -import eu.eudat.service.reference.external.config.entities.PrefillingMapping; -import eu.eudat.commons.exceptions.HugeResultSetException; +import eu.eudat.service.remotefetcher.config.entities.DefaultPrefillingMapping; +import eu.eudat.service.remotefetcher.config.entities.PrefillingFixedMapping; +import eu.eudat.service.remotefetcher.config.entities.PrefillingGet; +import eu.eudat.service.remotefetcher.config.entities.PrefillingMapping; import eu.eudat.logic.utilities.helpers.StreamDistinctBy; import eu.eudat.logic.utilities.json.JsonSearcher; import eu.eudat.commons.types.descriptiontemplate.fielddata.AutoCompleteDataEntity; import eu.eudat.models.data.datasetprofile.DatasetProfileOverviewModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; -import eu.eudat.models.data.externaldataset.ExternalAutocompleteFieldModel; -import gr.cite.tools.exception.MyNotFoundException; +import eu.eudat.service.remotefetcher.models.ExternalAutocompleteFieldResult; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -232,17 +230,17 @@ public class PrefillingMapper { AutoCompleteDataEntity autoCompleteDataEntity = mapper.treeToValue(dataNode, AutoCompleteDataEntity.class); isMultiSelect = autoCompleteDataEntity.getMultiAutoComplete(); for (String format : parsedValues) { - List result = new ArrayList<>(); + List result = new ArrayList<>(); try { result = datasetProfileManager.getAutocomplete(autoCompleteDataEntity, format); } catch (Exception e) { logger.error(e.getMessage(), e); } - result = result.stream().filter(StreamDistinctBy.distinctByKey(ExternalAutocompleteFieldModel::getId)).collect(Collectors.toList()); + result = result.stream().filter(StreamDistinctBy.distinctByKey(ExternalAutocompleteFieldResult::getId)).collect(Collectors.toList()); if(!result.isEmpty()){ List tempValues = new LinkedList<>(); - for (ExternalAutocompleteFieldModel f : result) { + for (ExternalAutocompleteFieldResult f : result) { if (format.equals(f.getId()) || f.getLabel().toUpperCase(Locale.ROOT).contains(format.toUpperCase(Locale.ROOT))) tempValues.add(mapper.valueToTree(f).toString()); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java index 0ad4d9dc4..496d73f83 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java @@ -1,11 +1,8 @@ package eu.eudat.logic.proxy.config.configloaders; -import eu.eudat.service.descriptiontemplate.Semantic; import eu.eudat.models.data.pid.PidLinks; -import eu.eudat.service.reference.external.config.ExternalUrls; import org.apache.poi.xwpf.usermodel.XWPFDocument; -import java.util.List; import java.util.Map; public interface ConfigLoader { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java index 771c3f6f6..885db8bdb 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java @@ -3,7 +3,6 @@ package eu.eudat.logic.proxy.config.configloaders; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.models.data.pid.PidLinks; -import eu.eudat.service.reference.external.config.ExternalUrls; import eu.eudat.service.storage.StorageFileService; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.slf4j.Logger; @@ -15,8 +14,6 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContext.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContext.java index 44f3d0116..eae6fd695 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContext.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContext.java @@ -2,7 +2,6 @@ package eu.eudat.logic.services; import eu.eudat.logic.services.helpers.HelpersService; import eu.eudat.logic.services.operations.OperationsContext; -import eu.eudat.logic.services.utilities.UtilitiesService; public interface ApiContext { @@ -10,5 +9,4 @@ public interface ApiContext { OperationsContext getOperationsContext(); - UtilitiesService getUtilitiesService(); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContextImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContextImpl.java index 42920db8a..ec88e7ccb 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContextImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/ApiContextImpl.java @@ -2,7 +2,6 @@ package eu.eudat.logic.services; import eu.eudat.logic.services.helpers.HelpersService; import eu.eudat.logic.services.operations.OperationsContext; -import eu.eudat.logic.services.utilities.UtilitiesService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -12,13 +11,11 @@ public class ApiContextImpl implements ApiContext { private OperationsContext operationsContext; private HelpersService helpersService; - private UtilitiesService utilitiesService; @Autowired - public ApiContextImpl(OperationsContext operationsContext, HelpersService helpersService, UtilitiesService utilitiesService) { + public ApiContextImpl(OperationsContext operationsContext, HelpersService helpersService) { this.operationsContext = operationsContext; this.helpersService = helpersService; - this.utilitiesService = utilitiesService; } @Override @@ -31,8 +28,4 @@ public class ApiContextImpl implements ApiContext { return helpersService; } - @Override - public UtilitiesService getUtilitiesService() { - return utilitiesService; - } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/ExternalValidationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/ExternalValidationService.java index 083a10b05..e91ae4bfb 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/ExternalValidationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/ExternalValidationService.java @@ -1,9 +1,9 @@ package eu.eudat.logic.services; import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.service.reference.external.criteria.ExternalReferenceCriteria; +import eu.eudat.service.remotefetcher.criteria.ExternalReferenceCriteria; import eu.eudat.commons.exceptions.HugeResultSetException; -import eu.eudat.service.reference.external.RemoteFetcher; +import eu.eudat.service.remotefetcher.RemoteFetcherService; import gr.cite.tools.exception.MyNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -11,19 +11,19 @@ import org.springframework.stereotype.Service; @Service public class ExternalValidationService { - private RemoteFetcher remoteFetcher; + private RemoteFetcherService remoteFetcherService; private final UserScope userScope; @Autowired - public ExternalValidationService(RemoteFetcher remoteFetcher, UserScope userScope) { + public ExternalValidationService(RemoteFetcherService remoteFetcherService, UserScope userScope) { super(); - this.remoteFetcher = remoteFetcher; + this.remoteFetcherService = remoteFetcherService; this.userScope = userScope; } public Boolean validateIdentifier(String identifier, String type) throws MyNotFoundException, HugeResultSetException { ExternalReferenceCriteria externalReferenceCriteria = new ExternalReferenceCriteria(identifier); - Integer count = this.remoteFetcher.countEntries(externalReferenceCriteria, type); + Integer count = this.remoteFetcherService.countEntries(externalReferenceCriteria, type); return userScope.isSet() && count > 0; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index dc64509a5..a40b22b59 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -12,10 +12,6 @@ public interface DatabaseRepository { DMPDao getDmpDao(); - InvitationDao getInvitationDao(); - - - EmailConfirmationDao getLoginConfirmationEmailDao(); FileUploadDao getFileUploadDao(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index 491d70de5..01aa379cd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -15,11 +15,6 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { private DMPDao dmpDao; - private InvitationDao invitationDao; - - - private EmailConfirmationDao loginConfirmationEmailDao; - private FileUploadDao fileUploadDao; @@ -59,31 +54,11 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { } - @Override - public InvitationDao getInvitationDao() { - return invitationDao; - } - - @Autowired - public void setInvitationDao(InvitationDao invitationDao) { - this.invitationDao = invitationDao; - } - @Autowired public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; } - @Override - public EmailConfirmationDao getLoginConfirmationEmailDao() { - return loginConfirmationEmailDao; - } - - @Autowired - public void setLoginConfirmationEmailDao(EmailConfirmationDao loginConfirmationEmailDao) { - this.loginConfirmationEmailDao = loginConfirmationEmailDao; - } - @Override public FileUploadDao getFileUploadDao() { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContext.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContext.java index 265694ac0..f0ee1cbba 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContext.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContext.java @@ -1,7 +1,7 @@ package eu.eudat.logic.services.operations; import eu.eudat.logic.builders.BuilderFactory; -import eu.eudat.service.reference.external.RemoteFetcher; +import eu.eudat.service.remotefetcher.RemoteFetcherService; import org.springframework.context.ApplicationContext; /** @@ -15,7 +15,7 @@ public interface OperationsContext { BuilderFactory getBuilderFactory(); - RemoteFetcher getRemoteFetcher(); + RemoteFetcherService getRemoteFetcher(); // FileStorageService getFileStorageService(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContextImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContextImpl.java index dced680c0..4a0631ed2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContextImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/OperationsContextImpl.java @@ -1,7 +1,7 @@ package eu.eudat.logic.services.operations; import eu.eudat.logic.builders.BuilderFactory; -import eu.eudat.service.reference.external.RemoteFetcher; +import eu.eudat.service.remotefetcher.RemoteFetcherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; @@ -14,17 +14,17 @@ public class OperationsContextImpl implements OperationsContext { private final DatabaseRepository databaseRepository; private final ApplicationContext applicationContext; - private final RemoteFetcher remoteFetcher; + private final RemoteFetcherService remoteFetcherService; private final BuilderFactory builderFactory; // private final FileStorageService fileStorageService; // private final ElasticRepository elasticRepository; @Autowired - public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcher remoteFetcher + public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcherService remoteFetcherService , BuilderFactory builderFactory/*FileStorageService fileStorageService, ElasticRepository elasticRepository*/) { this.databaseRepository = databaseRepository; this.applicationContext = applicationContext; - this.remoteFetcher = remoteFetcher; + this.remoteFetcherService = remoteFetcherService; this.builderFactory = builderFactory; // this.fileStorageService = fileStorageService; // this.elasticRepository = elasticRepository; @@ -41,8 +41,8 @@ public class OperationsContextImpl implements OperationsContext { } @Override - public RemoteFetcher getRemoteFetcher() { - return remoteFetcher; + public RemoteFetcherService getRemoteFetcher() { + return remoteFetcherService; } @Override diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java deleted file mode 100644 index 0ee9e097c..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java +++ /dev/null @@ -1,15 +0,0 @@ -package eu.eudat.logic.services.utilities; - -import eu.eudat.data.dao.entities.EmailConfirmationDao; -import eu.eudat.data.UserEntity; - -import javax.management.InvalidApplicationException; - - -public interface ConfirmationEmailService { - public void sentConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user) throws InvalidApplicationException; - - public void sentUnlinkConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user, Integer provider) throws InvalidApplicationException; - - public void sentMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user, Integer provider) throws InvalidApplicationException; -} \ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java deleted file mode 100644 index 3242ad3aa..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java +++ /dev/null @@ -1,159 +0,0 @@ -package eu.eudat.logic.services.utilities; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import eu.eudat.commons.JsonHandlingService; -import eu.eudat.commons.enums.ContactInfoType; -import eu.eudat.commons.enums.notification.NotificationContactType; -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.commons.types.notification.*; -import eu.eudat.configurations.notification.NotificationProperties; -import eu.eudat.data.dao.entities.EmailConfirmationDao; -import eu.eudat.data.old.EmailConfirmation; -import eu.eudat.data.UserEntity; -import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEvent; -import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler; -import eu.eudat.model.UserContactInfo; -import eu.eudat.query.UserContactInfoQuery; -import gr.cite.tools.data.query.Ordering; -import gr.cite.tools.data.query.QueryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.management.InvalidApplicationException; -import java.util.*; - -@Service("ConfirmationEmailService") -public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { - private static final Logger logger = LoggerFactory.getLogger(ConfirmationEmailServiceImpl.class); - //private Logger logger; - private final UserScope userScope; - private final QueryFactory queryFactory; - private final JsonHandlingService jsonHandlingService; - private final NotificationIntegrationEventHandler eventHandler; - private final NotificationProperties notificationProperties; - - - public ConfirmationEmailServiceImpl(/*Logger logger,*/ UserScope userScope, QueryFactory queryFactory, JsonHandlingService jsonHandlingService, NotificationIntegrationEventHandler eventHandler, NotificationProperties notificationProperties) { -// this.logger = logger; - this.userScope = userScope; - this.queryFactory = queryFactory; - this.jsonHandlingService = jsonHandlingService; - this.eventHandler = eventHandler; - this.notificationProperties = notificationProperties; - } - - @Override - public void sentConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user) throws InvalidApplicationException { - - EmailConfirmation confirmationEmail = new EmailConfirmation(); - confirmationEmail.setEmail(email); - confirmationEmail.setExpiresAt(Date - .from(new Date() - .toInstant() - .plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()) - ) - ); - confirmationEmail.setUserId(user.getId()); - confirmationEmail.setIsConfirmed(false); - confirmationEmail.setToken(UUID.randomUUID()); - confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail); - } - - @Override - public void sentUnlinkConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, String email, UserEntity user, Integer provider) throws InvalidApplicationException { - EmailConfirmation confirmationEmail = new EmailConfirmation(); - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - confirmationEmail.setEmail(query.first().getValue()); - confirmationEmail.setExpiresAt(Date - .from(new Date() - .toInstant() - .plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()) - ) - ); - confirmationEmail.setUserId(user.getId()); - try { - Map map = new HashMap<>(); - map.put("email", email); - map.put("provider", provider.toString()); - confirmationEmail.setData(new ObjectMapper().writeValueAsString(map)); - } catch (JsonProcessingException e) { - logger.error(e.getMessage(), e); - } - confirmationEmail.setIsConfirmed(false); - confirmationEmail.setToken(UUID.randomUUID()); - confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail); - - NotificationIntegrationEvent event = new NotificationIntegrationEvent(); - event.setUserId(userScope.getUserIdSafe()); - List contactPairs = new ArrayList<>(); - contactPairs.add(new ContactPair(ContactInfoType.Email, email)); - NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); - event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(NotificationContactType.EMAIL); - event.setNotificationType(notificationProperties.getRemoveCredentialConfirmationType()); - NotificationFieldData data = new NotificationFieldData(); - List fieldInfoList = new ArrayList<>(); - fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString())); - fieldInfoList.add(new FieldInfo("{email}", DataType.String, email)); - fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds()))); - data.setFields(fieldInfoList); - event.setData(jsonHandlingService.toJsonSafe(data)); - eventHandler.handle(event); - } - - @Override - public void sentMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, - String email, UserEntity user, Integer provider) throws InvalidApplicationException { - EmailConfirmation confirmationEmail = new EmailConfirmation(); - confirmationEmail.setEmail(email); - confirmationEmail.setExpiresAt(Date - .from(new Date() - .toInstant() - .plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()) - ) - ); - confirmationEmail.setUserId(user.getId()); - try { - Map map = new HashMap<>(); - map.put("userId", this.userScope.getUserId()); - map.put("provider", provider.toString()); - confirmationEmail.setData(new ObjectMapper().writeValueAsString(map)); - } catch (JsonProcessingException | InvalidApplicationException e) { - logger.error(e.getMessage(), e); - } - confirmationEmail.setIsConfirmed(false); - confirmationEmail.setToken(UUID.randomUUID()); - confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail); - - NotificationIntegrationEvent event = new NotificationIntegrationEvent(); - event.setUserId(userScope.getUserIdSafe()); - List contactPairs = new ArrayList<>(); - contactPairs.add(new ContactPair(ContactInfoType.Email, email)); - NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); - event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(NotificationContactType.EMAIL); - event.setNotificationType(notificationProperties.getMergeAccountConfirmationType()); - NotificationFieldData data = new NotificationFieldData(); - List fieldInfoList = new ArrayList<>(); - fieldInfoList.add(new FieldInfo("{userName}", DataType.String, user.getName())); - fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString())); - fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds()))); - data.setFields(fieldInfoList); - event.setData(jsonHandlingService.toJsonSafe(data)); - eventHandler.handle(event); - - } - - private String secondsToTime(int seconds) { - int sec = seconds % 60; - int hour = seconds / 60; - int min = hour % 60; - hour = hour / 60; - return (hour + ":" + min + ":" + sec); - } - - -} \ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java deleted file mode 100644 index b7f891888..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java +++ /dev/null @@ -1,26 +0,0 @@ -package eu.eudat.logic.services.utilities; - - -import eu.eudat.data.DmpEntity; -import eu.eudat.data.DmpUserEntity; -import eu.eudat.data.dao.entities.DMPDao; -import eu.eudat.data.dao.entities.InvitationDao; -import eu.eudat.data.old.Invitation; - -import eu.eudat.data.UserEntity; -import jakarta.mail.MessagingException; - -import javax.management.InvalidApplicationException; -import java.util.List; -import java.util.concurrent.CompletableFuture; - - -public interface InvitationService { - void assignToDmp(DMPDao dmpDao, List users, DmpEntity dmp); - - void assignToDmp(DMPDao dmpDao, DmpUserEntity user, DmpEntity dmp); - - void createInvitations(InvitationDao invitationDao, List users, DmpEntity dmp, Integer role, UserEntity creator) throws MessagingException, InvalidApplicationException; - - void sendInvitation(DmpEntity dmp, Invitation invitation, UserEntity user, Integer role) throws InvalidApplicationException; -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java deleted file mode 100644 index 4243a6e86..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -package eu.eudat.logic.services.utilities; - - -import eu.eudat.commons.JsonHandlingService; -import eu.eudat.commons.enums.ContactInfoType; -import eu.eudat.commons.enums.DmpUserRole; -import eu.eudat.commons.enums.notification.NotificationContactType; -import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.commons.types.notification.*; -import eu.eudat.configurations.notification.NotificationProperties; -import eu.eudat.data.DmpEntity; -import eu.eudat.data.DmpUserEntity; -import eu.eudat.data.dao.entities.DMPDao; -import eu.eudat.data.dao.entities.InvitationDao; -import eu.eudat.data.old.Invitation; -import eu.eudat.data.UserEntity; -import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEvent; -import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler; -import eu.eudat.model.UserContactInfo; -import eu.eudat.models.data.invitation.Properties; -import eu.eudat.query.UserContactInfoQuery; -import gr.cite.tools.data.query.Ordering; -import gr.cite.tools.data.query.QueryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; - -import jakarta.mail.MessagingException; -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.Marshaller; - -import javax.management.InvalidApplicationException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - - -@Service("invitationService") -public class InvitationServiceImpl implements InvitationService { - private static final Logger logger = LoggerFactory.getLogger(InvitationServiceImpl.class); - private Environment environment; - private final UserScope userScope; - private final NotificationIntegrationEventHandler eventHandler; - private final JsonHandlingService jsonHandlingService; - private final NotificationProperties notificationProperties; - - @Autowired - public InvitationServiceImpl(Environment environment, UserScope userScope, NotificationIntegrationEventHandler eventHandler, JsonHandlingService jsonHandlingService, NotificationProperties notificationProperties, QueryFactory queryFactory) { - this.environment = environment; - this.userScope = userScope; - this.eventHandler = eventHandler; - this.jsonHandlingService = jsonHandlingService; - this.notificationProperties = notificationProperties; - this.queryFactory = queryFactory; - } - private final QueryFactory queryFactory; - - @Override - public void assignToDmp(DMPDao dmpDao, List users, DmpEntity dmp) { -// for (DmpUserEntity user : users) { -// dmp.getUsers().add(user); -// } //TODO - dmpDao.createOrUpdate(dmp); - } - - @Override - public void assignToDmp(DMPDao dmpDao, DmpUserEntity user, DmpEntity dmp) { -// if (!dmp.getUsers().stream().map(x -> x.getUser().getId()).collect(Collectors.toList()).contains(user.getId())) { -// dmp.getUsers().add(user); -// dmpDao.createOrUpdate(dmp); -// } //TODO - } - - @Override - public void createInvitations(InvitationDao invitationDao, List users, DmpEntity dmp, Integer role, UserEntity creator) throws MessagingException, InvalidApplicationException { - for (UserEntity user : users) { - Invitation invitation = new Invitation(); -// invitation.setDmp(dmp); //TODO - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - invitation.setInvitationEmail(query.first().getValue()); - invitation.setUser(creator); - invitation.setToken(UUID.randomUUID()); - invitation.setAcceptedInvitation(false); - Properties properties = new Properties(); - properties.setRole(role); - try { - JAXBContext context = JAXBContext.newInstance(Properties.class); - Marshaller marshaller = context.createMarshaller(); - StringWriter propertyWriter = new StringWriter(); - marshaller.marshal(properties, propertyWriter); - invitation.setProperties(propertyWriter.toString()); - }catch (Exception e) { - logger.error(e.getMessage(), e); - } - invitationDao.createOrUpdate(invitation); - this.sendInvitation(dmp, invitation, user, role); - } - } - - @Override - public void sendInvitation(DmpEntity dmp, Invitation invitation, UserEntity user, Integer role) throws InvalidApplicationException { - - NotificationIntegrationEvent event = new NotificationIntegrationEvent(); - event.setUserId(user.getId()); - - UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); - query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); - - List contactPairs = new ArrayList<>(); - contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); - NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); - event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(NotificationContactType.EMAIL); - event.setNotificationType(notificationProperties.getDmpInvitationExternalUserType()); - NotificationFieldData data = new NotificationFieldData(); - List fieldInfoList = new ArrayList<>(); - fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName())); - fieldInfoList.add(new FieldInfo("{invitationID}", DataType.String, invitation.getId().toString())); - fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel())); - fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, DmpUserRole.of(role.shortValue()).toString())); - data.setFields(fieldInfoList); - event.setData(jsonHandlingService.toJsonSafe(data)); - eventHandler.handle(event); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/UtilitiesService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/UtilitiesService.java deleted file mode 100644 index 917284f58..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/UtilitiesService.java +++ /dev/null @@ -1,14 +0,0 @@ -package eu.eudat.logic.services.utilities; - -import eu.eudat.logic.services.forms.VisibilityRuleService; -//import eu.eudat.service.mail.MailService; - -/** - * Created by ikalyvas on 3/1/2018. - */ -public interface UtilitiesService { - - InvitationService getInvitationService(); - - ConfirmationEmailService getConfirmationEmailService(); -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/UtilitiesServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/UtilitiesServiceImpl.java deleted file mode 100644 index d4aa24119..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/UtilitiesServiceImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package eu.eudat.logic.services.utilities; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * Created by ikalyvas on 3/1/2018. - */ -@Service("utilitiesService") -public class UtilitiesServiceImpl implements UtilitiesService { - - private InvitationService invitationService; - private ConfirmationEmailService confirmationEmailService; - - @Autowired - public UtilitiesServiceImpl(InvitationService invitationService, ConfirmationEmailService confirmationEmailService) { - this.invitationService = invitationService; - this.confirmationEmailService = confirmationEmailService; - } - - @Override - public ConfirmationEmailService getConfirmationEmailService() { - return confirmationEmailService; - } - - @Override - public InvitationService getInvitationService() { - return invitationService; - } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java index 2b92d3aa1..290713485 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java @@ -940,7 +940,7 @@ public class WordBuilder { case RADIO_BOX: return field.getValue() != null ? field.getValue().toString() : null; case CHECK_BOX: - CheckBoxDataEntity data = (CheckBoxDataEntity) field.getData(); + LabelDataEntity data = (LabelDataEntity) field.getData(); if (field.getValue() == null || field.getValue().equals("false")) return null; return data.getLabel(); case DATE_PICKER:{ diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java index 6e7cd26bc..e88f1a531 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java @@ -261,7 +261,7 @@ public class ExportXmlBuilderDatasetProfile { dataOut.appendChild(types); break; case BOOLEAN_DECISION: - BooleanDecisionDataEntity booleanDecisionDataEntityObject = (BooleanDecisionDataEntity) field.getData(); + LabelAndMultiplicityDataEntity booleanDecisionDataEntityObject = (LabelAndMultiplicityDataEntity) field.getData(); dataOut.setAttribute("label", booleanDecisionDataEntityObject.getLabel()); break; case RADIO_BOX: @@ -294,15 +294,15 @@ public class ExportXmlBuilderDatasetProfile { dataOut.setAttribute("type", internalDmpEntitiesData.getFieldType().getValue()); switch (internalDmpEntitiesData.getFieldSubType()) { case Researchers: - ResearcherAutoCompleteDataEntity researchersAutoCompleteData = (ResearcherAutoCompleteDataEntity) internalDmpEntitiesData; + InternalDmpBaseDataEntity researchersAutoCompleteData = (InternalDmpBaseDataEntity) internalDmpEntitiesData; dataOut.setAttribute("multiAutocomplete", researchersAutoCompleteData.getMultiAutoComplete().toString()); break; case Datasets: - DatasetAutoCompleteDataEntity datasetAutoCompleteDataEntity = (DatasetAutoCompleteDataEntity) internalDmpEntitiesData; + InternalDmpBaseDataEntity datasetAutoCompleteDataEntity = (InternalDmpBaseDataEntity) internalDmpEntitiesData; dataOut.setAttribute("multiAutocomplete", datasetAutoCompleteDataEntity.getMultiAutoComplete().toString()); break; case Dmps: - DmpAutoCompleteDataEntity dmpAutoCompleteDataEntity = (DmpAutoCompleteDataEntity) internalDmpEntitiesData; + InternalDmpBaseDataEntity dmpAutoCompleteDataEntity = (InternalDmpBaseDataEntity) internalDmpEntitiesData; dataOut.setAttribute("multiAutocomplete", dmpAutoCompleteDataEntity.getMultiAutoComplete().toString()); break; } @@ -316,42 +316,42 @@ public class ExportXmlBuilderDatasetProfile { case DATA_REPOSITORIES: case JOURNAL_REPOSITORIES: case PUB_REPOSITORIES: - DataRepositoryDataEntity dataRepositoryDataEntity = (DataRepositoryDataEntity) field.getData(); + InternalDmpBaseDataEntity dataRepositoryDataEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", dataRepositoryDataEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", dataRepositoryDataEntity.getMultiAutoComplete().toString()); break; case TAXONOMIES: - TaxonomyDataEntity taxonomyDataEntity = (TaxonomyDataEntity) field.getData(); + InternalDmpBaseDataEntity taxonomyDataEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", taxonomyDataEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", taxonomyDataEntity.getMultiAutoComplete().toString()); break; case LICENSES: - LicenseDataEntity licensesData = (LicenseDataEntity) field.getData(); + InternalDmpBaseDataEntity licensesData = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", licensesData.getLabel()); dataOut.setAttribute("multiAutocomplete", licensesData.getMultiAutoComplete().toString()); break; case PUBLICATIONS: - PublicationDataEntity publicationDataEntity = (PublicationDataEntity) field.getData(); + InternalDmpBaseDataEntity publicationDataEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", publicationDataEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", publicationDataEntity.getMultiAutoComplete().toString()); break; case ORGANIZATIONS: - OrganizationDataEntity organizationDataEntity = (OrganizationDataEntity) field.getData(); + InternalDmpBaseDataEntity organizationDataEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", organizationDataEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", organizationDataEntity.getMultiAutoComplete().toString()); break; case RESEARCHERS: - ResearcherDataEntity researcherDataEntity = (ResearcherDataEntity) field.getData(); + InternalDmpBaseDataEntity researcherDataEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", researcherDataEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", researcherDataEntity.getMultiAutoComplete().toString()); break; case REGISTRIES: - RegistryDataEntity registriesEntity = (RegistryDataEntity) field.getData(); + InternalDmpBaseDataEntity registriesEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", registriesEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", registriesEntity.getMultiAutoComplete().toString()); break; case SERVICES: - ServiceDataEntity serviceDataEntity = (ServiceDataEntity) field.getData(); + InternalDmpBaseDataEntity serviceDataEntity = (InternalDmpBaseDataEntity) field.getData(); dataOut.setAttribute("label", serviceDataEntity.getLabel()); dataOut.setAttribute("multiAutocomplete", serviceDataEntity.getMultiAutoComplete().toString()); break; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/schedule/notification/NotificationScheduleJob.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/schedule/notification/NotificationScheduleJob.java deleted file mode 100644 index bd3ce64be..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/schedule/notification/NotificationScheduleJob.java +++ /dev/null @@ -1,49 +0,0 @@ -package eu.eudat.logic.utilities.schedule.notification; - -import eu.eudat.logic.managers.NotificationManager; -import eu.eudat.logic.services.ApiContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - - -@Component -public class NotificationScheduleJob { - private static final Logger logger = LoggerFactory.getLogger(NotificationScheduleJob.class); - - private ApiContext apiContext; - private NotificationManager notificationManager; - - @Autowired - public NotificationScheduleJob(ApiContext apiContext, NotificationManager notificationManager) { - this.apiContext = apiContext; - this.notificationManager = notificationManager; - } - -// @Transactional //TODO -// @Scheduled(fixedRateString = "${notification.rateInterval}") -// public void sendNotifications() throws InvalidApplicationException { -// List> futures = new LinkedList<>(); -// this.apiContext.getOperationsContext().getDatabaseRepository().getNotificationDao().asQueryable().where(((builder, root) -> -// builder.and( -// builder.or( -// builder.equal(root.get("notifyState"), NotifyState.PENDING), builder.equal(root.get("notifyState"), NotifyState.ERROR)) -// , builder.equal(root.get("isActive"), ActiveStatus.ACTIVE)))).toListAsync().thenApplyAsync((notifications) -> { -// if (!notifications.isEmpty()) { -// notifications.forEach(notification -> { -// try { -// this.notificationManager.sendNotification(notification); -// } catch (Exception e) { -// logger.error(e.getMessage(), e); -// } -// }); -// } -// return notifications; -// }).thenApplyAsync((notifications) -> { -// notifications.forEach((notification) -> futures.add(this.apiContext.getOperationsContext().getDatabaseRepository().getNotificationDao().createOrUpdateAsync(notification))); -// return futures; -// }).join(); -// -// } -} diff --git a/dmp-backend/web/src/main/resources/config/application.yml b/dmp-backend/web/src/main/resources/config/application.yml index 49dc175ed..dc7b597ee 100644 --- a/dmp-backend/web/src/main/resources/config/application.yml +++ b/dmp-backend/web/src/main/resources/config/application.yml @@ -28,5 +28,6 @@ spring: optional:classpath:config/tenant.yml[.yml], optional:classpath:config/tenant-${spring.profiles.active}.yml[.yml], optional:file:../config/tenant-${spring.profiles.active}.yml[.yml], optional:classpath:config/queue.yml[.yml], optional:classpath:config/queue-${spring.profiles.active}.yml[.yml], optional:file:../config/queue-${spring.profiles.active}.yml[.yml], optional:classpath:config/notification.yml[.yml], optional:classpath:config/notification-${spring.profiles.active}.yml[.yml], optional:file:../config/notification-${spring.profiles.active}.yml[.yml], + optional:classpath:config/locale.yml[.yml], optional:classpath:config/locale-${spring.profiles.active}.yml[.yml], optional:file:../config/locale-${spring.profiles.active}.yml[.yml], optional:classpath:config/transformer.yml[.yml], optional:classpath:config/transformer-${spring.profiles.active}.yml[.yml], optional:file:../config/transformer-${spring.profiles.active}.yml[.yml] diff --git a/dmp-backend/web/src/main/resources/config/db.yml b/dmp-backend/web/src/main/resources/config/db.yml index 95fe82271..5f68f3510 100644 --- a/dmp-backend/web/src/main/resources/config/db.yml +++ b/dmp-backend/web/src/main/resources/config/db.yml @@ -8,6 +8,7 @@ spring: jpa: properties: hibernate: + globally_quoted_identifiers: true ddl-auto: validate dialect: org.hibernate.dialect.PostgreSQLDialect hibernate: diff --git a/dmp-backend/web/src/main/resources/config/idpclaims.yml b/dmp-backend/web/src/main/resources/config/idpclaims.yml index 3372e4ca7..97ff4a10e 100644 --- a/dmp-backend/web/src/main/resources/config/idpclaims.yml +++ b/dmp-backend/web/src/main/resources/config/idpclaims.yml @@ -37,3 +37,5 @@ idpclient: - type: azp Authorities: - type: authorities + ExternalProviderName: + - type: identity_provider \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/config/locale.yml b/dmp-backend/web/src/main/resources/config/locale.yml new file mode 100644 index 000000000..bc862307f --- /dev/null +++ b/dmp-backend/web/src/main/resources/config/locale.yml @@ -0,0 +1,4 @@ +locale: + timezone: UTC + language: en + culture: en-001 diff --git a/dmp-backend/web/src/main/resources/config/permissions.yml b/dmp-backend/web/src/main/resources/config/permissions.yml index 3d12b8c86..00bb8f25e 100644 --- a/dmp-backend/web/src/main/resources/config/permissions.yml +++ b/dmp-backend/web/src/main/resources/config/permissions.yml @@ -457,6 +457,7 @@ permissions: BrowseReference: roles: - Admin + - User clients: [ ] allowAnonymous: false allowAuthenticated: false @@ -669,6 +670,17 @@ permissions: clients: [ ] allowAnonymous: false allowAuthenticated: false + # Prefilling + BrowsePrefilling: + roles: + - Admin + - DescriptionTemplateEditor + - Manager + - User + claims: [ ] + clients: [ ] + allowAnonymous: false + allowAuthenticated: false # Lock Permissions BrowseLock: @@ -700,19 +712,19 @@ permissions: # ActionConfirmation Permissions BrowseActionConfirmation: roles: - - User + - Admin clients: [ ] allowAnonymous: false allowAuthenticated: false EditActionConfirmation: roles: - - User + - Admin clients: [ ] allowAnonymous: false allowAuthenticated: false DeleteActionConfirmation: roles: - - User + - Admin claims: [ ] clients: [ ] allowAnonymous: false diff --git a/dmp-backend/web/src/main/resources/config/queue-devel.yml b/dmp-backend/web/src/main/resources/config/queue-devel.yml index a5a7d9992..be18ee0e5 100644 --- a/dmp-backend/web/src/main/resources/config/queue-devel.yml +++ b/dmp-backend/web/src/main/resources/config/queue-devel.yml @@ -1,5 +1,6 @@ queue: rabbitmq: + enable: true durable: true queue: cite_dmp_devel_web_inbox_queue exchange: cite_dmp_devel_queue diff --git a/dmp-backend/web/src/main/resources/config/queue.yml b/dmp-backend/web/src/main/resources/config/queue.yml index 0f04da973..a9abcd96f 100644 --- a/dmp-backend/web/src/main/resources/config/queue.yml +++ b/dmp-backend/web/src/main/resources/config/queue.yml @@ -8,7 +8,7 @@ spring: enabled: false queue: rabbitmq: - enable: true + enable: false app-id: ${THE_API_ID} durable: null queue: null diff --git a/dmp-backend/web/src/main/resources/config/storage-devel.yml b/dmp-backend/web/src/main/resources/config/storage-devel.yml index cee91a319..76e2c374a 100644 --- a/dmp-backend/web/src/main/resources/config/storage-devel.yml +++ b/dmp-backend/web/src/main/resources/config/storage-devel.yml @@ -7,7 +7,7 @@ storage: - type: Main basePath: ./storage/main static-files: - externalUrls: externalUrls/ExternalUrls.xml + externalUrls: dmp-backend/web/src/main/resources/externalUrls/ExternalUrls.xml semantics: Semantics.json h2020Template: documents/h2020.docx h2020DescriptionTemplate: documents/h2020_dataset.docx diff --git a/dmp-db-scema/updates/00.01.018_addUserCredentialTable.sql b/dmp-db-scema/updates/00.01.018_addUserCredentialTable.sql index c7cb1d2d5..529b0d36e 100644 --- a/dmp-db-scema/updates/00.01.018_addUserCredentialTable.sql +++ b/dmp-db-scema/updates/00.01.018_addUserCredentialTable.sql @@ -8,6 +8,7 @@ BEGIN ( id uuid NOT NULL, "user" uuid NOT NULL, + "data" character varying NULL, external_id character varying(512) NOT NULL, created_at timestamp without time zone NOT NULL, PRIMARY KEY (id), diff --git a/dmp-frontend/src/app/app-routing.module.ts b/dmp-frontend/src/app/app-routing.module.ts index 797d49a70..f5385cbfa 100644 --- a/dmp-frontend/src/app/app-routing.module.ts +++ b/dmp-frontend/src/app/app-routing.module.ts @@ -270,6 +270,18 @@ const appRoutes: Routes = [ }) }, }, + { + path: 'notifications', + loadChildren: () => import('./ui/admin/notification/notification.module').then(m => m.NotificationModule), + data: { + authContext: { + permissions: [AppPermission.ViewNotificationPage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.NOTIFICATIONS' + }) + }, + }, { path: 'notification-templates', loadChildren: () => import('./ui/admin/notification-template/notification-template.module').then(m => m.NotificationTemplateModule), @@ -282,6 +294,18 @@ const appRoutes: Routes = [ }) }, }, + { + path: 'mine-notifications', + loadChildren: () => import('./ui/inapp-notification/mine-inapp-notification.module').then(m => m.MineInAppNotificationModule), + data: { + authContext: { + permissions: [AppPermission.ViewMineInAppNotificationPage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.INAPP-NOTIFICATIONS' + }) + }, + }, { path: 'index-managment', loadChildren: () => import('./ui/admin/index-managment/index-managment.module').then(m => m.IndexManagmentModule), diff --git a/dmp-frontend/src/app/core/common/enum/description-template-version-status.ts b/dmp-frontend/src/app/core/common/enum/description-template-version-status.ts new file mode 100644 index 000000000..130e01b1e --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/description-template-version-status.ts @@ -0,0 +1,4 @@ +export enum DescriptionTemplateVersionStatus { + Current = 0, + Previous = 1 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/notification-contact-type.ts b/dmp-frontend/src/app/core/common/enum/notification-contact-type.ts new file mode 100644 index 000000000..a0d2bd316 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/notification-contact-type.ts @@ -0,0 +1,4 @@ +export enum NotificationContactType { + EMAIL = 0, + IN_APP = 3, +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/notification-inapp-tracking.enum.ts b/dmp-frontend/src/app/core/common/enum/notification-inapp-tracking.enum.ts new file mode 100644 index 000000000..92422833e --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/notification-inapp-tracking.enum.ts @@ -0,0 +1,4 @@ +export enum NotificationInAppTracking { + Stored = 0, + Delivered = 1 +} diff --git a/dmp-frontend/src/app/core/common/enum/notification-notify-state.ts b/dmp-frontend/src/app/core/common/enum/notification-notify-state.ts new file mode 100644 index 000000000..c93c24e73 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/notification-notify-state.ts @@ -0,0 +1,7 @@ +export enum NotificationNotifyState { + PENDING = 0, + PROCESSING = 1, + SUCCESSFUL = 2, + ERROR = 3, + OMITTED = 4 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/notification-tracking-process.ts b/dmp-frontend/src/app/core/common/enum/notification-tracking-process.ts new file mode 100644 index 000000000..9cb3e30f3 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/notification-tracking-process.ts @@ -0,0 +1,7 @@ +export enum NotificationTrackingProcess { + PENDING = 0, + PROCESSING = 1, + SUCCESSFUL = 2, + ERROR = 3, + OMITTED = 4 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/notification-tracking-state.ts b/dmp-frontend/src/app/core/common/enum/notification-tracking-state.ts new file mode 100644 index 000000000..99b7fca9d --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/notification-tracking-state.ts @@ -0,0 +1,10 @@ +export enum NotificationTrackingState { + UNDEFINED = 0, + NA = 1, + QUEUED = 2, + SENT = 3, + DELIVERED = 4, + UNDELIVERED = 5, + FAILED = 6, + UNSENT = 7 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/permission.enum.ts b/dmp-frontend/src/app/core/common/enum/permission.enum.ts index 205ec77ca..0077e5859 100644 --- a/dmp-frontend/src/app/core/common/enum/permission.enum.ts +++ b/dmp-frontend/src/app/core/common/enum/permission.enum.ts @@ -34,6 +34,8 @@ export enum AppPermission { ViewTenantPage = 'ViewTenantPage', ViewLanguagePage = "ViewLanguagePage", ViewNotificationTemplatePage = "ViewNotificationTemplatePage", + ViewMineInAppNotificationPage = "ViewMineInAppNotificationPage", + ViewNotificationPage = "ViewNotificationPage", //ReferenceType BrowseReferenceType = "BrowseReferenceType", diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts index ae5601e81..4bf56873c 100644 --- a/dmp-frontend/src/app/core/core-service.module.ts +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -44,6 +44,8 @@ import { UserService } from './services/user/user.service'; import { FileUtils } from './services/utilities/file-utils.service'; import { QueryParamsService } from './services/utilities/query-params.service'; import { FileTransformerHttpService } from './services/file-transformer/file-transformer.http.service'; +import { InAppNotificationService } from './services/inapp-notification/inapp-notification.service'; +import { NotificationService } from './services/notification/notification-service'; // // // This is shared module that provides all the services. Its imported only once on the AppModule. @@ -106,7 +108,9 @@ export class CoreServiceModule { TagService, CanDeactivateGuard, FileTransformerService, - FileTransformerHttpService + FileTransformerHttpService, + InAppNotificationService, + NotificationService ], }; } diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-reference.ts b/dmp-frontend/src/app/core/model/dmp/dmp-reference.ts index df308ce03..d2a2f6491 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp-reference.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp-reference.ts @@ -1,9 +1,14 @@ import { BaseEntity } from "@common/base/base-entity.model"; import { Reference } from "../reference/reference"; import { Dmp } from "./dmp"; +import { Guid } from "@common/types/guid"; export interface DmpReference extends BaseEntity { dmp?: Dmp; reference?: Reference; - data: string; + data: DmpReferenceData; +} + +export interface DmpReferenceData { + blueprintFieldId: Guid; } \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dmp/dmp.ts b/dmp-frontend/src/app/core/model/dmp/dmp.ts index aa6452d44..710d9ba08 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp.ts @@ -17,7 +17,7 @@ export interface Dmp extends BaseEntity { version: number; status: DmpStatus; versionStatus: DmpVersionStatus; - properties: string; + properties: DmpProperties; groupId: String; description: String; finalizedAt: Date; @@ -34,6 +34,24 @@ export interface Dmp extends BaseEntity { entityDois: EntityDoi[]; } +export interface DmpProperties { + dmpBlueprintValues: DmpBlueprintValue[]; + contacts: DmpContact[]; +} + +export interface DmpBlueprintValue { + fieldId: Guid; + fieldValue: string; +} + +export interface DmpContact { + userId: Guid; + firstName: string; + lastName: string; + email: string; +} + + export interface DmpUser extends BaseEntity { dmp: Dmp; user: User; @@ -54,18 +72,39 @@ export interface DmpDescriptionTemplate extends BaseEntity { export interface DmpPersist extends BaseEntityPersist { label: string; status: DmpStatus; - properties: string; + properties: DmpPropertiesPersist; description: String; language: String; blueprint: Guid; accessType: DmpAccessType; - references: DmpReferencePersist[]; descriptionTemplates: DmpDescriptionTemplatePersist[]; } -export interface DmpReferencePersist extends BaseEntityPersist { +export interface DmpPropertiesPersist { + dmpBlueprintValues: DmpBlueprintValuePersist[]; + contacts: DmpContactPersist[]; +} + +export interface DmpBlueprintValuePersist { + fieldId: Guid; + fieldValue: string; + references: DmpReferencePersist[]; +} + +export interface DmpContactPersist { + userId: Guid; + firstName: string; + lastName: string; + email: string; +} + +export interface DmpReferencePersist { reference?: ReferencePersist; - data?: string; + data?: DmpReferenceDataPersist; +} + +export interface DmpReferenceDataPersist { + blueprintFieldId: Guid; } export interface DmpDescriptionTemplatePersist extends BaseEntityPersist { diff --git a/dmp-frontend/src/app/core/model/inapp-notification/inapp-notification.model.ts b/dmp-frontend/src/app/core/model/inapp-notification/inapp-notification.model.ts new file mode 100644 index 000000000..b0a3a5bb2 --- /dev/null +++ b/dmp-frontend/src/app/core/model/inapp-notification/inapp-notification.model.ts @@ -0,0 +1,17 @@ +import { Guid } from '@common/types/guid'; +import { User } from '../user/user'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum'; + +export interface InAppNotification { + id: Guid; + user: User; + isActive: IsActive; + type: Guid; + trackingState: NotificationInAppTracking; + subject: string; + body: string; + createdAt: Date; + updatedAt: Date; + hash: string; +} diff --git a/dmp-frontend/src/app/core/model/notification-template/notification-template.ts b/dmp-frontend/src/app/core/model/notification-template/notification-template.ts index e728b2bc4..5351cc7a7 100644 --- a/dmp-frontend/src/app/core/model/notification-template/notification-template.ts +++ b/dmp-frontend/src/app/core/model/notification-template/notification-template.ts @@ -5,10 +5,11 @@ import { Guid } from "@common/types/guid"; import { Language } from "../language/language"; import { NotificationDataType } from "@app/core/common/enum/notification-data-type"; import { EmailOverrideMode } from "@app/core/common/enum/email-override-mode"; +import { NotificationType } from "@app/core/common/enum/notification-type"; export interface NotificationTemplate extends BaseEntity{ channel: NotificationTemplateChannel; - notificationType: Guid; + notificationType: NotificationType; kind: NotificationTemplateKind; language: Language; value: NotificationTemplateValue; @@ -46,6 +47,7 @@ export interface NotificationFieldInfo { export interface NotificationTemplatePersist extends BaseEntityPersist{ channel: NotificationTemplateChannel; + notificationType: NotificationType; kind: NotificationTemplateKind; languageId: Guid; value: NotificationTemplateValuePersist; diff --git a/dmp-frontend/src/app/core/model/notification/notification.model.ts b/dmp-frontend/src/app/core/model/notification/notification.model.ts new file mode 100644 index 000000000..39088df68 --- /dev/null +++ b/dmp-frontend/src/app/core/model/notification/notification.model.ts @@ -0,0 +1,22 @@ +import { NotificationContactType } from '@app/core/common/enum/notification-contact-type'; +import { User } from '../user/user'; +import { NotificationType } from '@app/core/common/enum/notification-type'; +import { BaseEntity } from '@common/base/base-entity.model'; +import { NotificationNotifyState } from '@app/core/common/enum/notification-notify-state'; +import { NotificationTrackingProcess } from '@app/core/common/enum/notification-tracking-process'; +import { NotificationTrackingState } from '@app/core/common/enum/notification-tracking-state'; + +export interface Notification extends BaseEntity{ + user: User; + type: NotificationType; + contactTypeHint: NotificationContactType; + contactHint: string; + data: string; + notifyState: NotificationNotifyState; + notifiedWith: NotificationContactType; + notifiedAt: Date; + retryCount: number; + trackingState: NotificationTrackingState; + trackingProcess: NotificationTrackingProcess; + trackingData: string; +} diff --git a/dmp-frontend/src/app/core/query/description-template.lookup.ts b/dmp-frontend/src/app/core/query/description-template.lookup.ts index 1e7f2b836..b2ef3e146 100644 --- a/dmp-frontend/src/app/core/query/description-template.lookup.ts +++ b/dmp-frontend/src/app/core/query/description-template.lookup.ts @@ -2,6 +2,7 @@ import { Lookup } from '@common/model/lookup'; import { Guid } from '@common/types/guid'; import { DescriptionTemplateStatus } from '../common/enum/description-template-status'; import { IsActive } from '../common/enum/is-active.enum'; +import { DescriptionTemplateVersionStatus } from '../common/enum/description-template-version-status'; export class DescriptionTemplateLookup extends Lookup implements DescriptionTemplateFilter { ids: Guid[]; @@ -10,6 +11,8 @@ export class DescriptionTemplateLookup extends Lookup implements DescriptionTemp isActive: IsActive[]; typeIds: Guid[]; statuses: DescriptionTemplateStatus[]; + groupIds: Guid[]; + versionStatuses: DescriptionTemplateVersionStatus[]; constructor() { super(); @@ -23,4 +26,6 @@ export interface DescriptionTemplateFilter { isActive: IsActive[]; typeIds: Guid[]; statuses: DescriptionTemplateStatus[]; + groupIds: Guid[]; + versionStatuses: DescriptionTemplateVersionStatus[]; } diff --git a/dmp-frontend/src/app/core/query/inapp-notification.lookup.ts b/dmp-frontend/src/app/core/query/inapp-notification.lookup.ts new file mode 100644 index 000000000..e4ae69cfe --- /dev/null +++ b/dmp-frontend/src/app/core/query/inapp-notification.lookup.ts @@ -0,0 +1,22 @@ +import { Lookup } from '@common/model/lookup'; +import { NotificationType } from '../common/enum/notification-type'; +import { NotificationInAppTracking } from '../common/enum/notification-inapp-tracking.enum'; +import { IsActive } from '../common/enum/is-active.enum'; + +export class InAppNotificationLookup extends Lookup implements InAppNotificationFilter { + like: string; + isActive: IsActive[]; + type: NotificationType[]; + trackingState: NotificationInAppTracking[]; + + constructor() { + super(); + } +} + +export interface InAppNotificationFilter { + like: string; + isActive: IsActive[]; + trackingState: NotificationInAppTracking[]; + type: NotificationType[]; +} diff --git a/dmp-frontend/src/app/core/query/notification-template.lookup.ts b/dmp-frontend/src/app/core/query/notification-template.lookup.ts index 6d24e6be8..7fdaa95ce 100644 --- a/dmp-frontend/src/app/core/query/notification-template.lookup.ts +++ b/dmp-frontend/src/app/core/query/notification-template.lookup.ts @@ -3,6 +3,7 @@ import { Guid } from "@common/types/guid"; import { IsActive } from "../common/enum/is-active.enum"; import { NotificationTemplateKind } from "../common/enum/notification-template-kind"; import { NotificationTemplateChannel } from "../common/enum/notification-template-channel"; +import { NotificationType } from "../common/enum/notification-type"; export class NotificationTemplateLookup extends Lookup implements NotificationTemplateFilter { ids: Guid[]; @@ -10,6 +11,7 @@ export class NotificationTemplateLookup extends Lookup implements NotificationTe isActive: IsActive[]; kinds: NotificationTemplateKind[]; channels: NotificationTemplateChannel[]; + notificationTypes: NotificationType[]; constructor() { super(); @@ -22,4 +24,5 @@ export interface NotificationTemplateFilter { isActive: IsActive[]; kinds: NotificationTemplateKind[]; channels: NotificationTemplateChannel[]; + notificationTypes: NotificationType[]; } \ No newline at end of file diff --git a/dmp-frontend/src/app/core/query/notification.lookup.ts b/dmp-frontend/src/app/core/query/notification.lookup.ts new file mode 100644 index 000000000..3ac6f12cc --- /dev/null +++ b/dmp-frontend/src/app/core/query/notification.lookup.ts @@ -0,0 +1,38 @@ +import { Lookup } from "@common/model/lookup"; +import { Guid } from "@common/types/guid"; +import { IsActive } from "../common/enum/is-active.enum"; +import { NotificationType } from "../common/enum/notification-type"; +import { NotificationNotifyState } from "../common/enum/notification-notify-state"; +import { NotificationContactType } from "../common/enum/notification-contact-type"; +import { NotificationTrackingState } from "../common/enum/notification-tracking-state"; +import { NotificationTrackingProcess } from "../common/enum/notification-tracking-process"; + +export class NotificationLookup extends Lookup implements NotificationFilter { + ids: Guid[]; + excludedIds: Guid[]; + isActive: IsActive[]; + type: NotificationType[]; + notifyState: NotificationNotifyState[]; + notifiedWith: NotificationContactType[]; + contactType: NotificationContactType[]; + trackingState: NotificationTrackingState[]; + trackingProcess: NotificationTrackingProcess[]; + userIds: Guid[]; + + constructor() { + super(); + } +} + +export interface NotificationFilter { + ids: Guid[]; + excludedIds: Guid[]; + isActive: IsActive[]; + type: NotificationType[]; + notifyState: NotificationNotifyState[]; + notifiedWith: NotificationContactType[]; + contactType: NotificationContactType[]; + trackingState: NotificationTrackingState[]; + trackingProcess: NotificationTrackingProcess[]; + userIds: Guid[]; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/auth/auth.service.ts b/dmp-frontend/src/app/core/services/auth/auth.service.ts index 72eaee247..be4e7ebfc 100644 --- a/dmp-frontend/src/app/core/services/auth/auth.service.ts +++ b/dmp-frontend/src/app/core/services/auth/auth.service.ts @@ -143,7 +143,7 @@ export class AuthService extends BaseService { this.accessToken ? this.principalService.me(httpParams) : of(null) ])), map((item) => { - this.currentAccount(item[0]?.payload); + this.currentAccount(item[0]); return true; }) ); diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index 02cb670fb..b9ebaae25 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -118,6 +118,11 @@ export class ConfigurationService extends BaseComponent { return this._notificationServiceEnabled; } + private _inAppNotificationsCountInterval: number; + get inAppNotificationsCountInterval(): number { + return this._inAppNotificationsCountInterval || 3200; + } + public loadConfiguration(): Promise { return new Promise((r, e) => { // We need to exclude all interceptors here, for the initial configuration request. @@ -178,6 +183,7 @@ export class ConfigurationService extends BaseComponent { this._notificationServiceEnabled = config.notification_service.enabled; this._notificationServiceAddress = config.notification_service.address; } + this._inAppNotificationsCountInterval = config.inAppNotificationsCountInterval; } } diff --git a/dmp-frontend/src/app/core/services/description-template/description-template.service.ts b/dmp-frontend/src/app/core/services/description-template/description-template.service.ts index e4cda2701..cf8d41c8c 100644 --- a/dmp-frontend/src/app/core/services/description-template/description-template.service.ts +++ b/dmp-frontend/src/app/core/services/description-template/description-template.service.ts @@ -16,6 +16,8 @@ import { catchError, map } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; import { ConfigurationService } from '../configuration/configuration.service'; import { BaseHttpV2Service } from '../http/base-http-v2.service'; +import { DescriptionTemplateVersionStatus } from '@app/core/common/enum/description-template-version-status'; +import { DescriptionTemplateStatus } from '@app/core/common/enum/description-template-status'; @Injectable() export class DescriptionTemplateService { @@ -126,4 +128,46 @@ export class DescriptionTemplateService { if (like) { lookup.like = this.filterService.transformLike(like); } return lookup; } + + // + // Description Tempalte Group Autocomplete Commons + // + // tslint:disable-next-line: member-ordering + descriptionTempalteGroupSingleAutocompleteConfiguration: SingleAutoCompleteConfiguration = { + initialItems: (data?: any) => this.query(this.buildDescriptionTempalteGroupAutocompleteLookup()).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.query(this.buildDescriptionTempalteGroupAutocompleteLookup(searchQuery)).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.query(this.buildDescriptionTempalteGroupAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), + displayFn: (item: DescriptionTemplate) => item.label, + titleFn: (item: DescriptionTemplate) => item.label, + valueAssign: (item: DescriptionTemplate) => item.groupId, + }; + + // tslint:disable-next-line: member-ordering + descriptionTempalteGroupMultipleAutocompleteConfiguration: MultipleAutoCompleteConfiguration = { + initialItems: (excludedItems: any[], data?: any) => this.query(this.buildDescriptionTempalteGroupAutocompleteLookup(null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), + filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildDescriptionTempalteGroupAutocompleteLookup(searchQuery, excludedItems)).pipe(map(x => x.items)), + getSelectedItems: (selectedItems: any[]) => this.query(this.buildDescriptionTempalteGroupAutocompleteLookup(null, null, selectedItems)).pipe(map(x => x.items)), + displayFn: (item: DescriptionTemplate) => item.label, + titleFn: (item: DescriptionTemplate) => item.label, + valueAssign: (item: DescriptionTemplate) => item.groupId, + }; + + public buildDescriptionTempalteGroupAutocompleteLookup(like?: string, excludedIds?: Guid[], groupIds?: Guid[]): DescriptionTemplateLookup { + const lookup: DescriptionTemplateLookup = new DescriptionTemplateLookup(); + lookup.page = { size: 100, offset: 0 }; + if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } + if (groupIds && groupIds.length > 0) { lookup.groupIds = groupIds; } + lookup.isActive = [IsActive.Active]; + lookup.versionStatuses = [DescriptionTemplateVersionStatus.Current]; + lookup.statuses = [DescriptionTemplateStatus.Finalized]; + lookup.project = { + fields: [ + nameof(x => x.id), + nameof(x => x.label) + ] + }; + lookup.order = { items: [nameof(x => x.label)] }; + if (like) { lookup.like = this.filterService.transformLike(like); } + return lookup; + } } diff --git a/dmp-frontend/src/app/core/services/description/description.service.ts b/dmp-frontend/src/app/core/services/description/description.service.ts index e27e95092..8b352b54a 100644 --- a/dmp-frontend/src/app/core/services/description/description.service.ts +++ b/dmp-frontend/src/app/core/services/description/description.service.ts @@ -46,9 +46,6 @@ export class DescriptionService { const options: HttpParamsOptions = { fromObject: { f: reqFields } }; let params: BaseHttpParams = new BaseHttpParams(options); - params.interceptorContext = { - excludedInterceptors: [InterceptorType.AuthToken] - }; return this.http .get(url, { params: params }).pipe( @@ -57,10 +54,16 @@ export class DescriptionService { getPublicSingle(id: Guid, reqFields: string[] = []): Observable { const url = `${this.apiBase}/public/${id}`; - const options = { params: { f: reqFields } }; + const options: HttpParamsOptions = { fromObject: { f: reqFields } }; + + let params: BaseHttpParams = new BaseHttpParams(options); + params.interceptorContext = { + excludedInterceptors: [InterceptorType.AuthToken] + }; + return this.http - .get(url, options).pipe( + .get(url, { params: params }).pipe( catchError((error: any) => throwError(error))); } diff --git a/dmp-frontend/src/app/core/services/http/principal.service.ts b/dmp-frontend/src/app/core/services/http/principal.service.ts index 50b9cc5b5..a33ac37f8 100644 --- a/dmp-frontend/src/app/core/services/http/principal.service.ts +++ b/dmp-frontend/src/app/core/services/http/principal.service.ts @@ -2,7 +2,8 @@ import { Injectable } from '@angular/core'; import { AppAccount } from '@app/core/model/auth/principal'; import { Observable } from 'rxjs'; import { ConfigurationService } from '../configuration/configuration.service'; -import { BaseHttpV2Service } from './base-http-v2.service'; +import { BaseHttpV2Service } from '../http/base-http-v2.service'; +import { map } from 'rxjs/operators'; @Injectable() export class PrincipalService { diff --git a/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts b/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts new file mode 100644 index 000000000..b336696bb --- /dev/null +++ b/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts @@ -0,0 +1,74 @@ +import { Injectable } from '@angular/core'; +import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model'; +import { InAppNotificationLookup } from '@app/core/query/inapp-notification.lookup'; +import { BaseHttpParams } from '@common/http/base-http-params'; +import { InterceptorType } from '@common/http/interceptors/interceptor-type'; +import { QueryResult } from '@common/model/query-result'; +import { Guid } from '@common/types/guid'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { BaseHttpV2Service } from '../http/base-http-v2.service'; +import { ConfigurationService } from '../configuration/configuration.service'; + +@Injectable() +export class InAppNotificationService { + + constructor(private http: BaseHttpV2Service, private configurationService: ConfigurationService) { + } + + private get apiBase(): string { return `${this.configurationService.notificationServiceAddress}inapp-notification`; } + + + query(q: InAppNotificationLookup): Observable> { + const url = `${this.apiBase}/query`; + + return this.http + .post>(url, q).pipe( + catchError((error: any) => throwError(error))); + } + + getSingle(id: Guid, reqFields: string[] = []): Observable { + const url = `${this.apiBase}/${id}`; + const options = { params: { f: reqFields } }; + + return this.http + .get(url, options).pipe( + catchError((error: any) => throwError(error))); + } + + read(id: Guid): Observable { + const url = `${this.apiBase}/${id}/read`; + + return this.http + .post(url, {}).pipe( + catchError((error: any) => throwError(error))); + } + + countUnread(): Observable { + const url = `${this.apiBase}/count-unread`; + const params = new BaseHttpParams(); + params.interceptorContext = { + excludedInterceptors: [InterceptorType.ProgressIndication] + }; + const options = { params: params }; + + return this.http + .get(url, options).pipe( + catchError((error: any) => throwError(error))); + } + + readAll(): Observable { + const url = `${this.apiBase}/read-all`; + + return this.http + .post(url, {}).pipe( + catchError((error: any) => throwError(error))); + } + + delete(id: Guid): Observable { + const url = `${this.apiBase}/${id}`; + return this.http + .delete(url).pipe( + catchError((error: any) => throwError(error))); + } +} diff --git a/dmp-frontend/src/app/core/services/notification/notification-service.ts b/dmp-frontend/src/app/core/services/notification/notification-service.ts new file mode 100644 index 000000000..af3aa747b --- /dev/null +++ b/dmp-frontend/src/app/core/services/notification/notification-service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import { QueryResult } from '@common/model/query-result'; +import { Guid } from '@common/types/guid'; +import { NotificationLookup } from '@app/core/query/notification.lookup'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { Notification } from '@app/core/model/notification/notification.model'; +import { BaseHttpV2Service } from '../http/base-http-v2.service'; +import { ConfigurationService } from '../configuration/configuration.service'; + +@Injectable() +export class NotificationService { + + constructor(private http: BaseHttpV2Service, private configurationService: ConfigurationService) { + } + + private get apiBase(): string { return `${this.configurationService.notificationServiceAddress}notification`; } + + query(q: NotificationLookup): Observable> { + const url = `${this.apiBase}/query`; + + return this.http + .post>(url, q).pipe( + catchError((error: any) => throwError(error))); + } + + delete(id: Guid): Observable { + const url = `${this.apiBase}/${id}`; + + return this.http + .delete(url).pipe( + catchError((error: any) => throwError(error))); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/reference/reference.service.ts b/dmp-frontend/src/app/core/services/reference/reference.service.ts index 16ba3f344..49e5480ea 100644 --- a/dmp-frontend/src/app/core/services/reference/reference.service.ts +++ b/dmp-frontend/src/app/core/services/reference/reference.service.ts @@ -3,7 +3,7 @@ import { IsActive } from '@app/core/common/enum/is-active.enum'; import { ReferenceSourceType } from '@app/core/common/enum/reference-source-type'; import { ReferenceType } from '@app/core/common/enum/reference-type'; import { DmpReference } from '@app/core/model/dmp/dmp-reference'; -import { Reference, ReferencePersist } from '@app/core/model/reference/reference'; +import { Definition, Field, Reference, ReferencePersist } from '@app/core/model/reference/reference'; import { ReferenceSearchDefinitionLookup, ReferenceSearchLookup } from '@app/core/query/reference-search.lookup'; import { ReferenceLookup } from '@app/core/query/reference.lookup'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; @@ -70,31 +70,31 @@ export class ReferenceService { } // - // Autocomplete Commons + // Autocomplete Commons - Query // - public getSingleAutocompleteConfiguration(types?: ReferenceType[], sourceTypes?: ReferenceSourceType[]): SingleAutoCompleteConfiguration { + public getSingleAutocompleteQueryConfiguration(types?: ReferenceType[], sourceTypes?: ReferenceSourceType[]): SingleAutoCompleteConfiguration { return { - initialItems: (data?: any) => this.query(this.buildAutocompleteLookup(types, sourceTypes)).pipe(map(x => x.items)), - filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteLookup(types, sourceTypes, searchQuery)).pipe(map(x => x.items)), - getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteLookup(types, sourceTypes, null, null, [selectedItem])).pipe(map(x => x.items[0])), + initialItems: (data?: any) => this.query(this.buildAutocompleteQueryLookup(types, sourceTypes)).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteQueryLookup(types, sourceTypes, searchQuery)).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteQueryLookup(types, sourceTypes, null, null, [selectedItem])).pipe(map(x => x.items[0])), displayFn: (item: Reference) => item.label, titleFn: (item: Reference) => item.label, valueAssign: (item: Reference) => item.id, }; }; - public getMultipleAutoCompleteConfiguration(types?: ReferenceType[], sourceTypes?: ReferenceSourceType[]): MultipleAutoCompleteConfiguration { + public getMultipleAutoCompleteQueryConfiguration(types?: ReferenceType[], sourceTypes?: ReferenceSourceType[]): MultipleAutoCompleteConfiguration { return { - initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup(types, sourceTypes, null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), - filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup(types, sourceTypes, searchQuery, excludedItems)).pipe(map(x => x.items)), - getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup(types, sourceTypes, null, null, selectedItems)).pipe(map(x => x.items)), + initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteQueryLookup(types, sourceTypes, null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), + filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteQueryLookup(types, sourceTypes, searchQuery, excludedItems)).pipe(map(x => x.items)), + getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteQueryLookup(types, sourceTypes, null, null, selectedItems)).pipe(map(x => x.items)), displayFn: (item: Reference) => item.label, titleFn: (item: Reference) => item.label, valueAssign: (item: Reference) => item.id, }; } - private buildAutocompleteLookup(types?: ReferenceType[], sourceTypes?: ReferenceSourceType[], like?: string, excludedIds?: Guid[], ids?: Guid[]): ReferenceLookup { + private buildAutocompleteQueryLookup(types?: ReferenceType[], sourceTypes?: ReferenceSourceType[], like?: string, excludedIds?: Guid[], ids?: Guid[]): ReferenceLookup { const lookup: ReferenceLookup = new ReferenceLookup(); lookup.page = { size: 100, offset: 0 }; if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } @@ -113,6 +113,56 @@ export class ReferenceService { return lookup; } + // + // Autocomplete Commons - Search + // + public getSingleAutocompleteSearchConfiguration(type: ReferenceType): SingleAutoCompleteConfiguration { + return { + initialItems: (data?: any) => this.search(this.buildAutocompleteSearchLookup(type)).pipe(map(x => x)), + filterFn: (searchQuery: string, data?: any) => this.search(this.buildAutocompleteSearchLookup(type, searchQuery)).pipe(map(x => x)), + getSelectedItem: (selectedItem: any) => this.search(this.buildAutocompleteSearchLookup(type)).pipe(map(x => x[0])), + displayFn: (item: Reference) => item.label, + titleFn: (item: Reference) => item.label, + valueAssign: (item: Reference) => item.id, + }; + }; + + public getMultipleAutoCompleteSearchConfiguration(type: ReferenceType): MultipleAutoCompleteConfiguration { + return { + initialItems: (excludedItems: any[], data?: any) => this.search(this.buildAutocompleteSearchLookup(type, null)).pipe(map(x => x)), + filterFn: (searchQuery: string, excludedItems: any[]) => this.search(this.buildAutocompleteSearchLookup(type, searchQuery)).pipe(map(x => x)), + getSelectedItems: (selectedItems: any[]) => this.search(this.buildAutocompleteSearchLookup(type, null)).pipe(map(x => x)), + displayFn: (item: Reference) => item.label, + titleFn: (item: Reference) => item.label, + valueAssign: (item: Reference) => item, + }; + } + + private buildAutocompleteSearchLookup(type: ReferenceType, like?: string): ReferenceSearchLookup { + const lookup: ReferenceSearchLookup = new ReferenceSearchLookup(); + lookup.page = { size: 100, offset: 0 }; + lookup.project = { + fields: [ + nameof(x => x.id), + nameof(x => x.label), + nameof(x => x.type), + nameof(x => x.description), + [nameof(x => x.definition), nameof(x => x.fields), nameof(x => x.code)].join('.'), + [nameof(x => x.definition), nameof(x => x.fields), nameof(x => x.dataType)].join('.'), + [nameof(x => x.definition), nameof(x => x.fields), nameof(x => x.value)].join('.'), + nameof(x => x.reference), + nameof(x => x.abbreviation), + nameof(x => x.source), + nameof(x => x.sourceType), + ] + }; + lookup.type = type; + lookup.order = { items: [nameof(x => x.label)] }; + if (like) { lookup.like = this.filterService.transformLike(like); } + return lookup; + } + + // // // UI Helpers diff --git a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts index ad1835599..c403def60 100644 --- a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts +++ b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts @@ -27,6 +27,12 @@ import { DmpStatus } from '../../common/enum/dmp-status'; import { ValidationType } from '../../common/enum/validation-type'; import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; import { NotificationType } from '@app/core/common/enum/notification-type'; +import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum'; +import { NotificationContactType } from '@app/core/common/enum/notification-contact-type'; +import { NotificationNotifyState } from '@app/core/common/enum/notification-notify-state'; +import { NotificationTrackingState } from '@app/core/common/enum/notification-tracking-state'; +import { NotificationTrackingProcess } from '@app/core/common/enum/notification-tracking-process'; +import { DmpAccessType } from '@app/core/common/enum/dmp-access-type'; @Injectable() export class EnumUtils { @@ -334,4 +340,59 @@ export class EnumUtils { case NotificationType.publicContactSupportType: return this.language.instant('TYPES.NOTIFICATION-TEMPLATE-NOTIFICATION-TYPE.PUBLIC-CONTACT-SUPPORT'); } } + + public toNotificationInAppTrackingString(value: NotificationInAppTracking): string { + switch (value) { + case NotificationInAppTracking.Delivered: return this.language.instant('TYPES.NOTIFICATION-INAPP-TRACKING.DELIVERED'); + case NotificationInAppTracking.Stored: return this.language.instant('TYPES.NOTIFICATION-INAPP-TRACKING.STORED'); + } + } + + public toNotificationContactTypeString(value: NotificationContactType): string { + switch (value) { + case NotificationContactType.EMAIL: return this.language.instant('TYPES.NOTIFICATION-CONTACT-TYPE.EMAIL'); + case NotificationContactType.IN_APP: return this.language.instant('TYPES.NOTIFICATION-CONTACT-TYPE.INAPP'); + } + } + + public toNotificationNotifyStateString(value: NotificationNotifyState): string { + switch (value) { + case NotificationNotifyState.PENDING: return this.language.instant('TYPES.NOTIFICATION-NOTIFY-STATE.PENDING'); + case NotificationNotifyState.PROCESSING: return this.language.instant('TYPES.NOTIFICATION-NOTIFY-STATE.PROCESSING'); + case NotificationNotifyState.SUCCESSFUL: return this.language.instant('TYPES.NOTIFICATION-NOTIFY-STATE.SUCCESSFUL'); + case NotificationNotifyState.ERROR: return this.language.instant('TYPES.NOTIFICATION-NOTIFY-STATE.ERROR'); + case NotificationNotifyState.OMITTED: return this.language.instant('TYPES.NOTIFICATION-NOTIFY-STATE.OMITTED'); + } + } + + public toNotificationTrackingStateString(value: NotificationTrackingState): string { + switch (value) { + case NotificationTrackingState.UNDEFINED: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.UNDEFINED'); + case NotificationTrackingState.NA: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.NA'); + case NotificationTrackingState.QUEUED: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.QUEUED'); + case NotificationTrackingState.SENT: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.SENT'); + case NotificationTrackingState.DELIVERED: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.DELIVERED'); + case NotificationTrackingState.UNDELIVERED: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.UNDELIVERED'); + case NotificationTrackingState.FAILED: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.FAILED'); + case NotificationTrackingState.UNSENT: return this.language.instant('TYPES.NOTIFICATION-TRACKING-STATE.UNSENT'); + } + } + + public toNotificationTrackingProcessString(value: NotificationTrackingProcess): string { + switch (value) { + case NotificationTrackingProcess.PENDING: return this.language.instant('TYPES.NOTIFICATION-TRACKING-PROCESS.PENDING'); + case NotificationTrackingProcess.PROCESSING: return this.language.instant('TYPES.NOTIFICATION-TRACKING-PROCESS.PROCESSING'); + case NotificationTrackingProcess.SUCCESSFUL: return this.language.instant('TYPES.NOTIFICATION-TRACKING-PROCESS.SUCCESSFUL'); + case NotificationTrackingProcess.ERROR: return this.language.instant('TYPES.NOTIFICATION-TRACKING-PROCESS.ERROR'); + case NotificationTrackingProcess.OMITTED: return this.language.instant('TYPES.NOTIFICATION-TRACKING-PROCESS.OMITTED'); + } + } + + public toDmpAccessTypeString(value: DmpAccessType): string { + switch (value) { + case DmpAccessType.Public: return this.language.instant('TYPES.DMP-ACCESS-TYPE.PUBLIC'); + case DmpAccessType.Restricted: return this.language.instant('TYPES.DMP-ACCESS-TYPE.RESTRICTED'); + } + } + } diff --git a/dmp-frontend/src/app/ui/admin/description-types/editor/description-template-type-editor.model.ts b/dmp-frontend/src/app/ui/admin/description-types/editor/description-template-type-editor.model.ts index 6f280477b..6b47ba8fc 100644 --- a/dmp-frontend/src/app/ui/admin/description-types/editor/description-template-type-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/description-types/editor/description-template-type-editor.model.ts @@ -44,7 +44,7 @@ export class DescriptionTemplateTypeEditorModel extends BaseEditorModel implemen const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); - baseValidationArray.push({ key: 'name', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'RenameourceId')] }); + baseValidationArray.push({ key: 'name', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'name')] }); baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); baseValidationArray.push({ key: 'hash', validators: [] }); diff --git a/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/dmp-blueprint-listing.component.html b/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/dmp-blueprint-listing.component.html index 447ae70fb..bdbd7d444 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/dmp-blueprint-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/dmp-blueprint-listing.component.html @@ -16,7 +16,7 @@
- diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html index d63d0769c..3bc5faa99 100644 --- a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html @@ -33,8 +33,8 @@ {{'LANGUAGE-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -45,24 +45,24 @@ {{languageCode}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'LANGUAGE-EDITOR.FIELDS.ORDINAL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('ordinal').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'LANGUAGE-EDITOR.FIELDS.PAYLOAD' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('payload').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{'LANGUAGE-EDITOR.FIELDS.OVERRIDE' | translate}} diff --git a/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html index 55be97c8b..94d9f035b 100644 --- a/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html @@ -39,9 +39,9 @@
- + {{item?.name | nullifyValue}} + (click)="$event.stopPropagation()">{{item?.code | nullifyValue}}
diff --git a/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.html b/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.html index ab3cb0e4f..89783a75d 100644 --- a/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.html @@ -33,7 +33,7 @@
{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.NOTIFICATION-TYPE' | translate}} - + {{enumUtils.toNotificationTypeString(type)}} @@ -326,7 +326,7 @@
{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.CC' | translate}} - + @@ -355,61 +355,60 @@ {{'GENERAL.VALIDATION.REQUIRED' | translate}}
-
- -
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.BCC-MODE' | translate}} - - - {{enumUtils.toEmailOverrideModeString(emailOverrideMode)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - -
- - +
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.BCC' | translate}} + + + {{field}} + + + + + +
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.BCC-MODE' | translate}} + + + {{enumUtils.toEmailOverrideModeString(emailOverrideMode)}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.EXTRA-DATA-KEYS' | translate}} + + + {{field}} + + + + + +
+
diff --git a/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.ts b/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.ts index 51daaad43..cca4177d3 100644 --- a/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/notification-template/editor/notification-template-editor.component.ts @@ -124,7 +124,6 @@ export class NotificationTemplateEditorComponent extends BaseEditor
-

{{'NOTIFICATION-TEMPLATE-LISTING.FILTER.TITLE' | translate}}

+

{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.TITLE' | translate}}

- {{'NOTIFICATION-TEMPLATE-LISTING.FILTER.IS-ACTIVE' | translate}} + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.IS-ACTIVE' | translate}}
- {{'NOTIFICATION-TEMPLATE-LISTING.FILTER.KIND' | translate}} + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.NOTIFICATION-TYPE' | translate}} + + {{enumUtils.toNotificationTypeString(type)}} + + +
+ +
+ {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.KIND' | translate}} {{enumUtils.toNotificationTemplateKindString(kind)}} @@ -29,7 +37,7 @@
- {{'NOTIFICATION-TEMPLATE-LISTING.FILTER.CHANNEL' | translate}} + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.CHANNEL' | translate}} {{enumUtils.toNotificationTemplateChannelString(channel)}} @@ -38,10 +46,10 @@
diff --git a/dmp-frontend/src/app/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.ts b/dmp-frontend/src/app/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.ts index eff5f21a1..e18f4a269 100644 --- a/dmp-frontend/src/app/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.ts +++ b/dmp-frontend/src/app/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.ts @@ -2,6 +2,7 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChange import { IsActive } from '@app/core/common/enum/is-active.enum'; import { NotificationTemplateChannel } from '@app/core/common/enum/notification-template-channel'; import { NotificationTemplateKind } from '@app/core/common/enum/notification-template-kind'; +import { NotificationType } from '@app/core/common/enum/notification-type'; import { NotificationTemplateFilter } from '@app/core/query/notification-template.lookup'; import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; import { BaseComponent } from '@common/base/base.component'; @@ -18,6 +19,7 @@ export class NotificationTemplateListingFiltersComponent extends BaseComponent i @Output() filterChange = new EventEmitter(); notificationTemplateKindEnumValues = this.enumUtils.getEnumValues(NotificationTemplateKind) notificationTemplateChannelEnumValues = this.enumUtils.getEnumValues(NotificationTemplateChannel); + notificationTypeEnumValues = this.enumUtils.getEnumValues(NotificationType); // * State internalFilters: NotificationTemplateListingFilters = this._getEmptyFilters(); @@ -49,13 +51,14 @@ export class NotificationTemplateListingFiltersComponent extends BaseComponent i } protected applyFilters(): void { - const { isActive, kinds, channels } = this.internalFilters ?? {} + const { isActive, kinds, channels, notificationTypes } = this.internalFilters ?? {} this.filterChange.emit({ ...this.filter, // like, isActive: isActive ? [IsActive.Active] : [IsActive.Inactive], kinds, - channels + channels, + notificationTypes }) } @@ -65,12 +68,13 @@ export class NotificationTemplateListingFiltersComponent extends BaseComponent i return this._getEmptyFilters(); } - let { isActive, kinds, channels } = inputFilter; + let { isActive, kinds, channels, notificationTypes } = inputFilter; return { isActive: (isActive ?? [])?.includes(IsActive.Active) || !isActive?.length, kinds: kinds, - channels: channels + channels: channels, + notificationTypes: notificationTypes } } @@ -79,7 +83,8 @@ export class NotificationTemplateListingFiltersComponent extends BaseComponent i return { isActive: true, kinds: null, - channels: null + channels: null, + notificationTypes: null } } @@ -100,4 +105,5 @@ interface NotificationTemplateListingFilters { isActive: boolean; kinds: NotificationTemplateKind[]; channels: NotificationTemplateChannel[]; + notificationTypes: NotificationType[]; } diff --git a/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.html b/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.html index e38459e2f..616f548b7 100644 --- a/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.html @@ -1,9 +1,9 @@ -
+
-

{{'NOTIFICATION-TEMPLATE-LISTING.TITLE' | translate}}

+

{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.TITLE' | translate}}

@@ -12,7 +12,7 @@ *ngIf="authService.hasPermission(authService.permissionEnum.EditNotificationTemplate)" [routerLink]="['/notification-templates/new']"> add - {{'NOTIFICATION-TEMPLATE-LISTING.CREATE' | translate}} + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.CREATE' | translate}}
@@ -44,28 +44,44 @@ (click)="$event.stopPropagation()">{{item?.name | nullifyValue}}
- - -
-
- {{enumUtils.toDescriptionTemplateTypeStatusString(item.status) | nullifyValue}} -
-
-
- - + - {{'NOTIFICATION-TEMPLATE-LISTING.FIELDS.CREATED-AT' | translate}}: + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.NOTIFICATION-TYPE' | translate}}: - {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + {{enumUtils.toNotificationTypeString(item.notificationType) | nullifyValue}}
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.KIND' | translate}}: + + {{enumUtils.toNotificationTemplateKindString(item.kind) | nullifyValue}} + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.CHANNEL' | translate}}: + + {{enumUtils.toNotificationTemplateChannelString(item.channel) | nullifyValue}} + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.CREATED-AT' | translate}}: + + {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + + + - {{'NOTIFICATION-TEMPLATE-LISTING.FIELDS.UPDATED-AT' | translate}}: + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.UPDATED-AT' | translate}}: {{item?.updatedAt | dateTimeFormatter : 'short' | nullifyValue}} @@ -83,11 +99,11 @@
diff --git a/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.scss b/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.scss index 6e1b48814..1bf5a1acb 100644 --- a/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.scss +++ b/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.scss @@ -1,4 +1,4 @@ -.description-template-type-listing { +.notification-template-listing { margin-top: 1.3rem; margin-left: 1rem; margin-right: 2rem; diff --git a/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.ts b/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.ts index ab7109fea..412c8a137 100644 --- a/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.ts +++ b/dmp-frontend/src/app/ui/admin/notification-template/listing/notification-template-listing.component.ts @@ -25,10 +25,11 @@ import { NotificationTemplateService } from '@app/core/services/notification-tem import { NotificationTemplateChannelPipe } from '@common/formatting/pipes/notification-template-channel.pipe'; import { NotificationTemplateKindPipe } from '@common/formatting/pipes/notification-template-kind.pipe'; import { Language } from '@app/core/model/language/language'; +import { NotificationTypePipe } from '@common/formatting/pipes/notification-type.pipe'; @Component({ - templateUrl: './NOTIFICATION-TEMPLATE-LISTING.component.html', - styleUrls: ['./NOTIFICATION-TEMPLATE-LISTING.component.scss'] + templateUrl: './notification-template-listing.component.html', + styleUrls: ['./notification-template-listing.component.scss'] }) export class NotificationTemplateListingComponent extends BaseListingComponent implements OnInit { publish = false; @@ -40,6 +41,7 @@ export class NotificationTemplateListingComponent extends BaseListingComponent(x => x.id), + nameof(x => x.notificationType), nameof(x => x.kind), nameof(x => x.channel), nameof(x => x.updatedAt), @@ -90,33 +92,39 @@ export class NotificationTemplateListingComponent extends BaseListingComponent(x => x.notificationType), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.NOTIFICATION-TYPE', + pipe: this.pipeService.getPipe(NotificationTypePipe) + }, + { prop: nameof(x => x.kind), sortable: true, - languageName: 'NOTIFICATION-TEMPLATE-LISTING.FIELDS.KIND', + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.KIND', pipe: this.pipeService.getPipe(NotificationTemplateKindPipe) }, { prop: nameof(x => x.channel), sortable: true, - languageName: 'NOTIFICATION-TEMPLATE-LISTING.FIELDS.CHANNEL', + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.CHANNEL', pipe: this.pipeService.getPipe(NotificationTemplateChannelPipe) }, { prop: nameof(x => x.createdAt), sortable: true, - languageName: 'NOTIFICATION-TEMPLATE-LISTING.FIELDS.CREATED-AT', + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.CREATED-AT', pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') }, { prop: nameof(x => x.updatedAt), sortable: true, - languageName: 'NOTIFICATION-TEMPLATE-LISTING.FIELDS.UPDATED-AT', + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.UPDATED-AT', pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') }, { prop: nameof(x => x.isActive), sortable: true, - languageName: 'NOTIFICATION-TEMPLATE-LISTING.FIELDS.IS-ACTIVE', + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.IS-ACTIVE', pipe: this.pipeService.getPipe(IsActiveTypePipe) }, { diff --git a/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.html new file mode 100644 index 000000000..36441e232 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.html @@ -0,0 +1,84 @@ +
+ + + + + +
+
+
+

{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.TITLE' | translate}}

+ +
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | translate}} + + +
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.USERS' | translate}} + + + +
+ +
+ {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.NOTIFICATION-TYPE' | translate}} + + {{enumUtils.toNotificationTypeString(type)}} + + +
+ +
+ {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.CONTACT-TYPE' | translate}} + + {{enumUtils.toNotificationContactTypeString(contactType)}} + + +
+ +
+ {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.NOTIFY-STATE' | translate}} + + {{enumUtils.toNotificationNotifyStateString(notifyState)}} + + +
+ +
+ {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.TRACKING-STATE' | translate}} + + {{enumUtils.toNotificationTrackingStateString(trackingState)}} + + +
+ +
+ {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.TRACKING-PROCESS' | translate}} + + {{enumUtils.toNotificationTrackingProcessString(trackingProcess)}} + + +
+ +
+ + +
+
+
+
+ + +
diff --git a/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.scss new file mode 100644 index 000000000..ea00a215c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.scss @@ -0,0 +1,21 @@ +::ng-deep.mat-mdc-menu-panel { + max-width: 100% !important; + height: 100% !important; +} + +:host::ng-deep.mat-mdc-menu-content:not(:empty) { + padding-top: 0 !important; +} + + +.filter-button{ + padding-top: .6rem; + padding-bottom: .6rem; + // .mat-icon{ + // font-size: 1.5em; + // width: 1.2em; + // height: 1.2em; + // } +} + + diff --git a/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.ts b/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.ts new file mode 100644 index 000000000..402dad24b --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/filters/notification-listing-filters.component.ts @@ -0,0 +1,137 @@ +import { COMMA, ENTER } from '@angular/cdk/keycodes'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { NotificationContactType } from '@app/core/common/enum/notification-contact-type'; +import { NotificationNotifyState } from '@app/core/common/enum/notification-notify-state'; +import { NotificationTrackingProcess } from '@app/core/common/enum/notification-tracking-process'; +import { NotificationTrackingState } from '@app/core/common/enum/notification-tracking-state'; +import { NotificationType } from '@app/core/common/enum/notification-type'; +import { NotificationFilter } from '@app/core/query/notification.lookup'; +import { UserService } from '@app/core/services/user/user.service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; +import { Guid } from '@common/types/guid'; +import { nameof } from 'ts-simple-nameof'; + +@Component({ + selector: 'app-notification-listing-filters', + templateUrl: './notification-listing-filters.component.html', + styleUrls: ['./notification-listing-filters.component.scss'] +}) +export class NotificationListingFiltersComponent extends BaseComponent implements OnInit, OnChanges { + + @Input() readonly filter: NotificationFilter; + @Output() filterChange = new EventEmitter(); + notificationContactTypeEnumValues = this.enumUtils.getEnumValues(NotificationContactType) + notificationNotifyStateEnumValues = this.enumUtils.getEnumValues(NotificationNotifyState); + notificationTrackingStateEnumValues = this.enumUtils.getEnumValues(NotificationTrackingState); + notificationTrackingProcessEnumValues = this.enumUtils.getEnumValues(NotificationTrackingProcess); + notificationTypeEnumValues = this.enumUtils.getEnumValues(NotificationType); + userAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + + readonly separatorKeysCodes: number[] = [ENTER, COMMA]; + + // * State + internalFilters: NotificationListingFilters = this._getEmptyFilters(); + + protected appliedFilterCount: number = 0; + constructor( + public enumUtils: EnumUtils, + private userService: UserService, + ) { super(); } + + ngOnInit() { + this.userAutoCompleteConfiguration = this.userService.multipleAutocompleteConfiguration; + } + + ngOnChanges(changes: SimpleChanges): void { + const filterChange = changes[nameof(x => x.filter)]?.currentValue as NotificationFilter; + if (filterChange) { + this.updateFilters() + } + } + + + onSearchTermChange(searchTerm: string): void { + this.applyFilters() + } + + + protected updateFilters(): void { + this.internalFilters = this._parseToInternalFilters(this.filter); + this.appliedFilterCount = this._computeAppliedFilters(this.internalFilters); + } + + protected applyFilters(): void { + const { isActive, type, notifyState, notifiedWith, contactType, trackingState, trackingProcess, userIds } = this.internalFilters ?? {} + this.filterChange.emit({ + ...this.filter, + isActive: isActive ? [IsActive.Active] : [IsActive.Inactive], + type, + notifyState, + notifiedWith, + contactType, + trackingState, + trackingProcess, + userIds + }) + } + + + private _parseToInternalFilters(inputFilter: NotificationFilter): NotificationListingFilters { + if (!inputFilter) { + return this._getEmptyFilters(); + } + + let { isActive, type, notifyState, notifiedWith, contactType, trackingState, trackingProcess, userIds } = inputFilter; + + return { + isActive: (isActive ?? [])?.includes(IsActive.Active) || !isActive?.length, + type: type, + notifyState: notifyState, + notifiedWith: notifiedWith, + contactType: contactType, + trackingState: trackingState, + trackingProcess: trackingProcess, + userIds: userIds + } + + } + + private _getEmptyFilters(): NotificationListingFilters { + return { + isActive: true, + type: null, + notifyState: null, + notifiedWith: null, + contactType: null, + trackingState: null, + trackingProcess: null, + userIds: null + } + } + + private _computeAppliedFilters(filters: NotificationListingFilters): number { + let count = 0; + if (filters?.isActive) { + count++ + } + return count; + } + + clearFilters() { + this.internalFilters = this._getEmptyFilters(); + } +} + +interface NotificationListingFilters { + isActive: boolean; + type: NotificationType[]; + notifyState: NotificationNotifyState[]; + notifiedWith: NotificationContactType[]; + contactType: NotificationContactType[]; + trackingState: NotificationTrackingState[]; + trackingProcess: NotificationTrackingProcess[]; + userIds: Guid[]; +} diff --git a/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.html b/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.html new file mode 100644 index 000000000..5d78108ad --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.html @@ -0,0 +1,96 @@ +
+
+ +
+
+

{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.TITLE' | translate}}

+ + +
+
+ + + + + + + + +
+
+ + + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFICATION-TYPE' | translate}}: + + {{enumUtils.toNotificationTypeString(item.type) | nullifyValue}} + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CONTACT-TYPE' | translate}}: + + {{enumUtils.toNotificationContactTypeString(item.contactTypeHint) | nullifyValue}} + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFY-STATE' | translate}}: + + {{enumUtils.toNotificationNotifyStateString(item.notifyState) | nullifyValue}} + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFIED-AT' | translate}}: + + {{item?.notifiedAt | dateTimeFormatter : 'short' | nullifyValue}} + + +
+
+ + + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CREATED-AT' | translate}}: + + {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + + + +
+
+
+ + +
+
+ + + + +
+
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.scss b/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.scss new file mode 100644 index 000000000..09eab6ac5 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.scss @@ -0,0 +1,27 @@ +.notification-listing { + margin-top: 1.3rem; + margin-left: 1rem; + margin-right: 2rem; + + .mat-header-row{ + background: #f3f5f8; + } + .mat-card { + margin: 16px 0; + padding: 0px; + } + + .mat-row { + cursor: pointer; + min-height: 4.5em; + } + + mat-row:hover { + background-color: #eef5f6; + } + .mat-fab-bottom-right { + float: right; + z-index: 5; + } +} + diff --git a/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.ts b/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.ts new file mode 100644 index 000000000..e47455f95 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/notification-listing.component.ts @@ -0,0 +1,231 @@ +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; +import { BaseListingComponent } from '@common/base/base-listing-component'; +import { PipeService } from '@common/formatting/pipe.service'; +import { DataTableDateTimeFormatPipe } from '@common/formatting/pipes/date-time-format.pipe'; +import { QueryResult } from '@common/model/query-result'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { ColumnDefinition, ColumnsChangedEvent, HybridListingComponent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; +import { IsActiveTypePipe } from '@common/formatting/pipes/is-active-type.pipe'; +import { Notification } from '@app/core/model/notification/notification.model'; +import { NotificationLookup } from '@app/core/query/notification.lookup'; +import { NotificationService } from '@app/core/services/notification/notification-service'; +import { NotificationTypePipe } from '@common/formatting/pipes/notification-type.pipe'; +import { NotificationContactTypePipe } from '@common/formatting/pipes/notification-contact-type.pipe'; +import { NotificationNotifyStatePipe } from '@common/formatting/pipes/notification-notify-state.pipe'; +import { NotificationTrackingStatePipe } from '@common/formatting/pipes/notification-tracking-state.pipe'; +import { NotificationTrackingProcessPipe } from '@common/formatting/pipes/notification-tracking-process.pipe'; + +@Component({ + templateUrl: './notification-listing.component.html', + styleUrls: ['./notification-listing.component.scss'] +}) +export class NotificationListingComponent extends BaseListingComponent implements OnInit { + publish = false; + userSettingsKey = { key: 'NotificationListingUserSettings' }; + propertiesAvailableForOrder: ColumnDefinition[]; + + @ViewChild('actions', { static: true }) actions?: TemplateRef; + @ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent; + + private readonly lookupFields: string[] = [ + nameof(x => x.id), + nameof(x => x.type), + nameof(x => x.retryCount), + nameof(x => x.trackingState), + nameof(x => x.trackingProcess), + nameof(x => x.contactTypeHint), + nameof(x => x.notifyState), + nameof(x => x.notifiedWith), + nameof(x => x.notifiedAt), + nameof(x => x.user.id), + nameof(x => x.user.name), + nameof(x => x.createdAt), + nameof(x => x.updatedAt), + nameof(x => x.hash), + nameof(x => x.isActive) + ]; + + rowIdentity = x => x.id; + + constructor( + protected router: Router, + protected route: ActivatedRoute, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected queryParamsService: QueryParamsService, + private notificationService: NotificationService, + public authService: AuthService, + private pipeService: PipeService, + public enumUtils: EnumUtils, + private language: TranslateService, + private dialog: MatDialog + ) { + super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService); + // Lookup setup + // Default lookup values are defined in the user settings class. + this.lookup = this.initializeLookup(); + } + + ngOnInit() { + super.ngOnInit(); + } + + protected initializeLookup(): NotificationLookup { + const lookup = new NotificationLookup(); + lookup.metadata = { countAll: true }; + lookup.page = { offset: 0, size: this.ITEMS_PER_PAGE }; + lookup.isActive = [IsActive.Active]; + lookup.order = { items: [this.toDescSortField(nameof(x => x.createdAt))] }; + this.updateOrderUiFields(lookup.order); + + lookup.project = { + fields: this.lookupFields + }; + + return lookup; + } + + protected setupColumns() { + this.gridColumns.push(...[{ + prop: nameof(x => x.type), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFICATION-TYPE', + pipe: this.pipeService.getPipe(NotificationTypePipe) + }, + { + prop: nameof(x => x.contactTypeHint), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CONTACT-TYPE', + pipe: this.pipeService.getPipe(NotificationContactTypePipe) + }, + { + prop: nameof(x => x.notifyState), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFY-STATE', + pipe: this.pipeService.getPipe(NotificationNotifyStatePipe) + }, + { + prop: nameof(x => x.notifiedWith), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFIED-WITH', + pipe: this.pipeService.getPipe(NotificationContactTypePipe) + }, + { + prop: nameof(x => x.notifiedAt), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFIED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + prop: nameof(x => x.trackingState), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.TRACKING-STATE', + pipe: this.pipeService.getPipe(NotificationTrackingStatePipe) + }, + { + prop: nameof(x => x.user.name), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.USER', + }, + { + prop: nameof(x => x.trackingProcess), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.TRACKING-PROCESS', + pipe: this.pipeService.getPipe(NotificationTrackingProcessPipe) + }, + { + prop: nameof(x => x.retryCount), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.RETRY-COUNT', + }, + { + prop: nameof(x => x.createdAt), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CREATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + prop: nameof(x => x.updatedAt), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.UPDATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + prop: nameof(x => x.isActive), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.IS-ACTIVE', + pipe: this.pipeService.getPipe(IsActiveTypePipe) + }, + { + alwaysShown: true, + cellTemplate: this.actions, + maxWidth: 120 + } + ]); + this.propertiesAvailableForOrder = this.gridColumns.filter(x => x.sortable); + } + + // + // Listing Component functions + // + onColumnsChanged(event: ColumnsChangedEvent) { + super.onColumnsChanged(event); + this.onColumnsChangedInternal(event.properties.map(x => x.toString())); + } + + private onColumnsChangedInternal(columns: string[]) { + // Here are defined the projection fields that always requested from the api. + const fields = new Set(this.lookupFields); + this.gridColumns.map(x => x.prop) + .filter(x => !columns?.includes(x as string)) + .forEach(item => { + fields.delete(item as string) + }); + this.lookup.project = { fields: [...fields] }; + this.onPageLoad({ offset: 0 } as PageLoadEvent); + } + + protected loadListing(): Observable> { + return this.notificationService.query(this.lookup); + } + + public deleteType(id: Guid) { + if (id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { + isDeleteConfirmation: true, + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.notificationService.delete(id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success); + this.ngOnInit(); + } +} diff --git a/dmp-frontend/src/app/ui/admin/notification/notification.module.ts b/dmp-frontend/src/app/ui/admin/notification/notification.module.ts new file mode 100644 index 000000000..68d779f10 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/notification.module.ts @@ -0,0 +1,41 @@ +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { NgModule } from "@angular/core"; +import { AutoCompleteModule } from "@app/library/auto-complete/auto-complete.module"; +import { CommonFormattingModule } from '@common/formatting/common-formatting.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { HybridListingModule } from "@common/modules/hybrid-listing/hybrid-listing.module"; +import { TextFilterModule } from "@common/modules/text-filter/text-filter.module"; +import { UserSettingsModule } from "@common/modules/user-settings/user-settings.module"; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { NgxDropzoneModule } from "ngx-dropzone"; +import { NotificationListingComponent } from './notification-listing.component'; +import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-editor.module'; +import { NotificationRoutingModule } from './notification.routing'; +import { NotificationListingFiltersComponent } from './filters/notification-listing-filters.component'; +import { MatIconModule } from '@angular/material/icon'; +import { EditorModule } from '@tinymce/tinymce-angular'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + ConfirmationDialogModule, + NotificationRoutingModule, + NgxDropzoneModule, + DragDropModule, + AutoCompleteModule, + HybridListingModule, + TextFilterModule, + UserSettingsModule, + CommonFormattingModule, + RichTextEditorModule, + MatIconModule, + EditorModule + ], + declarations: [ + NotificationListingComponent, + NotificationListingFiltersComponent + ] +}) +export class NotificationModule { } diff --git a/dmp-frontend/src/app/ui/admin/notification/notification.routing.ts b/dmp-frontend/src/app/ui/admin/notification/notification.routing.ts new file mode 100644 index 000000000..9174a1ae0 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/notification/notification.routing.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '@app/core/auth-guard.service'; +import { NotificationListingComponent } from './notification-listing.component'; + +const routes: Routes = [ + { + path: '', + component: NotificationListingComponent, + canActivate: [AuthGuard] + }, + { path: '**', loadChildren: () => import('@common/modules/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule) }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [] +}) +export class NotificationRoutingModule { } diff --git a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html index 29c1fdd99..afd96d71d 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html @@ -35,10 +35,8 @@ {{'REFERENCE-TYPE-EDITOR.FIELDS.NAME' | translate}} - - {{formGroup.get('name').getError('backendError').message}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('name').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -89,24 +87,24 @@ {{'REFERENCE-TYPE-EDITOR.FIELDS.LABEL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('label').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-TYPE-EDITOR.FIELDS.DESCRIPTION' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('description').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-TYPE-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.ts b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.ts index 9b634f833..6594a1e2e 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.ts @@ -13,7 +13,7 @@ import { AppPermission } from '@app/core/common/enum/permission.enum'; import { ReferenceFieldDataType } from '@app/core/common/enum/reference-field-data-type'; import { ReferenceTypeExternalApiHTTPMethodType } from '@app/core/common/enum/reference-type-external-api-http-method-type'; import { ReferenceTypeSourceType } from '@app/core/common/enum/reference-type-source-type'; -import { ReferenceType, ReferenceTypePersist } from '@app/core/model/reference-type/reference-type'; +import { ReferenceType, ReferenceTypeDefinition, ReferenceTypePersist } from '@app/core/model/reference-type/reference-type'; import { AuthService } from '@app/core/services/auth/auth.service'; import { LoggingService } from '@app/core/services/logging/logging-service'; import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; @@ -25,7 +25,7 @@ import { FilterService } from '@common/modules/text-filter/filter-service'; import { Guid } from '@common/types/guid'; import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; -import { DependencyPropertyEditorModel, QueryConfigEditorModel, ReferenceTypeEditorModel, ReferenceTypeFieldEditorModel, ReferenceTypeSourceBaseConfigurationEditorModel, ReferenceTypeSourceBaseDependencyEditorModel, ReferenceTypeStaticOptionEditorModel, ResultFieldsMappingConfigurationEditorModel } from './reference-type-editor.model'; +import { DependencyPropertyEditorModel, QueryConfigEditorModel, ReferenceTypeDefinitionEditorModel, ReferenceTypeEditorModel, ReferenceTypeFieldEditorModel, ReferenceTypeSourceBaseConfigurationEditorModel, ReferenceTypeSourceBaseDependencyEditorModel, ReferenceTypeStaticOptionEditorModel, ResultFieldsMappingConfigurationEditorModel } from './reference-type-editor.model'; import { ReferenceTypeEditorResolver } from './reference-type-editor.resolver'; import { ReferenceTypeEditorService } from './reference-type-editor.service'; @@ -172,9 +172,9 @@ export class ReferenceTypeEditorComponent extends BaseEditor new ReferenceTypeFieldEditorModel( this.validationErrorModel ).fromModel(item).buildForm({ - rootPath: `fields[${index}].` + rootPath: `[${index}].` }), context.getValidation('fields') ) ), @@ -128,6 +147,21 @@ export class ReferenceTypeDefinitionEditorModel implements ReferenceTypeDefiniti return baseContext; } + static reapplyFieldsValidators(params: { + formArray: UntypedFormArray, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + const { validationErrorModel, rootPath, formArray } = params; + formArray?.controls?.forEach( + (control, index) => ReferenceTypeFieldEditorModel.reapplyValidators({ + formGroup: control as UntypedFormGroup, + rootPath: `${rootPath}fields[${index}].`, + validationErrorModel: validationErrorModel + }) + ); + } + } export class ReferenceTypeFieldEditorModel implements ReferenceTypeFieldPersist { @@ -182,14 +216,32 @@ export class ReferenceTypeFieldEditorModel implements ReferenceTypeFieldPersist const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'code', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}code`)] }); - baseValidationArray.push({ key: 'label', validators: [Validators.required,BackendErrorValidator(validationErrorModel, `${rootPath}label`)] }); + baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}label`)] }); baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}description`)] }); - baseValidationArray.push({ key: 'dataType', validators: [Validators.required,BackendErrorValidator(validationErrorModel, `${rootPath}dataType`)] }); + baseValidationArray.push({ key: 'dataType', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}dataType`)] }); baseContext.validation = baseValidationArray; return baseContext; } + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = ReferenceTypeFieldEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['code', 'label', 'description', 'dataType'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + } } export class ReferenceTypeSourceBaseConfigurationEditorModel implements ReferenceTypeSourceBaseConfigurationPersist { @@ -209,9 +261,9 @@ export class ReferenceTypeSourceBaseConfigurationEditorModel implements Referenc auth: AuthenticationConfigurationEditorModel = new AuthenticationConfigurationEditorModel(); queries?: QueryConfigEditorModel[] = []; - options : ReferenceTypeStaticOptionEditorModel[] = []; + options: ReferenceTypeStaticOptionEditorModel[] = []; - dependencies : ReferenceTypeSourceBaseDependencyEditorModel[] = []; + dependencies: ReferenceTypeSourceBaseDependencyEditorModel[] = []; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -234,18 +286,18 @@ export class ReferenceTypeSourceBaseConfigurationEditorModel implements Referenc if (item.httpMethod) this.httpMethod = item.httpMethod; if (item.requestBody) this.requestBody = item.requestBody; if (item.filterType) this.filterType = item.filterType; - if (item.auth) this.auth = new AuthenticationConfigurationEditorModel().fromModel(item.auth); - if(item.queries) { item.queries.map(x => this.queries.push(new QueryConfigEditorModel().fromModel(x))); } - - if(item.options) { + if (item.auth) this.auth = new AuthenticationConfigurationEditorModel().fromModel(item.auth); + if (item.queries) { item.queries.map(x => this.queries.push(new QueryConfigEditorModel().fromModel(x))); } + + if (item.options) { item.options.map(x => this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel(x))); } else { - this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel({code: 'reference_id', value: undefined})); - this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel({code: 'label', value: undefined})); - this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel({code: 'description', value: undefined})); + this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel({ code: 'reference_id', value: undefined })); + this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel({ code: 'label', value: undefined })); + this.options.push(new ReferenceTypeStaticOptionEditorModel().fromModel({ code: 'description', value: undefined })); } - if(item.dependencies) { item.dependencies.map(x => this.dependencies.push(new ReferenceTypeSourceBaseDependencyEditorModel().fromModel(x))); } + if (item.dependencies) { item.dependencies.map(x => this.dependencies.push(new ReferenceTypeSourceBaseDependencyEditorModel().fromModel(x))); } } return this; } @@ -281,7 +333,7 @@ export class ReferenceTypeSourceBaseConfigurationEditorModel implements Referenc requestBody: [{ value: this.requestBody, disabled: disabled }, context.getValidation('requestBody').validators], filterType: [{ value: this.filterType, disabled: disabled }, context.getValidation('filterType').validators], auth: this.auth.buildForm({ - rootPath: `auth.` + rootPath: `auth.` }), queries: this.formBuilder.array( (this.queries ?? []).map( @@ -323,9 +375,9 @@ export class ReferenceTypeSourceBaseConfigurationEditorModel implements Referenc const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'type', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}type`)] }); - baseValidationArray.push({ key: 'key', validators: [Validators.required,BackendErrorValidator(validationErrorModel, `${rootPath}key`)] }); - baseValidationArray.push({ key: 'label', validators: [Validators.required,BackendErrorValidator(validationErrorModel, `${rootPath}label`)] }); - baseValidationArray.push({ key: 'ordinal', validators: [Validators.required,Validators.pattern("^[0-9]*$"), BackendErrorValidator(validationErrorModel, `${rootPath}ordinal`)] }); + baseValidationArray.push({ key: 'key', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}key`)] }); + baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}label`)] }); + baseValidationArray.push({ key: 'ordinal', validators: [Validators.required, Validators.pattern("^[0-9]*$"), BackendErrorValidator(validationErrorModel, `${rootPath}ordinal`)] }); baseValidationArray.push({ key: 'url', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}url`)] }); baseValidationArray.push({ key: 'paginationPath', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}paginationPath`)] }); @@ -348,7 +400,7 @@ export class ReferenceTypeSourceBaseConfigurationEditorModel implements Referenc export class ResultsConfigurationEditorModel implements ResultsConfigurationPersist { public resultsArrayPath: string; - public fieldsMapping: ResultFieldsMappingConfigurationEditorModel[] =[]; + public fieldsMapping: ResultFieldsMappingConfigurationEditorModel[] = []; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -358,11 +410,11 @@ export class ResultsConfigurationEditorModel implements ResultsConfigurationPers fromModel(item: ResultsConfiguration): ResultsConfigurationEditorModel { this.resultsArrayPath = item.resultsArrayPath; - if(item.fieldsMapping) { item.fieldsMapping.map(x => this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel(x))); } + if (item.fieldsMapping) { item.fieldsMapping.map(x => this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel(x))); } else { - this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel({code: 'reference_id', responsePath: undefined})); - this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel({code: 'label', responsePath: undefined})); - this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel({code: 'description', responsePath: undefined})); + this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel({ code: 'reference_id', responsePath: undefined })); + this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel({ code: 'label', responsePath: undefined })); + this.fieldsMapping.push(new ResultFieldsMappingConfigurationEditorModel().fromModel({ code: 'description', responsePath: undefined })); } return this; } @@ -391,7 +443,7 @@ export class ResultsConfigurationEditorModel implements ResultsConfigurationPers }), context.getValidation('fieldsMapping') ) ) - + }); } @@ -661,7 +713,7 @@ export class ReferenceTypeSourceBaseDependencyEditorModel implements ReferenceTy this.referenceTypeCode = item.referenceTypeCode; this.key = item.key; this.required = item.required; - if(item.properties) { item.properties.map(x => this.properties.push(new DependencyPropertyEditorModel().fromModel(x))); } + if (item.properties) { item.properties.map(x => this.properties.push(new DependencyPropertyEditorModel().fromModel(x))); } return this; } diff --git a/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.html b/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.html index 26530010e..32e3296e4 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.html @@ -1,4 +1,4 @@ -
+
@@ -49,12 +49,13 @@ -
-
- {{enumUtils.toDescriptionTemplateTypeStatusString(item.status) | nullifyValue}} -
-
+ + {{'REFERENCE-TYPE-LISTING.FIELDS.CODE' | translate}}: + + {{item?.code | nullifyValue}} + + +
diff --git a/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.scss b/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.scss index 6e1b48814..cd02faad1 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.scss +++ b/dmp-frontend/src/app/ui/admin/reference-type/listing/reference-type-listing.component.scss @@ -1,4 +1,4 @@ -.description-template-type-listing { +.reference-type-listing { margin-top: 1.3rem; margin-left: 1rem; margin-right: 2rem; diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html index 80e0cadbd..f527e3962 100644 --- a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html @@ -33,8 +33,8 @@ {{'REFERENCE-EDITOR.FIELDS.LABEL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('label').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -44,9 +44,9 @@ {{enumUtils.toReferenceTypeString(type)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{formGroup.get('type').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -55,9 +55,8 @@
- - {{'GENERAL.VALIDATION.REQUIRED'| translate}} - + {{formGroup.get('description').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED'| translate}}
@@ -65,8 +64,8 @@ {{'REFERENCE-EDITOR.FIELDS.SOURCE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('source').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -76,25 +75,25 @@ {{enumUtils.toReferenceSourceTypeString(sourceType)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{formGroup.get('sourceType').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-EDITOR.FIELDS.REFERENCE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('reference').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-EDITOR.FIELDS.ABBREVIATION' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('abbreviation').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -121,8 +120,8 @@ {{'REFERENCE-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -132,17 +131,17 @@ {{enumUtils.toReferenceFieldDataTypeString(dataType)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{field.get('dataType').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-EDITOR.FIELDS.VALUE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('value').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts index f18bb26e6..a5741084e 100644 --- a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts @@ -190,12 +190,19 @@ export class ReferenceEditorComponent extends BaseEditor FieldEditorModel.reapplyValidators({ + formGroup: control as UntypedFormGroup, + rootPath: `${rootPath}fields[${index}].`, + validationErrorModel: validationErrorModel + }) + ); + } } export class FieldEditorModel implements FieldPersist { @@ -191,5 +225,24 @@ export class FieldEditorModel implements FieldPersist { baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = FieldEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['code', 'dataType', 'value'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + } } diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html index c1a42cc4b..6f349fd72 100644 --- a/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html @@ -39,12 +39,42 @@
- + {{item?.name | nullifyValue}} + (click)="$event.stopPropagation()">{{item?.label | nullifyValue}}
+ + + {{'REFERENCE-LISTING.FIELDS.SOURCE' | translate}}: + + {{item.source}} + + +
+
+ + + + {{'REFERENCE-LISTING.FIELDS.SOURCE-TYPE' | translate}}: + + {{enumUtils.toReferenceTypeSourceTypeString(item.sourceType) | nullifyValue}} + + +
+
+ + + + {{'REFERENCE-LISTING.FIELDS.TYPE' | translate}}: + + {{enumUtils.toReferenceTypeString(item.type) | nullifyValue}} + + +
+
+ {{'REFERENCE-LISTING.FIELDS.CREATED-AT' | translate}}: diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html index 48e3f4bcd..377ee3ef5 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html @@ -32,16 +32,16 @@ {{'TENANT-EDITOR.FIELDS.NAME' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('name').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -50,9 +50,8 @@
- - {{'GENERAL.VALIDATION.REQUIRED'| translate}} - + {{formGroup.get('description').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED'| translate}}
@@ -79,40 +78,40 @@ {{'TENANT-EDITOR.FIELDS.URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('url').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('issuerUrl').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientSecret').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('scope').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -134,6 +133,8 @@ [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addDepositCode($event)"/> + {{source.get('codes').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -162,40 +163,40 @@ {{'TENANT-EDITOR.FIELDS.URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('url').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('issuerUrl').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientSecret').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('scope').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -217,6 +218,8 @@ [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addFileCode($event)"/> + {{source.get('codes').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts index a2e83aadf..b3269e787 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts @@ -192,12 +192,20 @@ export class TenantEditorComponent extends BaseEditor // deposit source // addDepositSource(): void { - const source: TenantSourceEditorModel = new TenantSourceEditorModel(); - (this.formGroup.get('config').get('deposit').get('sources') as FormArray).push(source.buildForm()); + (this.formGroup.get('config').get('deposit').get('sources') as FormArray).push(this.editorModel.createChildDeposit((this.formGroup.get('config').get('deposit').get('sources') as FormArray).length)); } removeDepositSource(sourceIndex: number): void { (this.formGroup.get('config').get('deposit').get('sources') as FormArray).removeAt(sourceIndex); + + //Reapply validators + TenantEditorModel.reApplyDepositSourcesValidators( + { + formGroup: this.formGroup, + validationErrorModel: this.editorModel.validationErrorModel + } + ) + this.formGroup.get('config').get('deposit').get('sources').markAsDirty(); } // deposit source codes @@ -232,12 +240,20 @@ export class TenantEditorComponent extends BaseEditor // fileTransformers source // addFileSource(): void { - const source: TenantSourceEditorModel = new TenantSourceEditorModel(); - (this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).push(source.buildForm()); + (this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).push(this.editorModel.createChildFileTransformer((this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).length)); } removeFileSource(sourceIndex: number): void { (this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).removeAt(sourceIndex); + + //Reapply validators + TenantEditorModel.reApplyFileTransformerSourcesValidators( + { + formGroup: this.formGroup, + validationErrorModel: this.editorModel.validationErrorModel + } + ) + this.formGroup.get('config').get('fileTransformers').get('sources').markAsDirty(); } // fileTransformers source codes diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts index 268d4554d..ec5775981 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts @@ -1,4 +1,4 @@ -import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { Tenant, TenantConfig, TenantConfigPersist, TenantDepositConfig, TenantDepositConfigPersist, TenantFileTransformersConfig, TenantFileTransformersConfigPersist, TenantPersist, TenantSource, TenantSourcePersist } from "@app/core/model/tenant/tenant"; import { BaseEditorModel } from "@common/base/base-form-editor-model"; import { BackendErrorValidator } from "@common/forms/validation/custom-validator"; @@ -55,6 +55,44 @@ export class TenantEditorModel extends BaseEditorModel implements TenantPersist baseContext.validation = baseValidationArray; return baseContext; } + + createChildDeposit(index: number): UntypedFormGroup { + const deposit: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel); + return deposit.buildForm({ rootPath: 'config.deposit.sources[' + index + '].' }); + } + + static reApplyDepositSourcesValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; + const control = formGroup?.get('config').get('deposit'); + TenantDepositConfigEditorModel.reapplySourcesFieldsValidators({ + formArray: control.get('sources') as UntypedFormArray, + rootPath: `config.deposit.`, + validationErrorModel: validationErrorModel + }); + } + + createChildFileTransformer(index: number): UntypedFormGroup { + const deposit: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel); + return deposit.buildForm({ rootPath: 'config.fileTransformers.sources[' + index + '].' }); + } + + static reApplyFileTransformerSourcesValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; + const control = formGroup?.get('config').get('fileTransformers'); + TenantDepositConfigEditorModel.reapplySourcesFieldsValidators({ + formArray: control.get('sources') as UntypedFormArray, + rootPath: `config.fileTransformers.`, + validationErrorModel: validationErrorModel + }); + } } export class TenantConfigEditorModel implements TenantConfigPersist { @@ -167,6 +205,21 @@ export class TenantDepositConfigEditorModel implements TenantDepositConfigPersis baseContext.validation = baseValidationArray; return baseContext; } + + static reapplySourcesFieldsValidators(params: { + formArray: UntypedFormArray, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + const { validationErrorModel, rootPath, formArray } = params; + formArray?.controls?.forEach( + (control, index) => TenantSourceEditorModel.reapplyValidators({ + formGroup: control as UntypedFormGroup, + rootPath: `${rootPath}sources[${index}].`, + validationErrorModel: validationErrorModel + }) + ); + } } export class TenantFileTransformersConfigEditorModel implements TenantFileTransformersConfigPersist { @@ -294,4 +347,23 @@ export class TenantSourceEditorModel implements TenantSourcePersist { baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = TenantSourceEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['url', 'codes', 'issuerUrl', 'clientId', 'clientSecret', 'scope'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + } } diff --git a/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html b/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html index 93669a2f5..7e147010a 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html @@ -45,13 +45,14 @@
- -
-
- {{enumUtils.toDescriptionTemplateTypeStatusString(item.status) | nullifyValue}} -
-
+ + + {{'TENANT-LISTING.FIELDS.CODE' | translate}}: + + {{item?.code | nullifyValue}} + + +
diff --git a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts index 8807da134..214555534 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, UntypedFormGroup } from '@angular/forms'; import { User, UserRolePatchPersist } from '@app/core/model/user/user'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; @@ -26,7 +26,7 @@ import { AppRole } from '@app/core/common/enum/app-role'; styleUrls: ['./user-role-editor.component.scss'], providers: [UserRoleEditorService] }) -export class UserRoleEditorComponent extends BaseComponent implements OnInit { +export class UserRoleEditorComponent extends BaseComponent implements OnInit, OnChanges { @Input() public item: User; public formGroup: UntypedFormGroup = null; @@ -49,7 +49,14 @@ export class UserRoleEditorComponent extends BaseComponent implements OnInit { ) { super(); } ngOnInit() { - if (this.formGroup == null) { this.prepareForm(this.item); } + this.prepareForm(this.item); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['item']) { + this.prepareForm(this.item); + this.nowEditing = false; + } } prepareForm(data: User) { diff --git a/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.html b/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.html index 611c28e7a..372ab5990 100644 --- a/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.html +++ b/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.html @@ -7,8 +7,7 @@
- - + {{formGroup.get('subject').getError('backendError').message}} @@ -17,7 +16,7 @@
- + {{formGroup.get('description').getError('backendError').message}} diff --git a/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.scss b/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.scss index 13a78e08f..0db19b4f4 100644 --- a/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.scss +++ b/dmp-frontend/src/app/ui/contact/contact-content/contact-content.component.scss @@ -23,6 +23,10 @@ img { padding-right: 1em; } +.mat-form-field { + width: 100%; +} + .send-btn { background: #ffffff 0% 0% no-repeat padding-box; border: 1px solid var(--primary-color); diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html index 1f09c0cee..50e410696 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html @@ -150,48 +150,35 @@
- - {{'DMP-EDITOR.PLACEHOLDER.RESEARCHERS' | translate}} - - - - {{formGroup.get('researchers').getError('backendError').message}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - -
- {{'DMP-EDITOR.FUNDING-INFO.FIND' | translate}} - {{'DMP-EDITOR.ACTIONS.INSERT-MANUALLY' | translate}} -
+
-
- - - {{vis.name | translate}} + + + {{enumUtils.toDmpAccessTypeString(dmpAccessType)}} - - {{formGroup.get('extraProperties').get('visible').getError('backendError').message}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('accessType').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} -
--> +
@@ -274,18 +240,17 @@
+ {{formGroup.get('descriptionTemplates').value | json}}
{{'DMP-EDITOR.FIELDS.DESCRIPTION-TEMPLATES' | translate}}
{{'DMP-EDITOR.FIELDS.DESCRIPTION-TEMPLATES-HINT' | translate}} - + - - {{formGroup.get('profiles').getError('backendError').message}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('descriptionTemplates').get(section.id).get('descriptionTemplateGroupId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss index 3d4fd45d8..447cb06ab 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss @@ -366,21 +366,6 @@ a:hover { margin-bottom: 1rem; } - .insert-manually { - text-decoration: underline; - color: var(--primary-color-3); - cursor: pointer; - font-size: 1rem; - font-weight: 400; - } - - .not-found { - // cursor: pointer; - font-size: 1rem; - font-weight: 400; - padding: 0rem 0.5rem 0rem 0rem; - } - .not-found-template { font-size: 0.875rem; font-weight: 400; diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts index 06c75f60e..f9417430e 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts @@ -33,6 +33,13 @@ import { map, takeUntil } from 'rxjs/operators'; import { DmpEditorModel } from './dmp-editor.model'; import { DmpEditorResolver } from './dmp-editor.resolver'; import { DmpEditorService } from './dmp-editor.service'; +import { ReferenceType } from '@app/core/common/enum/reference-type'; +import { LanguageInfo } from '@app/core/model/language-info'; +import { LanguageInfoService } from '@app/core/services/culture/language-info-service'; +import { DmpAccessType } from '@app/core/common/enum/dmp-access-type'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { UntypedFormArray } from '@angular/forms'; +import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service'; @Component({ selector: 'app-dmp-editor', @@ -52,6 +59,9 @@ export class DmpEditorComponent extends BaseEditor implemen dmpBlueprintSectionFieldCategoryEnum = DmpBlueprintSectionFieldCategory; dmpBlueprintSystemFieldTypeEnum = DmpBlueprintSystemFieldType; dmpBlueprintExtraFieldDataTypeEnum = DmpBlueprintExtraFieldDataType; + referenceTypeEnum = ReferenceType; + dmpAccessTypeEnum = DmpAccessType; + dmpAccessTypeEnumValues = this.enumUtils.getEnumValues(DmpAccessType); protected get canDelete(): boolean { return !this.isDeleted && !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteDmp); @@ -84,7 +94,6 @@ export class DmpEditorComponent extends BaseEditor implemen protected queryParamsService: QueryParamsService, // Rest dependencies. Inject any other needed deps here: public authService: AuthService, - // public enumUtils: EnumUtils, private dmpService: DmpService, private logger: LoggingService, // private descriptionEditorService: DescriptionEditorService, @@ -92,7 +101,10 @@ export class DmpEditorComponent extends BaseEditor implemen private matomoService: MatomoService, private lockService: LockService, private configurationService: ConfigurationService, - // public visibilityRulesService: VisibilityRulesService + // public visibilityRulesService: VisibilityRulesService, + private languageInfoService: LanguageInfoService, + private enumUtils: EnumUtils, + public descriptionTemplateService: DescriptionTemplateService ) { super(dialog, language, formService, router, uiNotificationService, httpErrorHandlingService, filterService, datePipe, route, queryParamsService); @@ -343,6 +355,81 @@ export class DmpEditorComponent extends BaseEditor implemen // this.onSubmit(true, false); } + // + // + // Description Template + // + // + + onRemoveDescriptionTemplate(event, sectionIndex: number) { + let found = false; + const section = this.selectedBlueprint.definition.sections[sectionIndex]; + let sectionDescriptionTemplates = (this.formGroup.get('descriptionTemplates') as UntypedFormArray).controls.find(x => x.get('sectionId').value === event.id); + } + + onPreviewDescriptionTemplate(event, sectionIndex: number) { + // const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, { + // width: '590px', + // minHeight: '200px', + // restoreFocus: false, + // data: { + // template: event + // }, + // panelClass: 'custom-modalbox' + // }); + // dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + // if (result) { + // this.addProfile(event, sectionIndex); + // this.profilesAutoCompleteConfiguration = { + // filterFn: this.filterProfiles.bind(this), + // initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), + // displayFn: (item) => item['label'], + // titleFn: (item) => item['label'], + // subtitleFn: (item) => item['description'], + // popupItemActionIcon: 'visibility' + // }; + // } + // }); + } + + onDescriptionTemplateSelected(event, sectionIndex: number) { + try { + this.addProfile(event, sectionIndex); + // const profileCounts: Map = new Map(); + // profiles.forEach((value) => profileCounts.set(value.id, (profileCounts.get(value.id) !== undefined ? profileCounts.get(value.id): 0 ) + 1)); + // const duplicateProfiles = profiles.filter((value) => { + // let isOk = profileCounts.get(value.id) > 1; + // if (isOk) { + // profileCounts.set(value.id, 0); + // } + // return isOk; + // }); + // duplicateProfiles.forEach((value) => profiles.splice(profiles.lastIndexOf(value), 1)); + // profiles.sort((a,b)=> a.label.localeCompare(b.label)); + } catch { + console.info('Could not sort Dataset Templates') + } + } + + addProfile(event, sectionIndex: number) { + // const profiles = this.formGroup.get('profiles').value as DmpDatasetProfile[]; + // let found = profiles.find((value) => value.id === event.id); + // if (found !== undefined) { + // if (found.data.dmpSectionIndex.indexOf(sectionIndex) === -1) { + // found.data.dmpSectionIndex.push(sectionIndex); + // } + // else { + // this.sectionTemplates[sectionIndex].pop(); + // } + // } + // else { + // let dmpDatasetProfileSection: DmpDatasetProfileSectionsFormModel = new DmpDatasetProfileSectionsFormModel(); + // dmpDatasetProfileSection.dmpSectionIndex = [sectionIndex]; + // profiles.push({ id: null, descriptionTemplateId: event.id, label: event.label, data: dmpDatasetProfileSection }); + // } + // this.formGroup.get('profiles').setValue(profiles); + } + // // // Misc @@ -352,6 +439,9 @@ export class DmpEditorComponent extends BaseEditor implemen return this.formGroup && this.formGroup.dirty; //&& this.hasChanges; } + getLanguageInfos(): LanguageInfo[] { + return this.languageInfoService.getLanguageInfoValues(); + } // canDeactivate(): boolean { // return !this.isDirty(); @@ -1470,7 +1560,7 @@ export class DmpEditorComponent extends BaseEditor implemen // this.formGroup.get('profiles').setValue(profiles); // } - // onPreviewTemplate(event, sectionIndex: number) { + // onPreviewDescriptionTemplate(event, sectionIndex: number) { // const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, { // width: '590px', // minHeight: '200px', diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts index 7ba14a1bf..925190814 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts @@ -1,7 +1,8 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { DmpAccessType } from "@app/core/common/enum/dmp-access-type"; import { DmpStatus } from "@app/core/common/enum/dmp-status"; -import { Dmp, DmpDescriptionTemplate, DmpDescriptionTemplatePersist, DmpPersist, DmpReferencePersist } from "@app/core/model/dmp/dmp"; +import { DmpBlueprint } from "@app/core/model/dmp-blueprint/dmp-blueprint"; +import { Dmp, DmpBlueprintValue, DmpBlueprintValuePersist, DmpContact, DmpContactPersist, DmpDescriptionTemplate, DmpDescriptionTemplatePersist, DmpPersist, DmpProperties, DmpPropertiesPersist, DmpReferenceDataPersist, DmpReferencePersist } from "@app/core/model/dmp/dmp"; import { DmpReference } from "@app/core/model/dmp/dmp-reference"; import { ReferencePersist } from "@app/core/model/reference/reference"; import { BaseEditorModel } from "@common/base/base-form-editor-model"; @@ -13,12 +14,12 @@ import { Guid } from "@common/types/guid"; export class DmpEditorModel extends BaseEditorModel implements DmpPersist { label: string; status: DmpStatus; - properties: string; + properties: DmpPropertiesEditorModel; description: String; language: String; blueprint: Guid; accessType: DmpAccessType; - references: DmpReferenceEditorModel[] = []; + // references: DmpReferenceEditorModel[] = []; descriptionTemplates: DmpDescriptionTemplateEditorModel[] = []; permissions: string[]; @@ -32,12 +33,12 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { super.fromModel(item); this.label = item.label; this.status = item.status; - this.properties = item.properties; + this.properties = new DmpPropertiesEditorModel().fromModel(item.properties, item.dmpReferences, item.blueprint); this.description = item.description; this.language = item.language; this.blueprint = item.blueprint?.id; this.accessType = item.accessType; - if (item.dmpReferences) { item.dmpReferences.map(x => this.references.push(new DmpReferenceEditorModel().fromModel(x))); } + //if (item.dmpReferences) { item.dmpReferences.map(x => this.references.push(new DmpReferenceEditorModel().fromModel(x))); } if (item.dmpDescriptionTemplates) { item.dmpDescriptionTemplates.map(x => this.descriptionTemplates.push(new DmpDescriptionTemplateEditorModel().fromModel(x))); } } return this; @@ -50,7 +51,9 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], - properties: [{ value: this.properties, disabled: disabled }, context.getValidation('properties').validators], + properties: this.properties.buildForm({ + rootPath: `properties.` + }), description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators], blueprint: [{ value: this.blueprint, disabled: disabled }, context.getValidation('blueprint').validators], @@ -64,25 +67,24 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { // }), context.getValidation('references') // ) // ), - // descriptionTemplates: this.formBuilder.array( - // (this.descriptionTemplates ?? []).map( - // (item, index) => new DmpDescriptionTemplateEditorModel( - // this.validationErrorModel - // ).fromModel(item).buildForm({ - // rootPath: `descriptionTemplates[${index}].` - // }), context.getValidation('descriptionTemplates') - // ) - // ), hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] }); - (this.references ?? []).map( - (item, index) => formGroup.addControl(item.id.toString(), new DmpReferenceEditorModel( - this.validationErrorModel - ).fromModel(item).buildForm({ - rootPath: `references[${index}].` - })), context.getValidation('references') + + // (this.references ?? []).filter(x => x?.data?.blueprintFieldId).map(x => x?.data?.blueprintFieldId).map( + // (item, index) => formGroup.addControl(item.data.blueprintFieldId.toString(), new DmpReferenceEditorModel( + // this.validationErrorModel + // ).fromModel(item).buildForm({ + // rootPath: `references[${index}].` + // })), context.getValidation('references') + // ) + const descriptionTemplatesFormGroup = this.formBuilder.group({}); + (this.descriptionTemplates ?? []).filter(x => x?.sectionId).map(x => x.sectionId).map( + (item, index) => descriptionTemplatesFormGroup.addControl(item.toString(), this.descriptionTemplates.find(x => x.sectionId === item).buildForm({ + rootPath: `descriptionTemplates[${index}].` + })), context.getValidation('descriptionTemplates') ) + formGroup.addControl('descriptionTemplates', descriptionTemplatesFormGroup); return formGroup; } @@ -98,7 +100,7 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { baseValidationArray.push({ key: 'language', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'language')] }); baseValidationArray.push({ key: 'blueprint', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'blueprint')] }); baseValidationArray.push({ key: 'accessType', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'accessType')] }); - baseValidationArray.push({ key: 'references', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'references')] }); + //baseValidationArray.push({ key: 'references', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'references')] }); baseValidationArray.push({ key: 'descriptionTemplates', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] }); baseValidationArray.push({ key: 'hash', validators: [] }); @@ -107,10 +109,205 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { } } +export class DmpPropertiesEditorModel implements DmpPropertiesPersist { + dmpBlueprintValues: DmpBlueprintValueEditorModel[] = []; + contacts: DmpContactEditorModel[] = []; + + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor( + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() + ) { } + + fromModel(item: DmpProperties, dmpReferences: DmpReference[], dmpBlueprint: DmpBlueprint): DmpPropertiesEditorModel { + + dmpBlueprint.definition.sections.forEach(section => { + section.fields.forEach(field => { + this.dmpBlueprintValues.push(new DmpBlueprintValueEditorModel().fromModel( + { + fieldId: field.id, + fieldValue: item?.dmpBlueprintValues?.find(x => x.fieldId == field.id)?.fieldValue + }, dmpReferences)); + }); + }); + // if (item?.dmpBlueprintValues) { item.dmpBlueprintValues.map(x => this.dmpBlueprintValues.push(new DmpBlueprintValueEditorModel().fromModel(x, dmpReferences))); } + if (item?.contacts) { item.contacts.map(x => this.contacts.push(new DmpContactEditorModel().fromModel(x))); } + + return this; + } + + buildForm(params?: { + context?: ValidationContext, + disabled?: boolean, + rootPath?: string + }): UntypedFormGroup { + let { context = null, disabled = false, rootPath } = params ?? {} + if (context == null) { + context = DmpPropertiesEditorModel.createValidationContext({ + validationErrorModel: this.validationErrorModel, + rootPath + }); + } + + const formGroup = this.formBuilder.group({ + contacts: this.formBuilder.array( + (this.contacts ?? []).map( + (item, index) => new DmpContactEditorModel( + this.validationErrorModel + ).fromModel(item).buildForm({ + rootPath: `contacts[${index}].` + }), context.getValidation('contacts') + ) + ), + + }); + + (this.dmpBlueprintValues ?? []).filter(x => x?.fieldId).map( + (item, index) => formGroup.addControl(item.fieldId.toString(), item.buildForm({ + rootPath: `dmpBlueprintValues[${index}].` + })), context.getValidation('dmpBlueprintValues') + ) + + return formGroup; + } + + static createValidationContext(params: { + rootPath?: string, + validationErrorModel: ValidationErrorModel + }): ValidationContext { + const { rootPath = '', validationErrorModel } = params; + + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + baseValidationArray.push({ key: 'dmpBlueprintValues', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}dmpBlueprintValues`)] }); + baseValidationArray.push({ key: 'contacts', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}contacts`)] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} + +export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { + fieldId: Guid; + fieldValue: string; + references: DmpReferencePersist[]; + + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor( + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() + ) { } + + fromModel(item: DmpBlueprintValue, dmpReferences: DmpReference[]): DmpBlueprintValueEditorModel { + this.fieldId = item.fieldId; + this.fieldValue = item.fieldValue; + this.references = dmpReferences.filter(x => x.data?.blueprintFieldId === this.fieldId); + + return this; + } + + buildForm(params?: { + context?: ValidationContext, + disabled?: boolean, + rootPath?: string + }): UntypedFormGroup { + let { context = null, disabled = false, rootPath } = params ?? {} + if (context == null) { + context = DmpBlueprintValueEditorModel.createValidationContext({ + validationErrorModel: this.validationErrorModel, + rootPath + }); + } + + return this.formBuilder.group({ + fieldId: [{ value: this.fieldId, disabled: disabled }, context.getValidation('fieldId').validators], + fieldValue: [{ value: this.fieldValue, disabled: disabled }, context.getValidation('fieldValue').validators], + references: [{ value: this.references, disabled: disabled }, context.getValidation('references').validators], + }); + } + + static createValidationContext(params: { + rootPath?: string, + validationErrorModel: ValidationErrorModel + }): ValidationContext { + const { rootPath = '', validationErrorModel } = params; + + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + baseValidationArray.push({ key: 'fieldId', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fieldId`)] }); + baseValidationArray.push({ key: 'fieldValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fieldValue`)] }); + baseValidationArray.push({ key: 'references', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} + +export class DmpContactEditorModel implements DmpContactPersist { + userId: Guid; + firstName: string; + lastName: string; + email: string; + + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor( + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() + ) { } + + fromModel(item: DmpContact): DmpContactEditorModel { + this.userId = item.userId; + this.firstName = item.firstName; + this.lastName = item.lastName; + this.email = item.email; + + return this; + } + + buildForm(params?: { + context?: ValidationContext, + disabled?: boolean, + rootPath?: string + }): UntypedFormGroup { + let { context = null, disabled = false, rootPath } = params ?? {} + if (context == null) { + context = DmpReferenceEditorModel.createValidationContext({ + validationErrorModel: this.validationErrorModel, + rootPath + }); + } + + return this.formBuilder.group({ + userId: [{ value: this.userId, disabled: disabled }, context.getValidation('userId').validators], + firstName: [{ value: this.firstName, disabled: disabled }, context.getValidation('firstName').validators], + lastName: [{ value: this.lastName, disabled: disabled }, context.getValidation('lastName').validators], + email: [{ value: this.email, disabled: disabled }, context.getValidation('email').validators], + }); + } + + static createValidationContext(params: { + rootPath?: string, + validationErrorModel: ValidationErrorModel + }): ValidationContext { + const { rootPath = '', validationErrorModel } = params; + + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + baseValidationArray.push({ key: 'userId', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}userId`)] }); + baseValidationArray.push({ key: 'firstName', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}firstName`)] }); + baseValidationArray.push({ key: 'lastName', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}lastName`)] }); + baseValidationArray.push({ key: 'email', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}email`)] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} + export class DmpReferenceEditorModel implements DmpReferencePersist { id: Guid; reference: ReferencePersist; - data: string; + referenceId: Guid; + data: DmpReferenceDataPersist; hash: string; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -203,7 +400,7 @@ export class DmpDescriptionTemplateEditorModel implements DmpDescriptionTemplate return this.formBuilder.group({ id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], - reference: [{ value: this.descriptionTemplateGroupId, disabled: disabled }, context.getValidation('descriptionTemplateGroupId').validators], + descriptionTemplateGroupId: [{ value: this.descriptionTemplateGroupId, disabled: disabled }, context.getValidation('descriptionTemplateGroupId').validators], sectionId: [{ value: this.sectionId, disabled: disabled }, context.getValidation('sectionId').validators], hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] }); diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts index caf122f54..fab72aad7 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts @@ -7,6 +7,7 @@ import { CommonUiModule } from '@common/ui/common-ui.module'; import { DmpEditorComponent } from './dmp-editor.component'; import { DmpEditorRoutingModule } from './dmp-editor.routing'; import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; +import { ReferenceFieldModule } from '@app/ui/reference/reference-field/reference-field.module'; @NgModule({ imports: [ @@ -16,7 +17,8 @@ import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.mod ConfirmationDialogModule, DmpEditorRoutingModule, RichTextEditorModule, - AutoCompleteModule + AutoCompleteModule, + ReferenceFieldModule ], declarations: [ DmpEditorComponent, diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts index 73072cee4..210fbe08d 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { Description } from '@app/core/model/description/description'; import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection, FieldInSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; -import { Dmp, DmpDescriptionTemplate } from '@app/core/model/dmp/dmp'; +import { Dmp, DmpBlueprintValue, DmpContact, DmpDescriptionTemplate, DmpProperties } from '@app/core/model/dmp/dmp'; import { DmpReference } from '@app/core/model/dmp/dmp-reference'; import { Reference } from '@app/core/model/reference/reference'; import { DmpService } from '@app/core/services/dmp/dmp.service'; @@ -33,6 +33,14 @@ export class DmpEditorResolver extends BaseEditorResolver { nameof(x => x.version), nameof(x => x.updatedAt), + [nameof(x => x.properties), nameof(x => x.dmpBlueprintValues), nameof(x => x.fieldId)].join('.'), + [nameof(x => x.properties), nameof(x => x.dmpBlueprintValues), nameof(x => x.fieldValue)].join('.'), + [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.userId)].join('.'), + [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.firstName)].join('.'), + [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.lastName)].join('.'), + [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.email)].join('.'), + + // [nameof(x => x.entityDois), nameof(x => x.id)].join('.'), // [nameof(x => x.entityDois), nameof(x => x.repositoryId)].join('.'), // [nameof(x => x.entityDois), nameof(x => x.doi)].join('.'), @@ -55,6 +63,10 @@ export class DmpEditorResolver extends BaseEditorResolver { [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.reference)].join('.'), + [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.sectionId)].join('.'), + [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), + + // nameof(x => x.id), // nameof(x => x.label), // nameof(x => x.status), @@ -67,23 +79,23 @@ export class DmpEditorResolver extends BaseEditorResolver { public static blueprintLookupFields(prefix?: string): string[] { return [ - prefix ? prefix + '.' : '' + [nameof(x => x.id)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.id)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.label)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.ordinal)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.hasTemplates)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.id)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.descriptionTemplateId)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.id)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.category)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.dataType)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.systemFieldType)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.label)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.placeholder)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.description)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.required)].join('.'), - prefix ? prefix + '.' : '' + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.ordinal)].join('.') + (prefix ? prefix + '.' : '') + [nameof(x => x.id)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.id)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.label)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.ordinal)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.hasTemplates)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.id)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.descriptionTemplateId)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.id)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.category)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.dataType)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.systemFieldType)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.label)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.placeholder)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.description)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.required)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.ordinal)].join('.') ] } diff --git a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html new file mode 100644 index 000000000..20af9eedf --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html @@ -0,0 +1,20 @@ +
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.scss b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.scss new file mode 100644 index 000000000..c916223d1 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.scss @@ -0,0 +1,7 @@ +.inapp-notification-editor { + padding-top: 1em; + + .editor-actions { + margin-top: 30px; + } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.ts b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.ts new file mode 100644 index 000000000..66b1483fd --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.ts @@ -0,0 +1,132 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, ParamMap, Router } from '@angular/router'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { LoggingService } from '@app/core/services/logging/logging-service'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { map, takeUntil } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model'; +import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum'; + +@Component({ + selector: 'app-inapp-notification-editor', + templateUrl: './inapp-notification-editor.component.html', + styleUrls: ['./inapp-notification-editor.component.scss'] +}) +export class InAppNotificationEditorComponent extends BaseComponent implements OnInit { + + isDeleted = false; + isRead = false; + isNew = false; + isFromDialog = false; + inappNotification: InAppNotification; + + constructor( + public authService: AuthService, + private dialog: MatDialog, + private inappNotificationService: InAppNotificationService, + private route: ActivatedRoute, + private router: Router, + private language: TranslateService, + public enumUtils: EnumUtils, + private formService: FormService, + private uiNotificationService: UiNotificationService, + private logger: LoggingService, + private httpErrorHandlingService: HttpErrorHandlingService + ) { + super(); + } + + ngOnInit(): void { + this.route.paramMap.pipe(takeUntil(this._destroyed)).subscribe((paramMap: ParamMap) => { + const itemId = paramMap.get('id'); + this.isFromDialog = this.route.snapshot.data ? this.route.snapshot.data['isFromDialog'] as boolean : false; + + if (itemId != null) { + this.inappNotificationService.getSingle(Guid.parse(itemId), + [ + nameof(x => x.id), + nameof(x => x.subject), + nameof(x => x.body), + nameof(x => x.type), + nameof(x => x.trackingState), + nameof(x => x.isActive), + nameof(x => x.hash), + nameof(x => x.updatedAt) + ]) + .pipe(map(data => data as InAppNotification), takeUntil(this._destroyed)) + .subscribe( + data => { + this.inappNotification = data; + this.isDeleted = this.inappNotification.isActive === IsActive.Inactive; + this.isRead = this.inappNotification.trackingState === NotificationInAppTracking.Delivered; + + if(!this.isDeleted && !this.isRead) this.markAsRead() + }, + error => this.onCallbackError(error) + ); + } else { + this.inappNotification = null; + } + }); + } + + public markAsRead() { + const value = this.inappNotification; + this.inappNotificationService.read(value.id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + // this.clearErrorModel(); + } + + public delete() { + const value = this.inappNotification; + if (value.id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + restoreFocus: false, + data: { + message: this.language.instant('COMMONS.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.inappNotificationService.delete(value.id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + public cancel(): void { + this.router.navigate(['/mine-notifications']); + } + + onCallbackSuccess(data?: any): void { + // this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); + // this.router.navigate(['/mine-notifications']); + } + + onCallbackError(errorResponse: HttpErrorResponse) { + const error: HttpError = this.httpErrorHandlingService.getError(errorResponse); + this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning); + } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html new file mode 100644 index 000000000..cd85d6d66 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html @@ -0,0 +1,17 @@ + + + drafts + mail + {{ inappNotification.subject }} + {{ inappNotification.createdAt | date : 'short'}} + + + + {{'NAV-BAR.INAPP-NOTIFICATIONS' + | translate}} + + + {{'NAV-BAR.READ-ALL-INAPP-NOTIFICATIONS' + | translate}} + + diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.scss new file mode 100644 index 000000000..7cbca544f --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.scss @@ -0,0 +1,15 @@ +.inapp-notification-listing-dialog { + padding-top: 0em; + + .unread{ + font-weight:bold + } + + .secondary-text { + color: rgba(0, 0, 0, 0.54); + } + + .mat-list-item-content { + text-align: center + } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.ts new file mode 100644 index 000000000..ee2a1a835 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.ts @@ -0,0 +1,98 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { Router } from '@angular/router'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { BaseComponent } from '@common/base/base.component'; +import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum'; +import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model'; +import { InAppNotificationLookup } from '@app/core/query/inapp-notification.lookup'; +import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service'; +import { takeUntil } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; + +@Component({ + selector: 'app-mine-inapp-notification-listing-dialog', + templateUrl: './mine-inapp-notification-listing-dialog.component.html', + styleUrls: ['./mine-inapp-notification-listing-dialog.component.scss'] +}) +export class MineInAppNotificationListingDialogComponent extends BaseComponent implements OnInit { + public inappNotifications = new Array(); + public notificationInAppTrackingEnum = NotificationInAppTracking; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public dialogData: any, + private inappNotificationService: InAppNotificationService, + private router: Router, + private uiNotificationService: UiNotificationService, + private httpErrorHandlingService: HttpErrorHandlingService, + public authService: AuthService, + ) { + super(); + } + + ngOnInit() { + const lookup = new InAppNotificationLookup(); + lookup.project = { + fields: [ + nameof(x => x.id), + nameof(x => x.subject), + nameof(x => x.createdAt), + nameof(x => x.trackingState), + ] + }; + lookup.page = { offset: 0, size: 10 }; + lookup.order = { items: ['-' + nameof(x => x.createdAt)] }; + lookup.isActive = [IsActive.Active]; + this.inappNotificationService.query(lookup) + .pipe(takeUntil(this._destroyed)) + .subscribe( + data => { + this.inappNotifications = data.items; + }, + error => this.onCallbackError(error), + ); + } + + private onCallbackError(errorResponse: HttpErrorResponse) { + const error: HttpError = this.httpErrorHandlingService.getError(errorResponse); + this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning); + } + + goToNotification(item: InAppNotification) { + if (item.trackingState === NotificationInAppTracking.Stored) { + this.inappNotificationService.read(item.id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + data => { + this.dialogRef.close(); + this.router.navigate(['/mine-notifications/dialog/' + item.id]); + }, + error => { + this.dialogRef.close(); + this.router.navigate(['/mine-notifications/dialog/' + item.id]); + }, + ); + } else { + this.dialogRef.close(); + this.router.navigate(['/mine-notifications/dialog/' + item.id]); + } + } + + goToNotifications() { + this.router.navigate(['/mine-notifications']); + this.dialogRef.close(); + } + + readAllNotifications() { + this.inappNotificationService.readAll() + .pipe(takeUntil(this._destroyed)) + .subscribe( + data => {}, + ); + } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.html new file mode 100644 index 000000000..0185cfa77 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.html @@ -0,0 +1,47 @@ +
+ + + + + +
+
+
+

{{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.TITLE' | translate}}

+ +
+ +
+ {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.NOTIFICATION-TYPE' | translate}} + + {{enumUtils.toNotificationTypeString(type)}} + + +
+
+ {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.TRACKING-STATE' | translate}} + + {{enumUtils.toNotificationInAppTrackingString(state)}} + + +
+ +
+ + +
+
+
+
+ + +
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.scss new file mode 100644 index 000000000..3e65f7c04 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.scss @@ -0,0 +1,20 @@ + +::ng-deep.mat-mdc-menu-panel { + max-width: 100% !important; + height: 100% !important; +} + +:host::ng-deep.mat-mdc-menu-content:not(:empty) { + padding-top: 0 !important; +} + + +.filter-button{ + padding-top: .6rem; + padding-bottom: .6rem; + // .mat-icon{ + // font-size: 1.5em; + // width: 1.2em; + // height: 1.2em; + // } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.ts new file mode 100644 index 000000000..9f5fc4f3b --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.ts @@ -0,0 +1,99 @@ +import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges, OnChanges } from '@angular/core'; +import { BaseComponent } from '@common/base/base.component'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { InAppNotificationFilter } from '@app/core/query/inapp-notification.lookup'; +import { nameof } from 'ts-simple-nameof'; +import { NotificationType } from '@app/core/common/enum/notification-type'; +@Component({ + selector: 'app-mine-inapp-notification-listing-filters', + templateUrl: './mine-inapp-notification-listing-filters.component.html', + styleUrls: ['./mine-inapp-notification-listing-filters.component.scss'] +}) +export class MineInAppNotificationListingFiltersComponent extends BaseComponent implements OnInit, OnChanges { + + @Input() readonly filter: InAppNotificationFilter; + @Output() filterChange = new EventEmitter(); + + notificationInAppTrackingEnumValues = this.enumUtils.getEnumValues(NotificationInAppTracking); + notificationTypeEnumValues = this.enumUtils.getEnumValues(NotificationType); + + // * State + internalFilters: InAppNotificationListingFilters = this._getEmptyFilters(); + + protected appliedFilterCount: number = 0; + constructor( + public enumUtils: EnumUtils, + ) { super(); } + + ngOnInit() { + } + + ngOnChanges(changes: SimpleChanges): void { + const filterChange = changes[nameof(x => x.filter)]?.currentValue as InAppNotificationFilter; + if (filterChange) { + this.updateFilters() + } + } + + + onSearchTermChange(searchTerm: string): void { + this.applyFilters() + } + + + protected updateFilters(): void { + this.internalFilters = this._parseToInternalFilters(this.filter); + this.appliedFilterCount = this._computeAppliedFilters(this.internalFilters); + } + + protected applyFilters(): void { + const { like, trackingState, type } = this.internalFilters ?? {} + this.filterChange.emit({ + ...this.filter, + like, + trackingState, + type + }) + } + + + private _parseToInternalFilters(inputFilter: InAppNotificationFilter): InAppNotificationListingFilters { + if (!inputFilter) { + return this._getEmptyFilters(); + } + + let { like, trackingState, type } = inputFilter; + + return { + like: like, + trackingState: trackingState, + type: type + } + + } + + private _getEmptyFilters(): InAppNotificationListingFilters { + return { + like: null, + trackingState: null, + type: null + } + } + + private _computeAppliedFilters(filters: InAppNotificationListingFilters): number { + let count = 0; + return count; + } + + clearFilters() { + this.internalFilters = this._getEmptyFilters(); + } +} + +interface InAppNotificationListingFilters { + like: string; + trackingState: NotificationInAppTracking[]; + type: NotificationType[]; +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.html new file mode 100644 index 000000000..6cd3006ed --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.html @@ -0,0 +1,100 @@ +
+
+ +
+
+

{{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.TITLE' | translate}}

+ + +
+
+ + + + + + + + +
+
+ + + + +
+
+ + + + drafts + mail + + +
+
+ + + + {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT' | translate}}: + + {{item?.subject | nullifyValue}} + + +
+
+ + + + {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.NOTIFICATION-TYPE' | translate}}: + + {{enumUtils.toNotificationTypeString(item.type) | nullifyValue}} + + +
+
+ + + + {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT' | translate}}: + + {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + + +
+
+
+
+
+ + +
+
+ + + + +
+
+
+ + +
+
+ drafts + mail +
+
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.scss new file mode 100644 index 000000000..977565d41 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.scss @@ -0,0 +1,61 @@ +.inapp-notification-listing { + margin-top: 1.3rem; + margin-left: 1rem; + margin-right: 2rem; + + .mat-header-row{ + background: #f3f5f8; + } + .mat-card { + margin: 16px 0; + padding: 0px; + } + + .mat-row { + cursor: pointer; + min-height: 4.5em; + } + + mat-row:hover { + background-color: #eef5f6; + } + .mat-fab-bottom-right { + float: right; + z-index: 5; + } + } + .create-btn { + border-radius: 30px; + background-color: var(--secondary-color); + padding-left: 2em; + padding-right: 2em; + // color: #000; + + .button-text{ + display: inline-block; + } + } + + .dlt-btn { + color: rgba(0, 0, 0, 0.54); + } + + .status-chip{ + + border-radius: 20px; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.2em; + font-size: .8em; + } + + .status-chip-finalized{ + color: #568b5a; + background: #9dd1a1 0% 0% no-repeat padding-box; + } + + .status-chip-draft{ + color: #00c4ff; + background: #d3f5ff 0% 0% no-repeat padding-box; + } + \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.ts new file mode 100644 index 000000000..2029435db --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.ts @@ -0,0 +1,175 @@ +import { Component, OnInit, TemplateRef, ViewChild, EventEmitter, Output, Input } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; +import { BaseListingComponent } from '@common/base/base-listing-component'; +import { PipeService } from '@common/formatting/pipe.service'; +import { DataTableDateTimeFormatPipe } from '@common/formatting/pipes/date-time-format.pipe'; +import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { ColumnDefinition, ColumnsChangedEvent, HybridListingComponent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model'; +import { InAppNotificationLookup } from '@app/core/query/inapp-notification.lookup'; +import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { nameof } from 'ts-simple-nameof'; +import { Observable } from 'rxjs'; +import { QueryResult } from '@common/model/query-result'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { TranslateService } from '@ngx-translate/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Guid } from '@common/types/guid'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { takeUntil } from 'rxjs/operators'; +import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum'; +import { NotificationTypePipe } from '@common/formatting/pipes/notification-type.pipe'; + +@Component({ + selector: 'app-mine-inapp-notification-listing', + templateUrl: './mine-inapp-notification-listing.component.html', + styleUrls: ['./mine-inapp-notification-listing.component.scss'] +}) +export class MineInAppNotificationListingComponent extends BaseListingComponent implements OnInit { + publish = false; + userSettingsKey = { key: 'InAppNotificationListingUserSettings' }; + propertiesAvailableForOrder: ColumnDefinition[]; + notificationInAppTracking= NotificationInAppTracking; + + @ViewChild('actions', { static: true }) actions?: TemplateRef; + @ViewChild('state', { static: true }) state?: TemplateRef; + @ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent; + + private readonly lookupFields: string[] = [ + nameof(x => x.id), + nameof(x => x.subject), + nameof(x => x.type), + nameof(x => x.trackingState), + nameof(x => x.createdAt), + nameof(x => x.isActive) + ]; + + rowIdentity = x => x.id; + + constructor( + protected router: Router, + protected route: ActivatedRoute, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected queryParamsService: QueryParamsService, + private inAppNotificationService: InAppNotificationService, + public authService: AuthService, + private pipeService: PipeService, + public enumUtils: EnumUtils, + private language: TranslateService, + private dialog: MatDialog + ) { + super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService); + // Lookup setup + // Default lookup values are defined in the user settings class. + this.lookup = this.initializeLookup(); + } + + ngOnInit() { + super.ngOnInit(); + } + + protected initializeLookup(): InAppNotificationLookup { + const lookup = new InAppNotificationLookup(); + lookup.metadata = { countAll: true }; + lookup.page = { offset: 0, size: this.ITEMS_PER_PAGE }; + lookup.isActive = [IsActive.Active]; + lookup.order = { items: [this.toDescSortField(nameof(x => x.createdAt))] }; + this.updateOrderUiFields(lookup.order); + + lookup.project = { + fields: this.lookupFields + }; + + return lookup; + } + + protected setupColumns() { + this.gridColumns.push(...[{ + prop: nameof(x => x.trackingState), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.TRACKING-STATE', + cellTemplate: this.state, + maxWidth: 100 + }, + { + prop: nameof(x => x.subject), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT' + }, + { + prop: nameof(x => x.type), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.NOTIFICATION-TYPE', + pipe: this.pipeService.getPipe(NotificationTypePipe) + }, + { + prop: nameof(x => x.createdAt), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + alwaysShown: true, + cellTemplate: this.actions, + maxWidth: 120 + } + ]); + this.propertiesAvailableForOrder = this.gridColumns.filter(x => x.sortable); + } + + // + // Listing Component functions + // + onColumnsChanged(event: ColumnsChangedEvent) { + super.onColumnsChanged(event); + this.onColumnsChangedInternal(event.properties.map(x => x.toString())); + } + + private onColumnsChangedInternal(columns: string[]) { + // Here are defined the projection fields that always requested from the api. + const fields = new Set(this.lookupFields); + this.gridColumns.map(x => x.prop) + .filter(x => !columns?.includes(x as string)) + .forEach(item => { + fields.delete(item as string) + }); + this.lookup.project = { fields: [...fields] }; + this.onPageLoad({ offset: 0 } as PageLoadEvent); + } + + protected loadListing(): Observable> { + return this.inAppNotificationService.query(this.lookup); + } + + public deleteType(id: Guid) { + if (id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { + isDeleteConfirmation: true, + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.inAppNotificationService.delete(id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success); + this.ngOnInit(); + } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification-routing.module.ts b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification-routing.module.ts new file mode 100644 index 000000000..26530a7e4 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification-routing.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '@app/core/auth-guard.service'; +import { MineInAppNotificationListingComponent } from './listing/mine-inapp-notification-listing.component'; +import { InAppNotificationEditorComponent } from './editor/inapp-notification-editor.component'; + +const routes: Routes = [ + { + path: '', + component: MineInAppNotificationListingComponent, + data: { + }, + canActivate: [AuthGuard] + }, + { + path: 'dialog/:id', + canActivate: [AuthGuard], + data: { + isFromDialog: true, + }, + component: InAppNotificationEditorComponent + }, + { + path: ':id', + canActivate: [AuthGuard], + component: InAppNotificationEditorComponent + }, + { path: '**', loadChildren: () => import('@common/modules/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule) }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class MineInAppNotificationRoutingModule { } diff --git a/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification.module.ts b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification.module.ts new file mode 100644 index 000000000..30e48d718 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification.module.ts @@ -0,0 +1,36 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { TextFilterModule } from '@common/modules/text-filter/text-filter.module'; +import { UserSettingsModule } from '@common/modules/user-settings/user-settings.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { MineInAppNotificationRoutingModule } from './mine-inapp-notification-routing.module'; +import { MineInAppNotificationListingComponent } from './listing/mine-inapp-notification-listing.component'; +import { HybridListingModule } from '@common/modules/hybrid-listing/hybrid-listing.module'; +import { InAppNotificationEditorComponent } from './editor/inapp-notification-editor.component'; +import { MineInAppNotificationListingFiltersComponent } from './listing/filters/mine-inapp-notification-listing-filters.component'; +import { MineInAppNotificationListingDialogComponent } from './listing-dialog/mine-inapp-notification-listing-dialog.component'; +import { CommonFormattingModule } from '@common/formatting/common-formatting.module'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + ConfirmationDialogModule, + HybridListingModule, + TextFilterModule, + MineInAppNotificationRoutingModule, + UserSettingsModule, + CommonFormattingModule + ], + declarations: [ + MineInAppNotificationListingComponent, + InAppNotificationEditorComponent, + MineInAppNotificationListingFiltersComponent, + MineInAppNotificationListingDialogComponent + ], + exports: [ + MineInAppNotificationListingComponent, + ] +}) +export class MineInAppNotificationModule { } diff --git a/dmp-frontend/src/app/ui/navbar/navbar.component.html b/dmp-frontend/src/app/ui/navbar/navbar.component.html index d2023d286..56a9a3957 100644 --- a/dmp-frontend/src/app/ui/navbar/navbar.component.html +++ b/dmp-frontend/src/app/ui/navbar/navbar.component.html @@ -32,6 +32,11 @@
+
+ +
diff --git a/dmp-frontend/src/app/ui/navbar/navbar.component.ts b/dmp-frontend/src/app/ui/navbar/navbar.component.ts index d46499f7d..0431fdf2d 100644 --- a/dmp-frontend/src/app/ui/navbar/navbar.component.ts +++ b/dmp-frontend/src/app/ui/navbar/navbar.component.ts @@ -1,6 +1,6 @@ import { Location } from '@angular/common'; import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { MatMenuTrigger } from '@angular/material/menu'; import { Router } from '@angular/router'; import { AppRole } from '@app/core/common/enum/app-role'; @@ -16,6 +16,10 @@ import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/st import { FaqDialogComponent } from '../faq/dialog/faq-dialog.component'; import { UserDialogComponent } from './user-dialog/user-dialog.component'; import { DATASETS_ROUTES, DMP_ROUTES, GENERAL_ROUTES } from '../sidebar/sidebar.component'; +import { MineInAppNotificationListingDialogComponent } from '../inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component'; +import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service'; +import { timer } from 'rxjs'; +import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; @Component({ selector: 'app-navbar', @@ -33,18 +37,22 @@ export class NavbarComponent extends BaseComponent implements OnInit { currentRoute: string; selectedLanguage: string; private user: User; + inAppNotificationDialog: MatDialogRef = null; + inAppNotificationCount = 0; @Output() sidebarToggled: EventEmitter = new EventEmitter(); @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger; constructor(location: Location, private element: ElementRef, private router: Router, - private authentication: AuthService, + public authentication: AuthService, private dialog: MatDialog, private progressIndicationService: ProgressIndicationService, private languageService: LanguageService, private matomoService: MatomoService, private sidenavService: SideNavService, + private inappNotificationService: InAppNotificationService, + private configurationService: ConfigurationService ) { super(); this.location = location; @@ -75,6 +83,23 @@ export class NavbarComponent extends BaseComponent implements OnInit { this.progressIndicationService.getProgressIndicationObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { setTimeout(() => { this.progressIndication = x; }); }); + timer(2000, this.configurationService.inAppNotificationsCountInterval * 1000) + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.countUnreadInappNotifications(); + }); + } + + private countUnreadInappNotifications() { + if (this.isAuthenticated()) { + this.inappNotificationService.countUnread() + .pipe(takeUntil(this._destroyed)) + .subscribe( + data => { + this.inAppNotificationCount = data; + }, + ); + } } public isAuthenticated(): boolean { @@ -273,4 +298,21 @@ export class NavbarComponent extends BaseComponent implements OnInit { this.router.navigate(['/logout']); } + toggleInAppNotifications() { + if (this.inAppNotificationDialog != null) { + this.inAppNotificationDialog.close(); + } else { + this.countUnreadInappNotifications(); + this.inAppNotificationDialog = this.dialog.open(MineInAppNotificationListingDialogComponent, { + position: { + top: '64px', right: '0px' + } + }); + this.inAppNotificationDialog.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + this.countUnreadInappNotifications(); + this.inAppNotificationDialog = null; + }); + } + } + } diff --git a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.html b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.html index 58f36952a..901107a2d 100644 --- a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.html +++ b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.html @@ -1,495 +1,11 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + {{'REFERENCE-FIELD.PLACEHOLDER' | translate}} {{enumUtils.toReferenceTypeString(referenceType)}} + + + {{form.getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ {{'REFERENCE-FIELD.COULD-NOT-FIND-MESSAGE' | translate}} + {{'REFERENCE-FIELD.ACTIONS.INSERT-MANUALLY' | translate}} +
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.scss b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.scss index 5221d29c7..3b3d40edc 100644 --- a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.scss +++ b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.scss @@ -1,35 +1,14 @@ -.dataset-external-references-editor { - .heading { - text-align: left; - font-weight: 700; - font-size: 18px; - letter-spacing: 0px; - color: #212121; - opacity: 0.81; - margin-top: 1.625rem; - margin-bottom: 0.625rem; - } + .insert-manually { + text-decoration: underline; + color: var(--primary-color-3); + cursor: pointer; + font-size: 1rem; + font-weight: 400; + } - .hint { - text-align: left; - font-weight: 400; - font-size: 16px; - letter-spacing: 0px; - color: #212121; - opacity: 0.81; - margin-bottom: 2.125rem; - } - - .external-item-card { - margin-bottom: 1em; - } -} - -::ng-deep .tags-form .mat-form-field-appearance-outline .mat-form-field-outline { - background: #fafafa !important; -} - -::ng-deep .tags-form .mat-form-field-appearance-outline .mat-form-field-infix { - font-size: 1rem; - padding: 0.6em 0 1em 0 !important; -} + .not-found { + // cursor: pointer; + font-size: 1rem; + font-weight: 400; + padding: 0rem 0.5rem 0rem 0rem; + } diff --git a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts index 248433f89..e1df7fc62 100644 --- a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts +++ b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts @@ -1,36 +1,10 @@ -import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; -import { UntypedFormArray, UntypedFormGroup } from '@angular/forms'; -import { MatDialog } from '@angular/material/dialog'; -import { Router } from '@angular/router'; -import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; -import { ExternalSourcesConfiguration } from '@app/core/model/external-sources/external-sources-configuration'; -import { DataRepositoryCriteria } from '@app/core/query/data-repository/data-repository-criteria'; -import { ExternalDatasetCriteria } from '@app/core/query/external-dataset/external-dataset-criteria'; -import { RegistryCriteria } from '@app/core/query/registry/registry-criteria'; -import { RequestItem } from '@app/core/query/request-item'; -import { ServiceCriteria } from '@app/core/query/service/service-criteria'; -import { TagCriteria } from '@app/core/query/tag/tag-criteria'; -import { ExternalSourcesConfigurationService } from '@app/core/services/external-sources/external-sources-configuration.service'; -import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; -import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; -import { ExternalDataRepositoryEditorModel, ExternalDatasetEditorModel, ExternalRegistryEditorModel, ExternalServiceEditorModel, ExternalTagEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model'; -import { DatasetExternalDataRepositoryDialogEditorComponent } from '@app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component'; -import { DatasetExternalDatasetDialogEditorComponent } from '@app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component'; -import { DatasetExternalRegistryDialogEditorComponent } from '@app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component'; -import { DatasetExternalServiceDialogEditorComponent } from '@app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component'; -import { BaseComponent } from '@common/base/base.component'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil, map } from 'rxjs/operators'; -import { ENTER, COMMA } from '@angular/cdk/keycodes'; -import { MatChipInputEvent } from '@angular/material/chips'; -import { isNullOrUndefined } from '@app/utilities/enhancers/utils'; -import { ExternalDataRepositoryService } from '@app/core/services/external-sources/data-repository/extternal-data-repository.service'; -import { ExternalDatasetService } from '@app/core/services/external-sources/dataset/external-dataset.service'; -import { ExternalRegistryService } from '@app/core/services/external-sources/registry/external-registry.service'; -import { ExternalServiceService } from '@app/core/services/external-sources/service/external-service.service'; -import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { Component, Input, OnInit } from '@angular/core'; +import { UntypedFormGroup } from '@angular/forms'; import { ReferenceType } from '@app/core/common/enum/reference-type'; +import { ReferenceService } from '@app/core/services/reference/reference.service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; @Component({ selector: 'app-reference-field-component', @@ -42,7 +16,9 @@ export class ReferenceFieldComponent extends BaseComponent implements OnInit { @Input() referenceType: ReferenceType = null; @Input() form: UntypedFormGroup = null; - referenceTypeEnum = ReferenceType; + multipleAutoCompleteSearchConfiguration: MultipleAutoCompleteConfiguration; + // referenceTypeEnum = ReferenceType; + // @Input() viewOnly = false; // @Output() formChanged: EventEmitter = new EventEmitter(); @@ -104,31 +80,34 @@ export class ReferenceFieldComponent extends BaseComponent implements OnInit { // private externalDataRepositoryService: ExternalDataRepositoryService, // private externalDatasetService: ExternalDatasetService, // private externalRegistryService: ExternalRegistryService, - // private externalServiceService: ExternalServiceService, + private referenceService: ReferenceService, + public enumUtils: EnumUtils, ) { super(); } ngOnInit() { + this.multipleAutoCompleteSearchConfiguration = this.referenceService.getMultipleAutoCompleteSearchConfiguration(this.referenceType); - // this.externalSourcesConfigurationService.getExternalSourcesConfiguration() - // .pipe(takeUntil(this._destroyed)) - // .subscribe(result => { - // this.externalSourcesConfiguration = result; - // this.externalSourcesConfiguration.dataRepositories.push({ key: '', label: 'All' }); - // this.externalSourcesConfiguration.externalDatasets.push({ key: '', label: 'All' }); - // this.externalSourcesConfiguration.registries.push({ key: '', label: 'All' }); - // this.externalSourcesConfiguration.services.push({ key: '', label: 'All' }); - // if (!isNullOrUndefined(this.externalSourcesConfiguration.tags)) { - // this.externalSourcesConfiguration.tags.push({ key: '', label: 'All' }); - // } else { - // this.externalSourcesConfiguration.tags = [{ key: '', label: 'All' }]; - // } - // }); - // this.formGroup.valueChanges - // .pipe(takeUntil(this._destroyed)) - // .subscribe(val => { - // this.formChanged.emit(val); - // }); + // this.externalSourcesConfigurationService.getExternalSourcesConfiguration() + // .pipe(takeUntil(this._destroyed)) + // .subscribe(result => { + // this.externalSourcesConfiguration = result; + // this.externalSourcesConfiguration.dataRepositories.push({ key: '', label: 'All' }); + // this.externalSourcesConfiguration.externalDatasets.push({ key: '', label: 'All' }); + // this.externalSourcesConfiguration.registries.push({ key: '', label: 'All' }); + // this.externalSourcesConfiguration.services.push({ key: '', label: 'All' }); + // if (!isNullOrUndefined(this.externalSourcesConfiguration.tags)) { + // this.externalSourcesConfiguration.tags.push({ key: '', label: 'All' }); + // } else { + // this.externalSourcesConfiguration.tags = [{ key: '', label: 'All' }]; + // } + // }); + + // this.formGroup.valueChanges + // .pipe(takeUntil(this._destroyed)) + // .subscribe(val => { + // this.formChanged.emit(val); + // }); } // public cancel(): void { diff --git a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.module.ts b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.module.ts index 699af2811..96caafc21 100644 --- a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.module.ts +++ b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.module.ts @@ -1,8 +1,10 @@ import { NgModule } from '@angular/core'; import { FormattingModule } from '@app/core/formatting.module'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; import { DescriptionRoutingModule } from '@app/ui/description/description.routing'; import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; +import { ReferenceFieldComponent } from './reference-field.component'; @NgModule({ imports: [ @@ -10,10 +12,13 @@ import { CommonUiModule } from '@common/ui/common-ui.module'; CommonFormsModule, FormattingModule, DescriptionRoutingModule, + AutoCompleteModule ], declarations: [ + ReferenceFieldComponent ], exports: [ + ReferenceFieldComponent ] }) export class ReferenceFieldModule { } diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts index 76c6c70f6..6dbf6d10c 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts @@ -58,6 +58,7 @@ export const ADMIN_ROUTES: RouteInfo[] = [ { path: '/languages', title: 'SIDE-BAR.LANGUAGES', icon: 'language' }, { path: '/supportive-material', title: 'SIDE-BAR.SUPPORTIVE-MATERIAL', icon: 'dataset_linked' }, { path: '/notification-templates', title: 'SIDE-BAR.NOTIFICATION-TEMPLATES', icon: 'build'}, + { path: '/notifications', title: 'SIDE-BAR.NOTIFICATIONS', icon: 'build'}, { path: '/index-managment', title: 'SIDE-BAR.MAINTENANCE', icon: 'build'} ]; diff --git a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html index fc2b9ae43..82e7ea6c5 100644 --- a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html +++ b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html @@ -11,8 +11,8 @@ {{enumUtils.toSupportiveMaterialTypeString(type)}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('type').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -23,8 +23,8 @@ {{languageCode}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('languageCode').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -50,6 +50,8 @@ alignleft aligncenter alignright alignjustify | \ bullist numlist outdent indent | code codesample | searchreplace | preview | removeformat | help' }" [formControl]="formGroup.get('payload')"> + {{formGroup.get('payload').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index 5f6f4c949..b23aa9b8e 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -15,10 +15,11 @@ "flow": "standard", "clientId": null, "silentCheckSsoRedirectUri": "http://localhost:4200/assets/silent-check-sso.html", - "scope": "openid profile email address phone dmp_web", + "scope": "openid profile email address phone dmp_web dmp_notification identity_provider", "clientSecret": null, "grantType": "code" }, + "inAppNotificationsCountInterval": "30", "notification_service": { "enabled": true, "address": "http://localhost:8086/api/" diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 4699bf8e6..a6eae7118 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -254,7 +254,9 @@ "LANGUAGES": "Languages", "NEW-LANGUAGE": "New", "EDIT-LANGUAGE": "Edit", - "NOTIFICATION-TEMPLATES": "Notification Templates" + "NOTIFICATION-TEMPLATES": "Notification Templates", + "INAPP-NOTIFICATIONS":"Notifications", + "NOTIFICATIONS": "Notifications" }, "COOKIE": { "MESSAGE": "This website uses cookies to enhance the user experience.", @@ -314,7 +316,9 @@ "DMP": "DMP", "GRANT": "Grant", "PUBLISHED": "Published" - } + }, + "INAPP-NOTIFICATIONS": "All Notifications", + "READ-ALL-INAPP-NOTIFICATIONS": "Read All" }, "SIDE-BAR": { "GENERAL": "GENERAL", @@ -354,7 +358,8 @@ "REFERENCES": "References", "LANGUAGES": "Languages", "MAINTENANCE": "Maintenance", - "NOTIFICATION-TEMPLATES": "Notification Templates" + "NOTIFICATION-TEMPLATES": "Notification Templates", + "NOTIFICATIONS":"Notifications" }, "DESCRIPTION-TEMPLATE-EDITOR": { "TITLE": { @@ -1249,37 +1254,6 @@ "SUCCESSFUL-DELETE": "Successful Delete", "UNSUCCESSFUL-DELETE": "This item could not be deleted." }, - "NOTIFICATION-TEMPLATE-LISTING": { - "TITLE": "Notification Templates", - "CREATE": "Create Notification Template", - "FIELDS": { - "LANGUAGE": "Language", - "KIND": "Kind", - "CHANNEL": "Channel", - "UPDATED-AT": "Updated", - "CREATED-AT": "Created", - "IS-ACTIVE": "Is Active" - }, - "FILTER": { - "TITLE": "Filters", - "IS-ACTIVE": "Is Active", - "KIND": "Kind", - "CHANNEL": "Channel", - "CANCEL": "Cancel", - "APPLY-FILTERS": "Apply filters" - }, - "CONFIRM-DELETE-DIALOG": { - "MESSAGE": "Would you like to delete this Notification Template?", - "CONFIRM-BUTTON": "Yes, delete", - "CANCEL-BUTTON": "No" - }, - "ACTIONS": { - "DELETE": "Delete", - "EDIT": "Edit" - }, - "SUCCESSFUL-DELETE": "Successful Delete", - "UNSUCCESSFUL-DELETE": "This item could not be deleted." - }, "SUPPORTIVE-MATERIAL-EDITOR": { "TITLE": "Supportive Material", "FIELDS": { @@ -1328,6 +1302,76 @@ } }, "NOTIFICATION-SERVICE": { + "INAPP-NOTIFICATION-LISTING": { + "TITLE": "Notifications", + "FIELDS": { + "SUBJECT": "Subject", + "TRACKING-STATE": "State", + "NOTIFICATION-TYPE":"Type", + "CREATED-AT": "Created" + }, + "FILTER": { + "TITLE": "Filters", + "TRACKING-STATE":"State", + "NOTIFICATION-TYPE":"Type", + "IS-ACTIVE": "Is Active", + "CANCEL": "Cancel", + "APPLY-FILTERS": "Apply filters" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Notification Template?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + }, + "ACTIONS": { + "DELETE": "Delete", + "EDIT": "Edit" + }, + "SUCCESSFUL-DELETE": "Successful Delete", + "UNSUCCESSFUL-DELETE": "This item could not be deleted." + }, + "INAPP-NOTIFICATION-EDITOR": { + "FIELDS": { + + }, + "ACTIONS": { + "CANCEL": "Cancel", + "DELETE": "Delete" + } + }, + "NOTIFICATION-TEMPLATE-LISTING": { + "TITLE": "Notification Templates", + "CREATE": "Create Notification Template", + "FIELDS": { + "NOTIFICATION-TYPE": "Type", + "LANGUAGE": "Language", + "KIND": "Kind", + "CHANNEL": "Channel", + "UPDATED-AT": "Updated", + "CREATED-AT": "Created", + "IS-ACTIVE": "Is Active" + }, + "FILTER": { + "TITLE": "Filters", + "NOTIFICATION-TYPE": "Type", + "IS-ACTIVE": "Is Active", + "KIND": "Kind", + "CHANNEL": "Channel", + "CANCEL": "Cancel", + "APPLY-FILTERS": "Apply filters" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Notification Template?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + }, + "ACTIONS": { + "DELETE": "Delete", + "EDIT": "Edit" + }, + "SUCCESSFUL-DELETE": "Successful Delete", + "UNSUCCESSFUL-DELETE": "This item could not be deleted." + }, "NOTIFICATION-TEMPLATE-EDITOR": { "NEW": "New Notification Template", "FIELDS": { @@ -1357,7 +1401,7 @@ "CC-MODE": "CC Mode", "BCC": "BCC", "BCC-MODE": "BCC Mode", - "EXTRA-DATA-KEYS": "EXTRA-DATA-KEYS", + "EXTRA-DATA-KEYS": "Extra Data Keys", "FORMATTING": "Formatting" }, "ACTIONS": { @@ -1365,6 +1409,46 @@ "CANCEL": "Cancel", "DELETE": "Delete" } + }, + "NOTIFICATION-LISTING": { + "TITLE": "Notifications", + "FIELDS": { + "NOTIFICATION-TYPE": "Type", + "NOTIFY-STATE": "Notify State", + "NOTIFIED-WITH": "Notified With", + "CONTACT-TYPE": "Contact Type", + "TRACKING-STATE": "Tracking State", + "TRACKING-PROCESS": "Tracking Process", + "RETRY-COUNT": "Retry Count", + "NOTIFIED-AT": "Notified At", + "USER": "User", + "UPDATED-AT": "Updated", + "CREATED-AT": "Created", + "IS-ACTIVE": "Is Active" + }, + "FILTER": { + "TITLE": "Filters", + "NOTIFICATION-TYPE": "Type", + "IS-ACTIVE": "Is Active", + "NOTIFY-STATE": "Notify State", + "CONTACT-TYPE": "Contact Type", + "TRACKING-STATE": "Tracking State", + "TRACKING-PROCESS": "Tracking Process", + "USERS": "Users", + "CANCEL": "Cancel", + "APPLY-FILTERS": "Apply filters" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Notification?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + }, + "ACTIONS": { + "DELETE": "Delete", + "EDIT": "Edit" + }, + "SUCCESSFUL-DELETE": "Successful Delete", + "UNSUCCESSFUL-DELETE": "This item could not be deleted." } }, "DESCRIPTION-TEMPLATE-TYPE-EDITOR": { @@ -1593,6 +1677,7 @@ "LICENSE": "License", "ACCESS-TYPE": "Access Rights", "CONTACT": "Contact", + "LANGUAGE": "Language", "DESCRIPTION-TEMPLATES": "Description templates", "DESCRIPTION-TEMPLATES-HINT": "Select a template to describe your descriptions" }, @@ -1747,6 +1832,13 @@ "MESSAGE": "Somebody else is modifying the DMP at this moment. You may view the dataset but you cannot make any changes." } }, + "REFERENCE-FIELD": { + "PLACEHOLDER":"Select", + "COULD-NOT-FIND-MESSAGE":"Couldn't find it?", + "ACTIONS": { + "INSERT-MANUALLY":"Insert it manually" + } + }, "DMP-CLONE-DIALOG": { "TITLE": "Clone", "FIELDS": { @@ -2275,6 +2367,42 @@ "DESCRIPTION-TEMPLATE-INVITATION": "Description Template Invitation", "CONTACT-SUPPORT": "Contact Support", "PUBLIC-CONTACT-SUPPORT": "Public Contact Support" + }, + "NOTIFICATION-INAPP-TRACKING": { + "STORED": "Unread", + "DELIVERED": "Read" + }, + "NOTIFICATION-CONTACT-TYPE": { + "EMAIL": "Email", + "INAPP": "In App" + }, + "NOTIFICATION-NOTIFY-STATE": { + "PENDING": "Pending", + "PROCESSING": "Processing", + "SUCCESSFUL": "Successful", + "ERROR":"Error", + "OMITTED": "Omitted" + }, + "NOTIFICATION-TRACKING-STATE": { + "UNDEFINED": "Undefined", + "NA": "NA", + "QUEUED": "Queued", + "SENT":"Sent", + "DELIVERED": "Delivered", + "UNDELIVERED": "Undelivered", + "FAILED": "Failed", + "UNSENT": "Unsent" + }, + "NOTIFICATION-TRACKING-PROCESS": { + "PENDING": "Pending", + "PROCESSING": "Processing", + "SUCCESSFUL": "Successful", + "ERROR":"Error", + "OMITTED": "Omitted" + }, + "DMP-ACCESS-TYPE": { + "PUBLIC": "Public", + "RESTRICTED": "Restricted Access" } }, "ADDRESEARCHERS-EDITOR": { diff --git a/dmp-frontend/src/assets/splash/contact.html b/dmp-frontend/src/assets/splash/contact.html index 7a0c03314..1af8280c0 100644 --- a/dmp-frontend/src/assets/splash/contact.html +++ b/dmp-frontend/src/assets/splash/contact.html @@ -68,7 +68,7 @@
-
+
Contact us to learn more
diff --git a/dmp-frontend/src/common/formatting/common-formatting.module.ts b/dmp-frontend/src/common/formatting/common-formatting.module.ts index a16d284a8..788a33ee9 100644 --- a/dmp-frontend/src/common/formatting/common-formatting.module.ts +++ b/dmp-frontend/src/common/formatting/common-formatting.module.ts @@ -9,6 +9,11 @@ import { ReferenceTypePipe } from './pipes/reference-type.pipe'; import { ReferenceSourceTypePipe } from './pipes/reference-source-type.pipe'; import { NotificationTemplateChannelPipe } from './pipes/notification-template-channel.pipe'; import { NotificationTemplateKindPipe } from './pipes/notification-template-kind.pipe'; +import { NotificationTypePipe } from './pipes/notification-type.pipe'; +import { NotificationContactTypePipe } from './pipes/notification-contact-type.pipe'; +import { NotificationNotifyStatePipe } from './pipes/notification-notify-state.pipe'; +import { NotificationTrackingProcessPipe } from './pipes/notification-tracking-process.pipe'; +import { NotificationTrackingStatePipe } from './pipes/notification-tracking-state.pipe'; // // @@ -29,7 +34,12 @@ import { NotificationTemplateKindPipe } from './pipes/notification-template-kind ReferenceTypePipe, ReferenceSourceTypePipe, NotificationTemplateChannelPipe, - NotificationTemplateKindPipe + NotificationTemplateKindPipe, + NotificationTypePipe, + NotificationContactTypePipe, + NotificationNotifyStatePipe, + NotificationTrackingProcessPipe, + NotificationTrackingStatePipe ], exports: [ DateFormatPipe, @@ -44,7 +54,12 @@ import { NotificationTemplateKindPipe } from './pipes/notification-template-kind ReferenceTypePipe, ReferenceSourceTypePipe, NotificationTemplateChannelPipe, - NotificationTemplateKindPipe + NotificationTemplateKindPipe, + NotificationTypePipe, + NotificationContactTypePipe, + NotificationNotifyStatePipe, + NotificationTrackingProcessPipe, + NotificationTrackingStatePipe ], providers: [ DateFormatPipe, @@ -59,7 +74,12 @@ import { NotificationTemplateKindPipe } from './pipes/notification-template-kind ReferenceTypePipe, ReferenceSourceTypePipe, NotificationTemplateChannelPipe, - NotificationTemplateKindPipe + NotificationTemplateKindPipe, + NotificationTypePipe, + NotificationContactTypePipe, + NotificationNotifyStatePipe, + NotificationTrackingProcessPipe, + NotificationTrackingStatePipe ] }) export class CommonFormattingModule { } diff --git a/dmp-frontend/src/common/formatting/pipes/notification-contact-type.pipe.ts b/dmp-frontend/src/common/formatting/pipes/notification-contact-type.pipe.ts new file mode 100644 index 000000000..160498482 --- /dev/null +++ b/dmp-frontend/src/common/formatting/pipes/notification-contact-type.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; + +@Pipe({ name: 'NotificationContactTypeFormat' }) +export class NotificationContactTypePipe implements PipeTransform { + constructor(private enumUtils: EnumUtils) { } + + public transform(value): any { + return this.enumUtils.toNotificationContactTypeString(value); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/common/formatting/pipes/notification-notify-state.pipe.ts b/dmp-frontend/src/common/formatting/pipes/notification-notify-state.pipe.ts new file mode 100644 index 000000000..f056c5bb1 --- /dev/null +++ b/dmp-frontend/src/common/formatting/pipes/notification-notify-state.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; + +@Pipe({ name: 'NotificationNotifyStateFormat' }) +export class NotificationNotifyStatePipe implements PipeTransform { + constructor(private enumUtils: EnumUtils) { } + + public transform(value): any { + return this.enumUtils.toNotificationNotifyStateString(value); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/common/formatting/pipes/notification-tracking-process.pipe.ts b/dmp-frontend/src/common/formatting/pipes/notification-tracking-process.pipe.ts new file mode 100644 index 000000000..de69188b6 --- /dev/null +++ b/dmp-frontend/src/common/formatting/pipes/notification-tracking-process.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; + +@Pipe({ name: 'NotificationTrackingProcessFormat' }) +export class NotificationTrackingProcessPipe implements PipeTransform { + constructor(private enumUtils: EnumUtils) { } + + public transform(value): any { + return this.enumUtils.toNotificationTrackingProcessString(value); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/common/formatting/pipes/notification-tracking-state.pipe.ts b/dmp-frontend/src/common/formatting/pipes/notification-tracking-state.pipe.ts new file mode 100644 index 000000000..450225329 --- /dev/null +++ b/dmp-frontend/src/common/formatting/pipes/notification-tracking-state.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; + +@Pipe({ name: 'NotificationTrackingStateFormat' }) +export class NotificationTrackingStatePipe implements PipeTransform { + constructor(private enumUtils: EnumUtils) { } + + public transform(value): any { + return this.enumUtils.toNotificationTrackingStateString(value); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/common/formatting/pipes/notification-type.pipe.ts b/dmp-frontend/src/common/formatting/pipes/notification-type.pipe.ts new file mode 100644 index 000000000..4e26ccb69 --- /dev/null +++ b/dmp-frontend/src/common/formatting/pipes/notification-type.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; + +@Pipe({ name: 'NotificationTypeFormat' }) +export class NotificationTypePipe implements PipeTransform { + constructor(private enumUtils: EnumUtils) { } + + public transform(value): any { + return this.enumUtils.toNotificationTypeString(value); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts b/dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts index 501335afa..a03ea232d 100644 --- a/dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts +++ b/dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts @@ -23,8 +23,8 @@ export class ValidationErrorModel implements Serializable let error: string; if (this.message && Array.isArray(this.message)) { for (const element of this.message) { - if (element.Key === propertyName) { - error = element.Value.join(', '); + if (element.key === propertyName) { + error = element.value.join(', '); break; } } @@ -38,10 +38,10 @@ export class ValidationErrorModel implements Serializable const errors = new Map(); if (this.message && Array.isArray(this.message)) { this.message.forEach(element => { - const match = element.Key.match(regExp); + const match = element.key.match(regExp); if (match && match.length >= 2) { const index = Number.parseInt(match[1]); - errors.set(index, element.Value.join(', ')); + errors.set(index, element.value.join(', ')); } }); } @@ -52,15 +52,15 @@ export class ValidationErrorModel implements Serializable if (this.message && Array.isArray(this.message)) { let exists = false; for (const element of this.message) { - if (element.Key === propertyName) { - if (!element.Value.includes(error)) { element.Value.push(error); } + if (element.key === propertyName) { + if (!element.value.includes(error)) { element.value.push(error); } exists = true; break; } } - if (!exists) { this.message.push({ Key: propertyName, Value: [error] }); } + if (!exists) { this.message.push({ key: propertyName, value: [error] }); } } else { - this.message = [{ Key: propertyName, Value: [error] }]; + this.message = [{ key: propertyName, value: [error] }]; } } @@ -68,7 +68,7 @@ export class ValidationErrorModel implements Serializable this.error = undefined; if (this.message && Array.isArray(this.message)) { this.message.forEach(element => { - element.Value.splice(0); + element.value.splice(0); }); } } @@ -76,8 +76,8 @@ export class ValidationErrorModel implements Serializable public clearPart(prefix: string) { if (this.message && Array.isArray(this.message)) { this.message.forEach(element => { - if (element && element.Key && element.Key.startsWith(prefix)) { - element.Value.splice(0); + if (element && element.key && element.key.startsWith(prefix)) { + element.value.splice(0); } }); } @@ -85,6 +85,6 @@ export class ValidationErrorModel implements Serializable } class ErrorMessageItem { - Key: string; - Value: Array = []; + key: string; + value: Array = []; } diff --git a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/UserMigrationService.java b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/UserMigrationService.java index 3886e9767..cf4f6ba7a 100644 --- a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/UserMigrationService.java +++ b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/UserMigrationService.java @@ -73,7 +73,7 @@ public class UserMigrationService { String avatarUrl = ""; String culture = "en-001"; String language = "en"; - String timezone = "en"; + String timezone = "UTC"; String roleOrganization = ""; UUID organizationId = null; if (oldUser != null){