add contact support

This commit is contained in:
Efstratios Giannopoulos 2024-01-04 16:25:07 +02:00
parent 065cd249c9
commit f8e1b4ab8b
25 changed files with 646 additions and 109 deletions

View File

@ -125,5 +125,8 @@ public class AuditableAction {
public static final EventId FileTransformer_GetAvailableConfigurations = new EventId(20000, "FileTransformer_GetAvailableConfigurations");
public static final EventId ContactSupport_Sent = new EventId(210000, "ContactSupport_Sent");
public static final EventId ContactSupport_PublicSent = new EventId(210001, "ContactSupport_PublicSent");
}

View File

@ -22,7 +22,7 @@ public final class Permission {
public static String PublicBrowseReference = "PublicBrowseReference";
public static String PublicBrowseUser = "PublicBrowseUser";
public static String PublicBrowseDashboardStatistics = "PublicBrowseDashboardStatistics";
public static String PublicSendContactSupport = "PublicSendContactSupport";
//Elastic
public static String ManageElastic = "ManageElastic";
@ -170,6 +170,9 @@ public final class Permission {
public static String EditLock = "EditLock";
public static String DeleteLock = "DeleteLock";
//ContactSupport
public static String SendContactSupport = "SendContactSupport";
//ActionConfirmation
public static String BrowseActionConfirmation = "BrowseActionConfirmation";
public static String EditActionConfirmation = "EditActionConfirmation";

View File

@ -7,103 +7,130 @@ import java.util.UUID;
@ConfigurationProperties(prefix = "notification")
public class NotificationProperties {
private UUID dmpInvitationExternalUser;
private UUID dmpInvitationExistingUser;
private UUID dmpModified;
private UUID dmpFinalised;
private UUID descriptionModified;
private UUID descriptionFinalised;
private UUID mergeAccountConfirmation;
private UUID removeCredentialConfirmation;
private UUID dmpDeposit;
private UUID descriptionTemplateInvitation;
private String emailExpirationTimeSeconds;
private UUID dmpInvitationExternalUserType;
private UUID dmpInvitationExistingUserType;
private UUID dmpModifiedType;
private UUID dmpFinalisedType;
private UUID descriptionModifiedType;
private UUID descriptionFinalisedType;
private UUID mergeAccountConfirmationType;
private UUID removeCredentialConfirmationType;
private UUID dmpDepositType;
private UUID descriptionTemplateInvitationType;
private UUID contactSupportType;
private UUID publicContactSupportType;
private int emailExpirationTimeSeconds;
private String contactSupportEmail;
public UUID getDmpInvitationExternalUser() {
return dmpInvitationExternalUser;
public UUID getDmpInvitationExternalUserType() {
return dmpInvitationExternalUserType;
}
public void setDmpInvitationExternalUser(UUID dmpInvitationExternalUser) {
this.dmpInvitationExternalUser = dmpInvitationExternalUser;
public void setDmpInvitationExternalUserType(UUID dmpInvitationExternalUserType) {
this.dmpInvitationExternalUserType = dmpInvitationExternalUserType;
}
public UUID getDmpInvitationExistingUser() {
return dmpInvitationExistingUser;
public UUID getDmpInvitationExistingUserType() {
return dmpInvitationExistingUserType;
}
public void setDmpInvitationExistingUser(UUID dmpInvitationExistingUser) {
this.dmpInvitationExistingUser = dmpInvitationExistingUser;
public void setDmpInvitationExistingUserType(UUID dmpInvitationExistingUserType) {
this.dmpInvitationExistingUserType = dmpInvitationExistingUserType;
}
public UUID getDmpModified() {
return dmpModified;
public UUID getDmpModifiedType() {
return dmpModifiedType;
}
public void setDmpModified(UUID dmpModified) {
this.dmpModified = dmpModified;
public void setDmpModifiedType(UUID dmpModifiedType) {
this.dmpModifiedType = dmpModifiedType;
}
public UUID getDmpFinalised() {
return dmpFinalised;
public UUID getDmpFinalisedType() {
return dmpFinalisedType;
}
public void setDmpFinalised(UUID dmpFinalised) {
this.dmpFinalised = dmpFinalised;
public void setDmpFinalisedType(UUID dmpFinalisedType) {
this.dmpFinalisedType = dmpFinalisedType;
}
public UUID getDescriptionModified() {
return descriptionModified;
public UUID getDescriptionModifiedType() {
return descriptionModifiedType;
}
public void setDescriptionModified(UUID descriptionModified) {
this.descriptionModified = descriptionModified;
public void setDescriptionModifiedType(UUID descriptionModifiedType) {
this.descriptionModifiedType = descriptionModifiedType;
}
public UUID getDescriptionFinalised() {
return descriptionFinalised;
public UUID getDescriptionFinalisedType() {
return descriptionFinalisedType;
}
public void setDescriptionFinalised(UUID descriptionFinalised) {
this.descriptionFinalised = descriptionFinalised;
public void setDescriptionFinalisedType(UUID descriptionFinalisedType) {
this.descriptionFinalisedType = descriptionFinalisedType;
}
public UUID getMergeAccountConfirmation() {
return mergeAccountConfirmation;
public UUID getMergeAccountConfirmationType() {
return mergeAccountConfirmationType;
}
public void setMergeAccountConfirmation(UUID mergeAccountConfirmation) {
this.mergeAccountConfirmation = mergeAccountConfirmation;
public void setMergeAccountConfirmationType(UUID mergeAccountConfirmationType) {
this.mergeAccountConfirmationType = mergeAccountConfirmationType;
}
public UUID getRemoveCredentialConfirmation() {
return removeCredentialConfirmation;
public UUID getRemoveCredentialConfirmationType() {
return removeCredentialConfirmationType;
}
public void setRemoveCredentialConfirmation(UUID removeCredentialConfirmation) {
this.removeCredentialConfirmation = removeCredentialConfirmation;
public void setRemoveCredentialConfirmationType(UUID removeCredentialConfirmationType) {
this.removeCredentialConfirmationType = removeCredentialConfirmationType;
}
public UUID getDmpDeposit() {
return dmpDeposit;
public UUID getDmpDepositType() {
return dmpDepositType;
}
public void setDmpDeposit(UUID dmpDeposit) {
this.dmpDeposit = dmpDeposit;
public void setDmpDepositType(UUID dmpDepositType) {
this.dmpDepositType = dmpDepositType;
}
public UUID getDescriptionTemplateInvitation() {
return descriptionTemplateInvitation;
public UUID getDescriptionTemplateInvitationType() {
return descriptionTemplateInvitationType;
}
public void setDescriptionTemplateInvitation(UUID descriptionTemplateInvitation) {
this.descriptionTemplateInvitation = descriptionTemplateInvitation;
public void setDescriptionTemplateInvitationType(UUID descriptionTemplateInvitationType) {
this.descriptionTemplateInvitationType = descriptionTemplateInvitationType;
}
public String getEmailExpirationTimeSeconds() {
public int getEmailExpirationTimeSeconds() {
return emailExpirationTimeSeconds;
}
public void setEmailExpirationTimeSeconds(String emailExpirationTimeSeconds) {
public void setEmailExpirationTimeSeconds(int emailExpirationTimeSeconds) {
this.emailExpirationTimeSeconds = emailExpirationTimeSeconds;
}
public UUID getContactSupportType() {
return contactSupportType;
}
public void setContactSupportType(UUID contactSupportType) {
this.contactSupportType = contactSupportType;
}
public UUID getPublicContactSupportType() {
return publicContactSupportType;
}
public void setPublicContactSupportType(UUID publicContactSupportType) {
this.publicContactSupportType = publicContactSupportType;
}
public String getContactSupportEmail() {
return contactSupportEmail;
}
public void setContactSupportEmail(String contactSupportEmail) {
this.contactSupportEmail = contactSupportEmail;
}
}

View File

@ -0,0 +1,70 @@
package eu.eudat.model.persist;
import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.commons.validation.specification.Specification;
import eu.eudat.convention.ConventionService;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
public class ContactSupportPersist {
private String subject;
public static final String _subject = "subject";
private String description;
public static final String _description = "description";
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Component(ContactSupportPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class ContactSupportPersistValidator extends BaseValidator<ContactSupportPersist> {
public static final String ValidatorName = "ContactSupportPersistValidator";
private final MessageSource messageSource;
protected ContactSupportPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<ContactSupportPersist> modelClass() {
return ContactSupportPersist.class;
}
@Override
protected List<Specification> specifications(ContactSupportPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isEmpty(item.getSubject()))
.failOn(ContactSupportPersist._subject).failWith(messageSource.getMessage("Validation_Required", new Object[]{ContactSupportPersist._subject}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getDescription()))
.failOn(ContactSupportPersist._description).failWith(messageSource.getMessage("Validation_Required", new Object[]{ContactSupportPersist._description}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -0,0 +1,95 @@
package eu.eudat.model.persist;
import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.commons.validation.specification.Specification;
import eu.eudat.convention.ConventionService;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
public class PublicContactSupportPersist {
private String fullName;
public static final String _fullName = "fullName";
private String email;
public static final String _email = "email";
private String affiliation;
public static final String _affiliation = "affiliation";
private String message;
public static final String _message = "message";
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAffiliation() {
return affiliation;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Component(PublicContactSupportPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class PublicContactSupportPersistValidator extends BaseValidator<PublicContactSupportPersist> {
public static final String ValidatorName = "PublicContactSupportPersistValidator";
private final MessageSource messageSource;
protected PublicContactSupportPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<PublicContactSupportPersist> modelClass() {
return PublicContactSupportPersist.class;
}
@Override
protected List<Specification> specifications(PublicContactSupportPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isEmpty(item.getFullName()))
.failOn(PublicContactSupportPersist._fullName).failWith(messageSource.getMessage("Validation_Required", new Object[]{PublicContactSupportPersist._fullName}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getEmail()))
.failOn(PublicContactSupportPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{PublicContactSupportPersist._email}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getAffiliation()))
.failOn(PublicContactSupportPersist._affiliation).failWith(messageSource.getMessage("Validation_Required", new Object[]{PublicContactSupportPersist._affiliation}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getMessage()))
.failOn(PublicContactSupportPersist._message).failWith(messageSource.getMessage("Validation_Required", new Object[]{PublicContactSupportPersist._message}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -20,16 +20,6 @@ public class FunderPublicOverviewModel {
this.label = label;
}
// public FunderPublicOverviewModel fromDataModel(Funder entity) {
// this.id = entity.getId();
// this.label = entity.getLabel();
// return this;
// }
//
// public Funder toDataModel() throws Exception {
// return null;
// }
public String getHint() {
return null;
}

View File

@ -78,9 +78,8 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
ActionConfirmationEntity data;
if (isUpdate) {
data = this.entityManager.find(ActionConfirmationEntity.class, model.getId());
if (data == null)
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), ReferenceType.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), ReferenceType.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
} else {
data = new ActionConfirmationEntity();

View File

@ -0,0 +1,15 @@
package eu.eudat.service.contactsupport;
import eu.eudat.model.DashboardStatistics;
import eu.eudat.model.RecentActivityItem;
import eu.eudat.model.RecentActivityItemLookup;
import eu.eudat.model.persist.ContactSupportPersist;
import eu.eudat.model.persist.PublicContactSupportPersist;
import javax.management.InvalidApplicationException;
import java.util.List;
public interface ContactSupportService {
void sendContactEmail(ContactSupportPersist model) throws InvalidApplicationException;
void sendPublicContactEmail(PublicContactSupportPersist model) throws InvalidApplicationException;
}

View File

@ -0,0 +1,119 @@
package eu.eudat.service.contactsupport;
import eu.eudat.authorization.Permission;
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.UserContactInfoEntity;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEvent;
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler;
import eu.eudat.model.UserContactInfo;
import eu.eudat.model.persist.ContactSupportPersist;
import eu.eudat.model.persist.PublicContactSupportPersist;
import eu.eudat.query.UserContactInfoQuery;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.util.ArrayList;
import java.util.List;
@Service
public class ContactSupportServiceImpl implements ContactSupportService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ContactSupportServiceImpl.class));
private final AuthorizationService authorizationService;
private final QueryFactory queryFactory;
private final JsonHandlingService jsonHandlingService;
private final UserScope userScope;
private final NotificationIntegrationEventHandler notificationIntegrationEventHandler;
private final NotificationProperties notificationProperties;
@Autowired
public ContactSupportServiceImpl(
AuthorizationService authorizationService,
QueryFactory queryFactory,
JsonHandlingService jsonHandlingService,
UserScope userScope,
NotificationIntegrationEventHandler notificationIntegrationEventHandler,
NotificationProperties notificationProperties) {
this.authorizationService = authorizationService;
this.queryFactory = queryFactory;
this.jsonHandlingService = jsonHandlingService;
this.userScope = userScope;
this.notificationIntegrationEventHandler = notificationIntegrationEventHandler;
this.notificationProperties = notificationProperties;
}
@Override
public void sendContactEmail(ContactSupportPersist model) throws InvalidApplicationException {
logger.debug(new MapLogEntry("send contact email").And("model", model));
this.authorizationService.authorizeForce(Permission.SendContactSupport);
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(this.userScope.getUserId());
query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal));
UserContactInfoEntity contactInfo = query.first();
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, notificationProperties.getContactSupportEmail()));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getContactSupportType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{subject}", DataType.String, model.getSubject()));
fieldInfoList.add(new FieldInfo("{description}", DataType.String, model.getDescription()));
fieldInfoList.add(new FieldInfo("{email}", DataType.String, contactInfo.getValue()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
notificationIntegrationEventHandler.handle(event);
}
@Override
public void sendPublicContactEmail(PublicContactSupportPersist model) throws InvalidApplicationException {
logger.debug(new MapLogEntry("public send contact email").And("model", model));
this.authorizationService.authorizeForce(Permission.SendContactSupport);
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, notificationProperties.getContactSupportEmail()));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getPublicContactSupportType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{subject}", DataType.String, model.getAffiliation()));
fieldInfoList.add(new FieldInfo("{description}", DataType.String, model.getMessage()));
fieldInfoList.add(new FieldInfo("{email}", DataType.String, model.getEmail()));
fieldInfoList.add(new FieldInfo("{name}", DataType.String, model.getFullName()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
notificationIntegrationEventHandler.handle(event);
}
}

View File

@ -242,9 +242,9 @@ public class DescriptionServiceImpl implements DescriptionService {
private NotificationIntegrationEvent applyNotificationType(DescriptionStatus status, NotificationIntegrationEvent event) {
switch (status) {
case Draft:
event.setNotificationType(notificationProperties.getDescriptionModified());
event.setNotificationType(notificationProperties.getDescriptionModifiedType());
case Finalized:
event.setNotificationType(notificationProperties.getDescriptionFinalised());
event.setNotificationType(notificationProperties.getDescriptionFinalisedType());
default:
throw new MyApplicationException("Unsupported Description Status.");
}

View File

@ -222,7 +222,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getDescriptionTemplateInvitation());
event.setNotificationType(notificationProperties.getDescriptionTemplateInvitationType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));

View File

@ -210,10 +210,10 @@ public class DmpServiceImpl implements DmpService {
private NotificationIntegrationEvent applyNotificationType(DmpStatus status, NotificationIntegrationEvent event) {
switch (status) {
case Draft:
event.setNotificationType(notificationProperties.getDmpModified());
event.setNotificationType(notificationProperties.getDmpModifiedType());
return event;
case Finalized:
event.setNotificationType(notificationProperties.getDmpFinalised());
event.setNotificationType(notificationProperties.getDmpFinalisedType());
return event;
default:
throw new MyApplicationException("Unsupported Dmp Status.");
@ -723,7 +723,7 @@ public class DmpServiceImpl implements DmpService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getDmpInvitationExistingUser());
event.setNotificationType(notificationProperties.getDmpInvitationExistingUserType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, recipient.getName()));
@ -747,7 +747,7 @@ public class DmpServiceImpl implements DmpService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getDmpInvitationExternalUser());
event.setNotificationType(notificationProperties.getDmpInvitationExternalUserType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, email));
@ -766,7 +766,7 @@ public class DmpServiceImpl implements DmpService {
persist.setToken(UUID.randomUUID().toString());
persist.setDmpInvitation(new DmpInvitationPersist(email, dmp.getId(), role));
persist.setCreatedById(this.userScope.getUserIdSafe());
persist.setExpiresAt(Instant.now().plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds())));
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
this.actionConfirmationService.persist(persist, null);

View File

@ -65,9 +65,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -355,12 +353,12 @@ public class UserServiceImpl implements UserService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getMergeAccountConfirmation());
event.setNotificationType(notificationProperties.getMergeAccountConfirmationType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{userName}", DataType.String, this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserIdSafe()).first().getName()));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(Integer.parseInt(this.notificationProperties.getEmailExpirationTimeSeconds()))));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
@ -386,12 +384,12 @@ public class UserServiceImpl implements UserService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getRemoveCredentialConfirmation());
event.setNotificationType(notificationProperties.getRemoveCredentialConfirmationType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
fieldInfoList.add(new FieldInfo("{email}", DataType.String, email));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(Integer.parseInt(this.notificationProperties.getEmailExpirationTimeSeconds()))));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
@ -403,8 +401,8 @@ public class UserServiceImpl implements UserService {
persist.setStatus(ActionConfirmationStatus.Requested);
persist.setToken(UUID.randomUUID().toString());
persist.setEmailConfirmation(new EmailConfirmationPersist(email));
persist.setCreatedById(this.userScope.getUserIdSafe());
persist.setExpiresAt(Instant.now().plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds())));
persist.setCreatedById(this.userScope.getUserId());
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
this.actionConfirmationService.persist(persist, null);
@ -421,18 +419,24 @@ public class UserServiceImpl implements UserService {
public void confirmMergeAccount(String token) throws InvalidApplicationException {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.MergeAccount).isActive(IsActive.Active).first();
if (action == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.checkActionState(action);
EmailConfirmationEntity emailConfirmation = this.xmlHandlingService.fromXmlSafe(EmailConfirmationEntity.class, action.getData());
action.setStatus(ActionConfirmationStatus.Accepted);
//TODO merge
// this.entityManager.merge(action);
}
public void confirmRemoveCredential(String token) throws InvalidApplicationException {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.RemoveCredential).isActive(IsActive.Active).first();
if (action == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.checkActionState(action);
@ -447,9 +451,6 @@ public class UserServiceImpl implements UserService {
}
private void checkActionState(ActionConfirmationEntity action) throws MyApplicationException {
if (action == null){
throw new MyApplicationException("Token does not exist!");
}
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){
throw new MyApplicationException("Account is already confirmed!");
}

View File

@ -41,6 +41,12 @@ notification:
- #descriptionTemplateInvitation
type: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B
contacts: [ email ]
- #contactSupportType
type: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD
contacts: [ email ]
- #publicContactSupportType
type: B542B606-ACC6-4629-ADEF-4D8EE2F01222
contacts: [ email ]
ad-hoc-config:
ad-hoc-notification-type: null
message:
@ -266,6 +272,45 @@ notification:
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
- #contactSupportType
key: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD
subject-path: classpath:notification_templates/contactsupport/email/subject.{language}.txt
subject-field-options:
mandatory: [ "{subject}" ]
optional: [ ]
body-path: classpath:notification_templates/contactsupport/email/body.{language}.html
body-field-options:
mandatory: [ "{description}", "{email}" ]
formatting:
'[{subject}]': null
'[{description}]': null
'[{email}]': null
cc: [ ]
cc-mode: 0
bcc: [ ]
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
- #publicContactSupportType
key: B542B606-ACC6-4629-ADEF-4D8EE2F01222
subject-path: classpath:notification_templates/publiccontactsupport/email/subject.{language}.txt
subject-field-options:
mandatory: [ "{subject}" ]
optional: [ ]
body-path: classpath:notification_templates/publiccontactsupport/email/body.{language}.html
body-field-options:
mandatory: [ "{description}", "{email}", "{name}" ]
formatting:
'[{subject}]': null
'[{description}]': null
'[{email}]': null
'[{name}]': null
cc: [ ]
cc-mode: 0
bcc: [ ]
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
template-cache:
prefix: ${CACHE_DISAMBIGUATION:}
key-pattern: "{prefix}:Notification_Message_Email_Template:{key}:v0"

View File

@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Simple Transactional Email</title>
</head>
<body class="">
{description}
<br/>
<br/>
Send by user: {email}
</body>
</html>

View File

@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Simple Transactional Email</title>
</head>
<body class="">
{description}
<br/>
<br/>
Send by user: {email}
</body>
</html>

View File

@ -41,6 +41,12 @@ notification:
- #descriptionTemplateInvitation
type: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B
contacts: [ email ]
- #contactSupportType
type: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD
contacts: [ email ]
- #publicContactSupportType
type: B542B606-ACC6-4629-ADEF-4D8EE2F01222
contacts: [ email ]
ad-hoc-config:
ad-hoc-notification-type: null
message:
@ -266,6 +272,45 @@ notification:
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
- #contactSupportType
key: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD
subject-path: classpath:notification_templates/contactsupport/email/subject.{language}.txt
subject-field-options:
mandatory: [ "{subject}" ]
optional: [ ]
body-path: classpath:notification_templates/contactsupport/email/body.{language}.html
body-field-options:
mandatory: [ "{description}", "{email}" ]
formatting:
'[{subject}]': null
'[{description}]': null
'[{email}]': null
cc: [ ]
cc-mode: 0
bcc: [ ]
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
- #publicContactSupportType
key: B542B606-ACC6-4629-ADEF-4D8EE2F01222
subject-path: classpath:notification_templates/publiccontactsupport/email/subject.{language}.txt
subject-field-options:
mandatory: [ "{subject}" ]
optional: [ ]
body-path: classpath:notification_templates/publiccontactsupport/email/body.{language}.html
body-field-options:
mandatory: [ "{description}", "{email}", "{name}" ]
formatting:
'[{subject}]': null
'[{description}]': null
'[{email}]': null
'[{name}]': null
cc: [ ]
cc-mode: 0
bcc: [ ]
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
template-cache:
prefix: ${CACHE_DISAMBIGUATION:}
key-pattern: "{prefix}:Notification_Message_Email_Template:{key}:v0"

View File

@ -0,0 +1,84 @@
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 org.slf4j.LoggerFactory;
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
@RequestMapping(path = "api/contact-support")
public class ContactSupportController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ContactSupportController.class));
private final AuditService auditService;
private final ContactSupportService contactSupportService;
public ContactSupportController(
AuditService auditService,
ContactSupportService contactSupportService) {
this.auditService = auditService;
this.contactSupportService = contactSupportService;
}
@PostMapping("send")
@Transactional
@ValidationFilterAnnotation(validator = ContactSupportPersist.ContactSupportPersistValidator.ValidatorName, argumentName ="model")
public void sendContactEmail(@RequestBody ContactSupportPersist model) throws InvalidApplicationException {
logger.debug(new MapLogEntry("send support email").And("model", model));
this.contactSupportService.sendContactEmail(model);
this.auditService.track(AuditableAction.ContactSupport_Sent, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model)
));
//this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
}
@PostMapping("public/send")
@Transactional
@ValidationFilterAnnotation(validator = PublicContactSupportPersist.PublicContactSupportPersistValidator.ValidatorName, argumentName ="model")
public void sendPublicContactEmail(@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<String, Object>("model", model)
));
//this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
}
}

View File

@ -19,7 +19,6 @@ 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.core.env.Environment;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
@ -53,7 +52,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
confirmationEmail.setExpiresAt(Date
.from(new Date()
.toInstant()
.plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds()))
.plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds())
)
);
confirmationEmail.setUserId(user.getId());
@ -71,7 +70,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
confirmationEmail.setExpiresAt(Date
.from(new Date()
.toInstant()
.plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds()))
.plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds())
)
);
confirmationEmail.setUserId(user.getId());
@ -94,12 +93,12 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getRemoveCredentialConfirmation());
event.setNotificationType(notificationProperties.getRemoveCredentialConfirmationType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> 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(Integer.parseInt(this.notificationProperties.getEmailExpirationTimeSeconds()))));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
@ -113,7 +112,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
confirmationEmail.setExpiresAt(Date
.from(new Date()
.toInstant()
.plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds()))
.plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds())
)
);
confirmationEmail.setUserId(user.getId());
@ -136,12 +135,12 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getMergeAccountConfirmation());
event.setNotificationType(notificationProperties.getMergeAccountConfirmationType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> 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(Integer.parseInt(this.notificationProperties.getEmailExpirationTimeSeconds()))));
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);

View File

@ -115,7 +115,7 @@ public class InvitationServiceImpl implements InvitationService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getDmpInvitationExternalUser());
event.setNotificationType(notificationProperties.getDmpInvitationExternalUserType());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));

View File

@ -1,12 +1,15 @@
notification:
dmpInvitationExternalUser: 065DEECD-21BB-44AF-9983-E660FDF24BC4
dmpInvitationExistingUser: 4904dea2-5079-46d3-83be-3a19c9ab45dc
dmpModified: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
dmpFinalised: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E
descriptionModified: 4FDBFA80-7A71-4A69-B854-67CBB70648F1
descriptionFinalised: 33790bad-94d4-488a-8ee2-7f6295ca18ea
mergeAccountConfirmation: BFE68845-CB05-4C5A-A03D-29161A7C9660
removeCredentialConfirmation: C9BC3F16-057E-4BBA-8A5F-36BD835E5604
dmpDeposit: 55736F7A-83AB-4190-AF43-9D031A6F9612
descriptionTemplateInvitation: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B
dmpInvitationExternalUserType: 065DEECD-21BB-44AF-9983-E660FDF24BC4
dmpInvitationExistingUserType: 4904dea2-5079-46d3-83be-3a19c9ab45dc
dmpModifiedType: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
dmpFinalisedType: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E
descriptionModifiedType: 4FDBFA80-7A71-4A69-B854-67CBB70648F1
descriptionFinalisedType: 33790bad-94d4-488a-8ee2-7f6295ca18ea
mergeAccountConfirmationType: BFE68845-CB05-4C5A-A03D-29161A7C9660
removeCredentialConfirmationType: C9BC3F16-057E-4BBA-8A5F-36BD835E5604
dmpDepositType: 55736F7A-83AB-4190-AF43-9D031A6F9612
descriptionTemplateInvitationType: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B
contactSupportType: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD
publicContactSupportType: B542B606-ACC6-4629-ADEF-4D8EE2F01222
contactSupportEmail: support@dmp.com
emailExpirationTimeSeconds: 14400

View File

@ -85,7 +85,11 @@ permissions:
clients: [ ]
allowAnonymous: true
allowAuthenticated: true
PublicSendContactSupport:
roles: [ ]
clients: [ ]
allowAnonymous: true
allowAuthenticated: true
# Elastic
ManageElastic:
roles:
@ -677,7 +681,12 @@ permissions:
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
# Lock Permissions
SendContactSupport:
roles: []
clients: [ ]
allowAnonymous: false
allowAuthenticated: true
# ActionConfirmation Permissions
BrowseActionConfirmation:
roles:

View File

@ -2,7 +2,7 @@ web:
security:
enabled: true
authorized-endpoints: [ api ]
allowed-endpoints: [ api/public, api/description/public, api/dashboard/public ]
allowed-endpoints: [ api/public, api/description/public, api/contact-support/public, api/dashboard/public ]
idp:
api-key:
enabled: false