create dmpInvitationExistingUser notification and small changes

This commit is contained in:
amentis 2023-12-15 11:51:08 +02:00
parent bcd42e7ec1
commit fd1d6c9b1a
21 changed files with 765 additions and 99 deletions

View File

@ -2,89 +2,100 @@ package eu.eudat.configurations.notification;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.UUID;
@ConfigurationProperties(prefix = "notification") @ConfigurationProperties(prefix = "notification")
public class NotificationProperties { public class NotificationProperties {
private String dmpInvitation; private UUID dmpInvitationExternalUser;
private String dmpModified; private UUID dmpInvitationExistingUser;
private String dmpFinalised; private UUID dmpModified;
private String descriptionModified; private UUID dmpFinalised;
private String descriptionFinalised; private UUID descriptionModified;
private String mergeAccountConfirmation; private UUID descriptionFinalised;
private String removeCredentialConfirmation; private UUID mergeAccountConfirmation;
private String dmpDeposit; private UUID removeCredentialConfirmation;
private String descriptionTemplateInvitation; private UUID dmpDeposit;
private UUID descriptionTemplateInvitation;
private String emailExpirationTimeSeconds; private String emailExpirationTimeSeconds;
public String getDmpInvitation() { public UUID getDmpInvitationExternalUser() {
return dmpInvitation; return dmpInvitationExternalUser;
} }
public void setDmpInvitation(String dmpInvitation) { public void setDmpInvitationExternalUser(UUID dmpInvitationExternalUser) {
this.dmpInvitation = dmpInvitation; this.dmpInvitationExternalUser = dmpInvitationExternalUser;
} }
public String getDmpModified() { public UUID getDmpInvitationExistingUser() {
return dmpInvitationExistingUser;
}
public void setDmpInvitationExistingUser(UUID dmpInvitationExistingUser) {
this.dmpInvitationExistingUser = dmpInvitationExistingUser;
}
public UUID getDmpModified() {
return dmpModified; return dmpModified;
} }
public void setDmpModified(String dmpModified) { public void setDmpModified(UUID dmpModified) {
this.dmpModified = dmpModified; this.dmpModified = dmpModified;
} }
public String getDmpFinalised() { public UUID getDmpFinalised() {
return dmpFinalised; return dmpFinalised;
} }
public void setDmpFinalised(String dmpFinalised) { public void setDmpFinalised(UUID dmpFinalised) {
this.dmpFinalised = dmpFinalised; this.dmpFinalised = dmpFinalised;
} }
public String getDescriptionModified() { public UUID getDescriptionModified() {
return descriptionModified; return descriptionModified;
} }
public void setDescriptionModified(String descriptionModified) { public void setDescriptionModified(UUID descriptionModified) {
this.descriptionModified = descriptionModified; this.descriptionModified = descriptionModified;
} }
public String getDescriptionFinalised() { public UUID getDescriptionFinalised() {
return descriptionFinalised; return descriptionFinalised;
} }
public void setDescriptionFinalised(String descriptionFinalised) { public void setDescriptionFinalised(UUID descriptionFinalised) {
this.descriptionFinalised = descriptionFinalised; this.descriptionFinalised = descriptionFinalised;
} }
public String getMergeAccountConfirmation() { public UUID getMergeAccountConfirmation() {
return mergeAccountConfirmation; return mergeAccountConfirmation;
} }
public void setMergeAccountConfirmation(String mergeAccountConfirmation) { public void setMergeAccountConfirmation(UUID mergeAccountConfirmation) {
this.mergeAccountConfirmation = mergeAccountConfirmation; this.mergeAccountConfirmation = mergeAccountConfirmation;
} }
public String getRemoveCredentialConfirmation() { public UUID getRemoveCredentialConfirmation() {
return removeCredentialConfirmation; return removeCredentialConfirmation;
} }
public void setRemoveCredentialConfirmation(String removeCredentialConfirmation) { public void setRemoveCredentialConfirmation(UUID removeCredentialConfirmation) {
this.removeCredentialConfirmation = removeCredentialConfirmation; this.removeCredentialConfirmation = removeCredentialConfirmation;
} }
public String getDmpDeposit() { public UUID getDmpDeposit() {
return dmpDeposit; return dmpDeposit;
} }
public void setDmpDeposit(String dmpDeposit) { public void setDmpDeposit(UUID dmpDeposit) {
this.dmpDeposit = dmpDeposit; this.dmpDeposit = dmpDeposit;
} }
public String getDescriptionTemplateInvitation() { public UUID getDescriptionTemplateInvitation() {
return descriptionTemplateInvitation; return descriptionTemplateInvitation;
} }
public void setDescriptionTemplateInvitation(String descriptionTemplateInvitation) { public void setDescriptionTemplateInvitation(UUID descriptionTemplateInvitation) {
this.descriptionTemplateInvitation = descriptionTemplateInvitation; this.descriptionTemplateInvitation = descriptionTemplateInvitation;
} }

View File

@ -71,7 +71,7 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
public void persist(ActionConfirmationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException{ public void persist(ActionConfirmationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException{
logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields)); logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields));
// this.authorizationService.authorizeForce(Permission.EditActionConfirmation); TODO // this.authorizationService.authorizeForce(Permission.EditActionConfirmation); //TODO
Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); Boolean isUpdate = this.conventionService.isValidGuid(model.getId());

View File

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

View File

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

View File

@ -201,10 +201,10 @@ public class DmpServiceImpl implements DmpService {
private NotificationIntegrationEvent applyNotificationType(DmpStatus status, NotificationIntegrationEvent event) { private NotificationIntegrationEvent applyNotificationType(DmpStatus status, NotificationIntegrationEvent event) {
switch (status) { switch (status) {
case Draft: case Draft:
event.setNotificationType(UUID.fromString(notificationProperties.getDmpModified())); event.setNotificationType(notificationProperties.getDmpModified());
return event; return event;
case Finalized: case Finalized:
event.setNotificationType(UUID.fromString(notificationProperties.getDmpFinalised())); event.setNotificationType(notificationProperties.getDmpFinalised());
return event; return event;
default: default:
throw new MyApplicationException("Unsupported Dmp Status."); throw new MyApplicationException("Unsupported Dmp Status.");
@ -702,22 +702,17 @@ public class DmpServiceImpl implements DmpService {
dmpUserPersist.setUser(type.getUserId()); dmpUserPersist.setUser(type.getUserId());
dmpUserPersist.setRole(model.getRole()); dmpUserPersist.setRole(model.getRole());
this.assignUsers(id, List.of(dmpUserPersist), null); this.assignUsers(id, List.of(dmpUserPersist), null);
this.sendDmpInvitationExistingUser(type.getUserId(), dmp, model.getRole());
} else if (type.getEmail() != null) { } else if (type.getEmail() != null) {
this.sendDmpInvitation(type.getEmail(),dmp, model.getRole()); this.sendDmpInvitationExternalUser(type.getEmail(),dmp, model.getRole());
} }
} }
} }
private void sendDmpInvitation(String email, DmpEntity dmp, DmpUserRole role) throws JAXBException, InvalidApplicationException { private void sendDmpInvitationExistingUser(UUID userId, DmpEntity dmp, DmpUserRole role) throws InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist(); UserEntity recipient = this.queryFactory.query(UserQuery.class).ids(userId).isActive(IsActive.Active).first();
persist.setType(ActionConfirmationType.DmpInvitation); String email = this.queryFactory.query(UserContactInfoQuery.class).userIds(recipient.getId()).first().getValue();
persist.setStatus(ActionConfirmationStatus.Requested);
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())));
this.actionConfirmationService.persist(persist, null);
NotificationIntegrationEvent event = new NotificationIntegrationEvent(); NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(this.userScope.getUserIdSafe()); event.setUserId(this.userScope.getUserIdSafe());
@ -727,11 +722,11 @@ public class DmpServiceImpl implements DmpService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL); event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getDmpInvitation())); event.setNotificationType(notificationProperties.getDmpInvitationExistingUser());
NotificationFieldData data = new NotificationFieldData(); NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>(); List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, email)); fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, recipient.getName()));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, persist.getToken())); fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserIdSafe()).first().getName()));
fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel())); fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel()));
fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, role.toString())); fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, role.toString()));
data.setFields(fieldInfoList); data.setFields(fieldInfoList);
@ -739,6 +734,42 @@ public class DmpServiceImpl implements DmpService {
eventHandler.handle(event); eventHandler.handle(event);
} }
private void sendDmpInvitationExternalUser(String email, DmpEntity dmp, DmpUserRole role) throws JAXBException, InvalidApplicationException {
String token = this.createActionConfirmation(email, dmp, role);
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(this.userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(notificationProperties.getDmpInvitationExternalUser());
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, email));
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
fieldInfoList.add(new FieldInfo("{dmpname}", DataType.String, dmp.getLabel()));
fieldInfoList.add(new FieldInfo("{dmprole}", DataType.String, role.toString()));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
}
private String createActionConfirmation(String email, DmpEntity dmp, DmpUserRole role) throws JAXBException, InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(ActionConfirmationType.DmpInvitation);
persist.setStatus(ActionConfirmationStatus.Requested);
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())));
this.actionConfirmationService.persist(persist, null);
return persist.getToken();
}
public void dmpInvitationAccept(String token) throws InvalidApplicationException { public void dmpInvitationAccept(String token) throws InvalidApplicationException {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.DmpInvitation).isActive(IsActive.Active).first(); ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.DmpInvitation).isActive(IsActive.Active).first();

View File

@ -342,28 +342,20 @@ public class UserServiceImpl implements UserService {
//notifications //notifications
public void sendMergeAccountConfirmation(String email) throws InvalidApplicationException, JAXBException { public void sendMergeAccountConfirmation(String email) throws InvalidApplicationException, JAXBException {
ActionConfirmationPersist persist = new ActionConfirmationPersist(); String token = this.createActionConfirmation(email, ActionConfirmationType.MergeAccount);
persist.setType(ActionConfirmationType.MergeAccount);
persist.setStatus(ActionConfirmationStatus.Requested);
persist.setToken(UUID.randomUUID().toString());
persist.setEmailConfirmation(new EmailConfirmationPersist(email));
// persist.setCreatedById(this.userScope.getUserIdSafe()); TODO
persist.setCreatedById(UUID.fromString("2c447092-ae88-40ab-ae7d-43b80b373a5f"));
persist.setExpiresAt(Instant.now().plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds())));
this.actionConfirmationService.persist(persist, null);
NotificationIntegrationEvent event = new NotificationIntegrationEvent(); NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(UUID.fromString("2c447092-ae88-40ab-ae7d-43b80b373a5f")); event.setUserId(this.userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>(); List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email)); contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL); event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getMergeAccountConfirmation())); event.setNotificationType(notificationProperties.getMergeAccountConfirmation());
NotificationFieldData data = new NotificationFieldData(); NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>(); List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{userName}", DataType.String, this.queryFactory.query(UserQuery.class).ids(UUID.fromString("2c447092-ae88-40ab-ae7d-43b80b373a5f")).first().getName())); 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, persist.getToken())); 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(Integer.parseInt(this.notificationProperties.getEmailExpirationTimeSeconds()))));
data.setFields(fieldInfoList); data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data)); event.setData(jsonHandlingService.toJsonSafe(data));
@ -371,37 +363,29 @@ public class UserServiceImpl implements UserService {
} }
public void sendRemoveCredentialConfirmation(String email) throws InvalidApplicationException, JAXBException { public void sendRemoveCredentialConfirmation(String email) throws InvalidApplicationException, JAXBException {
ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(ActionConfirmationType.RemoveCredential);
persist.setStatus(ActionConfirmationStatus.Requested);
persist.setToken(UUID.randomUUID().toString());
UserContactInfoEntity userContactInfo = this.queryFactory.query(UserContactInfoQuery.class).types(ContactInfoType.Email).userIds(UUID.fromString("d107dbad-c67f-418d-a930-f928a690dbfc")).values(email).first(); UserContactInfoEntity userContactInfo = this.queryFactory.query(UserContactInfoQuery.class).types(ContactInfoType.Email).userIds(this.userScope.getUserIdSafe()).values(email).first();
if(userContactInfo == null){ if(userContactInfo == null){
throw new InvalidApplicationException("Email does not exist in this user!"); throw new MyApplicationException("Email does not exist in this user!");
} }
UserCredentialQuery query = this.queryFactory.query(UserCredentialQuery.class).userIds(UUID.fromString("d107dbad-c67f-418d-a930-f928a690dbfc")); UserCredentialQuery query = this.queryFactory.query(UserCredentialQuery.class).userIds(this.userScope.getUserIdSafe());
if (query == null || query.count() == 0){ if (query == null || query.count() == 0){
throw new InvalidApplicationException("This user don't have credential!"); throw new MyApplicationException("This user don't have credential!");
} }
persist.setEmailConfirmation(new EmailConfirmationPersist(email)); String token = this.createActionConfirmation(email, ActionConfirmationType.RemoveCredential);
// persist.setCreatedById(this.userScope.getUserIdSafe()); TODO
persist.setCreatedById(UUID.fromString("d107dbad-c67f-418d-a930-f928a690dbfc"));
persist.setExpiresAt(Instant.now().plusSeconds(Long.parseLong(this.notificationProperties.getEmailExpirationTimeSeconds())));
this.actionConfirmationService.persist(persist, null);
NotificationIntegrationEvent event = new NotificationIntegrationEvent(); NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(UUID.fromString("d107dbad-c67f-418d-a930-f928a690dbfc")); event.setUserId(this.userScope.getUserIdSafe());
List<ContactPair> contactPairs = new ArrayList<>(); List<ContactPair> contactPairs = new ArrayList<>();
contactPairs.add(new ContactPair(ContactInfoType.Email, email)); contactPairs.add(new ContactPair(ContactInfoType.Email, email));
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL); event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getRemoveCredentialConfirmation())); event.setNotificationType(notificationProperties.getRemoveCredentialConfirmation());
NotificationFieldData data = new NotificationFieldData(); NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>(); List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, persist.getToken())); fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
fieldInfoList.add(new FieldInfo("{email}", DataType.String, email)); 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(Integer.parseInt(this.notificationProperties.getEmailExpirationTimeSeconds()))));
data.setFields(fieldInfoList); data.setFields(fieldInfoList);
@ -409,6 +393,18 @@ public class UserServiceImpl implements UserService {
eventHandler.handle(event); eventHandler.handle(event);
} }
private String createActionConfirmation(String email, ActionConfirmationType type) throws JAXBException, InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(type);
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())));
this.actionConfirmationService.persist(persist, null);
return persist.getToken();
}
private String secondsToTime(int seconds) { private String secondsToTime(int seconds) {
int sec = seconds % 60; int sec = seconds % 60;
@ -427,7 +423,7 @@ public class UserServiceImpl implements UserService {
action.setStatus(ActionConfirmationStatus.Accepted); action.setStatus(ActionConfirmationStatus.Accepted);
//TODO merge //TODO merge
this.entityManager.merge(action); // this.entityManager.merge(action);
} }
public void confirmRemoveCredential(String token) throws InvalidApplicationException { public void confirmRemoveCredential(String token) throws InvalidApplicationException {
@ -435,10 +431,9 @@ public class UserServiceImpl implements UserService {
this.checkActionState(action); this.checkActionState(action);
// EmailConfirmationEntity emailConfirmation = this.xmlHandlingService.fromXmlSafe(EmailConfirmationEntity.class, action.getData()); UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).userIds(this.userScope.getUserIdSafe()).first();
UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).userIds(UUID.fromString("d107dbad-c67f-418d-a930-f928a690dbfc")).first(); //ToDO
if (userCredential == null){ if (userCredential == null){
throw new InvalidApplicationException("This user does not have credential"); throw new MyApplicationException("This user does not have credential");
} }
this.deleterFactory.deleter(UserCredentialDeleter.class).deleteAndSaveByIds(List.of(userCredential.getId())); this.deleterFactory.deleter(UserCredentialDeleter.class).deleteAndSaveByIds(List.of(userCredential.getId()));
@ -446,15 +441,15 @@ public class UserServiceImpl implements UserService {
this.entityManager.merge(action); this.entityManager.merge(action);
} }
private void checkActionState(ActionConfirmationEntity action) throws InvalidApplicationException { private void checkActionState(ActionConfirmationEntity action) throws MyApplicationException {
if (action == null){ if (action == null){
throw new InvalidApplicationException("Token does not exist!"); throw new MyApplicationException("Token does not exist!");
} }
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){ if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){
throw new InvalidApplicationException("Account is already confirmed!"); throw new MyApplicationException("Account is already confirmed!");
} }
if (action.getExpiresAt().compareTo(Instant.now()) < 0){ if (action.getExpiresAt().compareTo(Instant.now()) < 0){
throw new InvalidApplicationException("Token has expired!"); throw new MyApplicationException("Token has expired!");
} }
} }

View File

@ -11,9 +11,12 @@ notification:
overrides: [] overrides: []
resolver: resolver:
global-policies: global-policies:
- #dmpInvitation - #dmpInvitationExternalUser
type: 065DEECD-21BB-44AF-9983-E660FDF24BC4 type: 065DEECD-21BB-44AF-9983-E660FDF24BC4
contacts: [ email ] contacts: [ email ]
- #dmpInvitationExistingUser
type: 4904dea2-5079-46d3-83be-3a19c9ab45dc
contacts: [ email ]
- #dpmModified - #dpmModified
type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
contacts: [ email ] contacts: [ email ]
@ -43,13 +46,13 @@ notification:
message: message:
email: email:
flows: flows:
- #dmpInvitation - #dmpInvitationExternalUser
key: 065DEECD-21BB-44AF-9983-E660FDF24BC4 key: 065DEECD-21BB-44AF-9983-E660FDF24BC4
subject-path: classpath:notification_templates/dmpinvitation/email/subject.{language}.txt subject-path: classpath:notification_templates/dmpinvitationexternaluser/email/subject.{language}.txt
subject-field-options: subject-field-options:
mandatory: [ ] mandatory: [ ]
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/dmpinvitation/email/body.{language}.html body-path: classpath:notification_templates/dmpinvitationexternaluser/email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{dmpname}", "{dmprole}", "{installation-url}", "{confirmationToken}" ] mandatory: [ "{dmpname}", "{dmprole}", "{installation-url}", "{confirmationToken}" ]
optional: optional:
@ -65,6 +68,29 @@ notification:
bcc-mode: 0 bcc-mode: 0
allow-attachments: false allow-attachments: false
cipher-fields: [ ] cipher-fields: [ ]
- #dmpInvitationExistingUser
key: 4904dea2-5079-46d3-83be-3a19c9ab45dc
subject-path: classpath:notification_templates/dmpinvitationexistinguser/email/subject.{language}.txt
subject-field-options:
mandatory: [ ]
optional: [ ]
body-path: classpath:notification_templates/dmpinvitationexistinguser/email/body.{language}.html
body-field-options:
mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}" ]
optional:
- key: "{recipient}"
value:
formatting:
'[{dmpname}]': null
'[{dmprole}]': null
'[{reasonName}]': null
'[{recipient}]': null
cc: [ ]
cc-mode: 0
bcc: [ ]
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
- #dmpModified - #dmpModified
key: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB key: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
subject-path: classpath:notification_templates/dmpmodified/email/subject.{language}.txt subject-path: classpath:notification_templates/dmpmodified/email/subject.{language}.txt

View File

@ -0,0 +1,287 @@
<!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>
<style>
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%; }
body {
background-color: #f6f6f6;
font-family: sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
line-height: 1.4;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; }
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%; }
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top; }
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%; }
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px; }
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px; }
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border-radius: 3px;
width: 100%; }
.wrapper {
box-sizing: border-box;
padding: 20px; }
.content-block {
padding-bottom: 10px;
padding-top: 10px;
}
.footer {
clear: both;
Margin-top: 10px;
text-align: center;
width: 100%; }
.footer td,
.footer p,
.footer span,
.footer a {
color: #999999;
font-size: 12px;
text-align: center; }
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1,
h2,
h3,
h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px; }
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize; }
p,
ul,
ol {
font-family: sans-serif;
font-size: 14px;
font-weight: normal;
margin: 0;
Margin-bottom: 15px; }
p li,
ul li,
ol li {
list-style-position: inside;
margin-left: 5px; }
a {
color: #3498db;
text-decoration: underline; }
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%; }
.btn > tbody > tr > td {
padding-bottom: 15px; }
.btn table {
width: auto; }
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center; }
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize; }
.btn-primary table td {
background-color: #3498db; }
.btn-primary a {
background-color: #3498db;
border-color: #3498db;
color: #ffffff; }
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0; }
.first {
margin-top: 0; }
.align-center {
text-align: center; }
.align-right {
text-align: right; }
.align-left {
text-align: left; }
.clear {
clear: both; }
.mt0 {
margin-top: 0; }
.mb0 {
margin-bottom: 0; }
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0; }
.powered-by a {
text-decoration: none; }
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0; }
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important; }
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important; }
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important; }
table[class=body] .content {
padding: 0 !important; }
table[class=body] .container {
padding: 0 !important;
width: 100% !important; }
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important; }
table[class=body] .btn table {
width: 100% !important; }
table[class=body] .btn a {
width: 100% !important; }
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important; }}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%; }
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%; }
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important; }
.btn-primary table td:hover {
background-color: #34495e !important; }
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important; } }
</style>
</head>
<body class="">
<table border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">This is preheader text. Some clients will show this text as a preview.</span>
<table class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<p>Dear {recipient},</p>
<p>{reasonName} just add you to collaborate to Data Management plan {dmpname} with role {dmprole}.</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>

View File

@ -11,9 +11,12 @@ notification:
overrides: [] overrides: []
resolver: resolver:
global-policies: global-policies:
- #dmpInvitation - #dmpInvitationExternalUser
type: 065DEECD-21BB-44AF-9983-E660FDF24BC4 type: 065DEECD-21BB-44AF-9983-E660FDF24BC4
contacts: [ email ] contacts: [ email ]
- #dmpInvitationExistingUser
type: 4904dea2-5079-46d3-83be-3a19c9ab45dc
contacts: [ email ]
- #dpmModified - #dpmModified
type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
contacts: [ email ] contacts: [ email ]
@ -43,13 +46,13 @@ notification:
message: message:
email: email:
flows: flows:
- #dmpInvitation - #dmpInvitationExternalUser
key: 065DEECD-21BB-44AF-9983-E660FDF24BC4 key: 065DEECD-21BB-44AF-9983-E660FDF24BC4
subject-path: classpath:notification_templates/dmpinvitation/email/subject.{language}.txt subject-path: classpath:notification_templates/dmpinvitationexternaluser/email/subject.{language}.txt
subject-field-options: subject-field-options:
mandatory: [ ] mandatory: [ ]
optional: [ ] optional: [ ]
body-path: classpath:notification_templates/dmpinvitation/email/body.{language}.html body-path: classpath:notification_templates/dmpinvitationexternaluser/email/body.{language}.html
body-field-options: body-field-options:
mandatory: [ "{dmpname}", "{dmprole}", "{installation-url}", "{confirmationToken}" ] mandatory: [ "{dmpname}", "{dmprole}", "{installation-url}", "{confirmationToken}" ]
optional: optional:
@ -65,6 +68,29 @@ notification:
bcc-mode: 0 bcc-mode: 0
allow-attachments: false allow-attachments: false
cipher-fields: [ ] cipher-fields: [ ]
- #dmpInvitationExistingUser
key: 4904dea2-5079-46d3-83be-3a19c9ab45dc
subject-path: classpath:notification_templates/dmpinvitationexistinguser/email/subject.{language}.txt
subject-field-options:
mandatory: [ ]
optional: [ ]
body-path: classpath:notification_templates/dmpinvitationexistinguser/email/body.{language}.html
body-field-options:
mandatory: [ "{dmpname}", "{dmprole}", "{reasonName}" ]
optional:
- key: "{recipient}"
value:
formatting:
'[{dmpname}]': null
'[{dmprole}]': null
'[{reasonName}]': null
'[{recipient}]': null
cc: [ ]
cc-mode: 0
bcc: [ ]
bcc-mode: 0
allow-attachments: false
cipher-fields: [ ]
- #dmpModified - #dmpModified
key: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB key: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
subject-path: classpath:notification_templates/dmpmodified/email/subject.{language}.txt subject-path: classpath:notification_templates/dmpmodified/email/subject.{language}.txt

View File

@ -0,0 +1,287 @@
<!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>
<style>
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%; }
body {
background-color: #f6f6f6;
font-family: sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
line-height: 1.4;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; }
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%; }
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top; }
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%; }
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px; }
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px; }
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border-radius: 3px;
width: 100%; }
.wrapper {
box-sizing: border-box;
padding: 20px; }
.content-block {
padding-bottom: 10px;
padding-top: 10px;
}
.footer {
clear: both;
Margin-top: 10px;
text-align: center;
width: 100%; }
.footer td,
.footer p,
.footer span,
.footer a {
color: #999999;
font-size: 12px;
text-align: center; }
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1,
h2,
h3,
h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px; }
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize; }
p,
ul,
ol {
font-family: sans-serif;
font-size: 14px;
font-weight: normal;
margin: 0;
Margin-bottom: 15px; }
p li,
ul li,
ol li {
list-style-position: inside;
margin-left: 5px; }
a {
color: #3498db;
text-decoration: underline; }
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%; }
.btn > tbody > tr > td {
padding-bottom: 15px; }
.btn table {
width: auto; }
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center; }
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize; }
.btn-primary table td {
background-color: #3498db; }
.btn-primary a {
background-color: #3498db;
border-color: #3498db;
color: #ffffff; }
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0; }
.first {
margin-top: 0; }
.align-center {
text-align: center; }
.align-right {
text-align: right; }
.align-left {
text-align: left; }
.clear {
clear: both; }
.mt0 {
margin-top: 0; }
.mb0 {
margin-bottom: 0; }
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0; }
.powered-by a {
text-decoration: none; }
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0; }
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important; }
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important; }
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important; }
table[class=body] .content {
padding: 0 !important; }
table[class=body] .container {
padding: 0 !important;
width: 100% !important; }
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important; }
table[class=body] .btn table {
width: 100% !important; }
table[class=body] .btn a {
width: 100% !important; }
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important; }}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%; }
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%; }
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important; }
.btn-primary table td:hover {
background-color: #34495e !important; }
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important; } }
</style>
</head>
<body class="">
<table border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">This is preheader text. Some clients will show this text as a preview.</span>
<table class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<p>Dear {recipient},</p>
<p>{reasonName} just add you to collaborate to Data Management plan {dmpname} with role {dmprole}.</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>

View File

@ -94,7 +94,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL); event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getRemoveCredentialConfirmation())); event.setNotificationType(notificationProperties.getRemoveCredentialConfirmation());
NotificationFieldData data = new NotificationFieldData(); NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>(); List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString())); fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, confirmationEmail.getToken().toString()));
@ -136,7 +136,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
event.setContactTypeHint(NotificationContactType.EMAIL); event.setContactTypeHint(NotificationContactType.EMAIL);
event.setNotificationType(UUID.fromString(notificationProperties.getMergeAccountConfirmation())); event.setNotificationType(notificationProperties.getMergeAccountConfirmation());
NotificationFieldData data = new NotificationFieldData(); NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>(); List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{userName}", DataType.String, user.getName())); fieldInfoList.add(new FieldInfo("{userName}", DataType.String, user.getName()));

View File

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

View File

@ -1,5 +1,6 @@
notification: notification:
dmpInvitation: 065DEECD-21BB-44AF-9983-E660FDF24BC4 dmpInvitationExternalUser: 065DEECD-21BB-44AF-9983-E660FDF24BC4
dmpInvitationExistingUser: 4904dea2-5079-46d3-83be-3a19c9ab45dc
dmpModified: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB dmpModified: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB
dmpFinalised: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E dmpFinalised: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E
descriptionModified: 4FDBFA80-7A71-4A69-B854-67CBB70648F1 descriptionModified: 4FDBFA80-7A71-4A69-B854-67CBB70648F1