merge remove credential changes

This commit is contained in:
Efstratios Giannopoulos 2024-01-15 13:57:33 +02:00
parent 0e61925f8d
commit 4da8c2a6a9
26 changed files with 639 additions and 272 deletions

View File

@ -24,6 +24,11 @@
<artifactId>commons-csv</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>validation</artifactId>

View File

@ -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;

View File

@ -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 RemoveCredentialConfirmationEntity {
@XmlAttribute(name = "credential-id")
private UUID credentialId;
public UUID getCredentialId() {
return credentialId;
}
public void setCredentialId(UUID credentialId) {
this.credentialId = credentialId;
}
}

View File

@ -3,6 +3,8 @@ package eu.eudat.commons.validation;
import eu.eudat.convention.ConventionService;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.exception.MyValidationException;
import org.apache.commons.validator.routines.EmailValidator;
import java.util.*;
public abstract class BaseValidator<T> extends AbstractValidator<T> {
@ -27,6 +29,9 @@ public abstract class BaseValidator<T> extends AbstractValidator<T> {
protected Boolean isValidGuid(UUID guid) {
return this.conventionService.isValidGuid(guid);
}
protected Boolean isValidEmail(String value) {
return EmailValidator.getInstance().isValid(value);
}
protected Boolean isValidHash(String hash) {
return this.conventionService.isValidHash(hash);

View File

@ -20,9 +20,6 @@ public class ActionConfirmation {
private ActionConfirmationStatus status;
public static final String _status = "status";
private String token;
public static final String _token = "token";
private EmailConfirmation emailConfirmation;
public static final String _emailConfirmation = "emailConfirmation";
@ -75,14 +72,6 @@ public class ActionConfirmation {
this.status = status;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public EmailConfirmation getEmailConfirmation() {
return emailConfirmation;
}

View File

@ -4,7 +4,7 @@ import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.XmlHandlingService;
import eu.eudat.commons.enums.ActionConfirmationType;
import eu.eudat.commons.types.actionconfirmation.DmpInvitationEntity;
import eu.eudat.commons.types.actionconfirmation.EmailConfirmationEntity;
import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.ActionConfirmationEntity;
import eu.eudat.model.ActionConfirmation;
@ -71,12 +71,11 @@ public class ActionConfirmationBuilder extends BaseBuilder<ActionConfirmation, A
if(fields.hasField(this.asIndexer(ActionConfirmation._id))) m.setId(d.getId());
if(fields.hasField(this.asIndexer(ActionConfirmation._type))) m.setType(d.getType());
if(fields.hasField(this.asIndexer(ActionConfirmation._status))) m.setStatus(d.getStatus());
if(fields.hasField(this.asIndexer(ActionConfirmation._token))) m.setToken(d.getToken());
if(fields.hasField(this.asIndexer(ActionConfirmation._isActive))) m.setIsActive(d.getIsActive());
if(fields.hasField(this.asIndexer(ActionConfirmation._expiresAt))) m.setExpiresAt(d.getExpiresAt());
if (!emailConfirmationFields.isEmpty() && d.getData() != null){
if (d.getType().equals(ActionConfirmationType.MergeAccount) || d.getType().equals(ActionConfirmationType.RemoveCredential)){
EmailConfirmationEntity emailConfirmation = this.xmlHandlingService.fromXmlSafe(EmailConfirmationEntity.class, d.getData());
MergeAccountConfirmationEntity emailConfirmation = this.xmlHandlingService.fromXmlSafe(MergeAccountConfirmationEntity.class, d.getData());
m.setEmailConfirmation(this.builderFactory.builder(EmailConfirmationBuilder.class).authorize(this.authorize).build(emailConfirmationFields, emailConfirmation));
}else{
DmpInvitationEntity dmpInvitation = this.xmlHandlingService.fromXmlSafe(DmpInvitationEntity.class, d.getData());

View File

@ -1,7 +1,7 @@
package eu.eudat.model.builder.actionconfirmation;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.types.actionconfirmation.EmailConfirmationEntity;
import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
import eu.eudat.convention.ConventionService;
import eu.eudat.model.actionconfirmation.EmailConfirmation;
import eu.eudat.model.builder.BaseBuilder;
@ -20,7 +20,7 @@ import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class EmailConfirmationBuilder extends BaseBuilder<EmailConfirmation, EmailConfirmationEntity> {
public class EmailConfirmationBuilder extends BaseBuilder<EmailConfirmation, MergeAccountConfirmationEntity> {
private final BuilderFactory builderFactory;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@ -38,7 +38,7 @@ public class EmailConfirmationBuilder extends BaseBuilder<EmailConfirmation, Ema
}
@Override
public List<EmailConfirmation> build(FieldSet fields, List<EmailConfirmationEntity> data) throws MyApplicationException {
public List<EmailConfirmation> build(FieldSet fields, List<MergeAccountConfirmationEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
@ -46,7 +46,7 @@ public class EmailConfirmationBuilder extends BaseBuilder<EmailConfirmation, Ema
List<EmailConfirmation> models = new ArrayList<>();
for (EmailConfirmationEntity d : data) {
for (MergeAccountConfirmationEntity d : data) {
EmailConfirmation m = new EmailConfirmation();
if (fields.hasField(this.asIndexer(EmailConfirmation._email))) m.setEmail(d.getEmail());

View File

@ -0,0 +1,68 @@
package eu.eudat.model.deleter;
import eu.eudat.data.UserSettingsEntity;
import eu.eudat.query.UserSettingsQuery;
import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.persistence.EntityManager;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.management.InvalidApplicationException;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserSettingsSettingsDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserSettingsSettingsDeleter.class));
private final EntityManager entityManager;
protected final QueryFactory queryFactory;
@Autowired
public UserSettingsSettingsDeleter(
EntityManager entityManager,
QueryFactory queryFactory
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids));
List<UserSettingsEntity> data = this.queryFactory.query(UserSettingsQuery.class).ids(ids).collect();
logger.trace("retrieved {} items", Optional.ofNullable(data).map(List::size).orElse(0));
this.deleteAndSave(data);
}
public void deleteAndSave(List<UserSettingsEntity> data) throws InvalidApplicationException {
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
this.delete(data);
logger.trace("saving changes");
this.entityManager.flush();
logger.trace("changes saved");
}
public void delete(List<UserSettingsEntity> data) throws InvalidApplicationException {
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
if (data == null || data.isEmpty())
return;
for (UserSettingsEntity item : data) {
logger.trace("deleting item {}", item.getId());
logger.trace("deleting item");
this.entityManager.remove(item);
logger.trace("deleted item");
}
}
}

View File

@ -8,7 +8,7 @@ import eu.eudat.commons.validation.specification.Specification;
import eu.eudat.convention.ConventionService;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.model.persist.actionconfirmation.DmpInvitationPersist;
import eu.eudat.model.persist.actionconfirmation.EmailConfirmationPersist;
import eu.eudat.model.persist.actionconfirmation.MergeAccountConfirmationPersist;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
@ -40,18 +40,18 @@ public class ActionConfirmationPersist {
private static final String _dmpInvitation = "dmpInvitation";
private EmailConfirmationPersist emailConfirmation;
private MergeAccountConfirmationPersist mergeAccountConfirmation;
private static final String _emailConfirmation = "emailConfirmation";
private static final String _mergeAccountConfirmation = "mergeAccountConfirmation";
private RemoveCredentialRequestPersist removeCredentialRequest;
private static final String _removeCredentialRequest = "removeCredentialRequest";
private Instant expiresAt;
private static final String _expiresAt = "expiresAt";
private UUID createdById;
private static final String _createdById = "createdById";
private String hash;
private static final String _hash = "hash";
@ -80,14 +80,6 @@ public class ActionConfirmationPersist {
this.status = status;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public DmpInvitationPersist getDmpInvitation() {
return dmpInvitation;
}
@ -96,12 +88,28 @@ public class ActionConfirmationPersist {
this.dmpInvitation = dmpInvitation;
}
public EmailConfirmationPersist getEmailConfirmation() {
return emailConfirmation;
public MergeAccountConfirmationPersist getMergeAccountConfirmation() {
return mergeAccountConfirmation;
}
public void setEmailConfirmation(EmailConfirmationPersist emailConfirmation) {
this.emailConfirmation = emailConfirmation;
public void setMergeAccountConfirmation(MergeAccountConfirmationPersist mergeAccountConfirmation) {
this.mergeAccountConfirmation = mergeAccountConfirmation;
}
public RemoveCredentialRequestPersist getRemoveCredentialRequest() {
return removeCredentialRequest;
}
public void setRemoveCredentialRequest(RemoveCredentialRequestPersist removeCredentialRequest) {
this.removeCredentialRequest = removeCredentialRequest;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Instant getExpiresAt() {
@ -112,13 +120,6 @@ public class ActionConfirmationPersist {
this.expiresAt = expiresAt;
}
public UUID getCreatedById() {
return createdById;
}
public void setCreatedById(UUID createdById) {
this.createdById = createdById;
}
public String getHash() {
return hash;
@ -173,8 +174,18 @@ public class ActionConfirmationPersist {
.must(() -> !this.isNull(item.getExpiresAt()))
.failOn(ActionConfirmationPersist._expiresAt).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._expiresAt}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isNull(item.getCreatedById()))
.failOn(ActionConfirmationPersist._createdById).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._createdById}, LocaleContextHolder.getLocale())),
.iff(() -> ActionConfirmationType.MergeAccount.equals(item.getType()))
.must(() -> !this.isNull(item.getMergeAccountConfirmation()))
.failOn(ActionConfirmationPersist._mergeAccountConfirmation).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._mergeAccountConfirmation}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> ActionConfirmationType.DmpInvitation.equals(item.getType()))
.must(() -> !this.isNull(item.getDmpInvitation()))
.failOn(ActionConfirmationPersist._dmpInvitation).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._dmpInvitation}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> ActionConfirmationType.RemoveCredential.equals(item.getType()))
.must(() -> !this.isNull(item.getRemoveCredentialRequest()))
.failOn(ActionConfirmationPersist._removeCredentialRequest).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._removeCredentialRequest}, LocaleContextHolder.getLocale())),
this.refSpec()
.iff(() -> !this.isNull(item.getDmpInvitation()))
@ -182,10 +193,16 @@ public class ActionConfirmationPersist {
.over(item.getDmpInvitation())
.using(() -> this.validatorFactory.validator(DmpInvitationPersist.DmpInvitationPersistValidator.class)),
this.refSpec()
.iff(() -> !this.isNull(item.getEmailConfirmation()))
.on(ActionConfirmationPersist._emailConfirmation)
.over(item.getEmailConfirmation())
.using(() -> this.validatorFactory.validator(EmailConfirmationPersist.EmailConfirmationPersistValidator.class))
.iff(() -> !this.isNull(item.getMergeAccountConfirmation()))
.on(ActionConfirmationPersist._mergeAccountConfirmation)
.over(item.getMergeAccountConfirmation())
.using(() -> this.validatorFactory.validator(MergeAccountConfirmationPersist.MergeAccountConfirmationPersistValidator.class)),
this.refSpec()
.iff(() -> !this.isNull(item.getRemoveCredentialRequest()))
.on(ActionConfirmationPersist._removeCredentialRequest)
.over(item.getRemoveCredentialRequest())
.using(() -> this.validatorFactory.validator(RemoveCredentialRequestPersist.RemoveCredentialRequestPersistValidator.class))
);
}

View File

@ -0,0 +1,60 @@
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;
import java.util.UUID;
public class RemoveCredentialRequestPersist {
private UUID credentialId;
public static final String _credentialId = "credentialId";
public UUID getCredentialId() {
return credentialId;
}
public void setCredentialId(UUID credentialId) {
this.credentialId = credentialId;
}
@Component(RemoveCredentialRequestPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class RemoveCredentialRequestPersistValidator extends BaseValidator<RemoveCredentialRequestPersist> {
public static final String ValidatorName = "RemoveCredentialRequestPersistValidator";
private final MessageSource messageSource;
protected RemoveCredentialRequestPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<RemoveCredentialRequestPersist> modelClass() {
return RemoveCredentialRequestPersist.class;
}
@Override
protected List<Specification> specifications(RemoveCredentialRequestPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isValidGuid(item.getCredentialId()))
.failOn(RemoveCredentialRequestPersist._credentialId).failWith(messageSource.getMessage("Validation_Required", new Object[]{RemoveCredentialRequestPersist._credentialId}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -0,0 +1,65 @@
package eu.eudat.model.persist;
import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.commons.validation.ValidatorFactory;
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 UserMergeRequestPersist {
private String email;
public static final String _email = "email";
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Component(UserMergeRequestPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class UserMergeRequestPersistValidator extends BaseValidator<UserMergeRequestPersist> {
public static final String ValidatorName = "UserMergeRequestPersistValidator";
private final MessageSource messageSource;
protected UserMergeRequestPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<UserMergeRequestPersist> modelClass() {
return UserMergeRequestPersist.class;
}
@Override
protected List<Specification> specifications(UserMergeRequestPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isEmpty(item.getEmail()))
.failOn(UserMergeRequestPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserMergeRequestPersist._email}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getEmail()))
.must(() -> this.isValidEmail(item.getEmail()))
.failOn(UserMergeRequestPersist._email).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{UserMergeRequestPersist._email}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -1,78 +0,0 @@
package eu.eudat.model.persist;
import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.commons.validation.ValidatorFactory;
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;
import java.util.UUID;
public class UserRequestPersist {
private UUID userId;
public static final String _userId = "userId";
private String email;
public static final String _email = "email";
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Component(UserRequestPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class UserRequestPersistValidator extends BaseValidator<UserRequestPersist> {
public static final String ValidatorName = "UserRequestPersistValidator";
private final MessageSource messageSource;
private final ValidatorFactory validatorFactory;
protected UserRequestPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
super(conventionService, errors);
this.messageSource = messageSource;
this.validatorFactory = validatorFactory;
}
@Override
protected Class<UserRequestPersist> modelClass() {
return UserRequestPersist.class;
}
@Override
protected List<Specification> specifications(UserRequestPersist item) {
return Arrays.asList(
this.spec()
.must(() -> this.isValidGuid(item.getUserId()))
.failOn(UserRequestPersist._userId).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserRequestPersist._userId}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getEmail()))
.failOn(UserRequestPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserRequestPersist._email}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -13,15 +13,12 @@ import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
public class EmailConfirmationPersist {
public class MergeAccountConfirmationPersist {
private String email;
public static final String _email = "email";
public EmailConfirmationPersist(String email) {
this.email = email;
}
public String getEmail() {
return email;
@ -31,30 +28,30 @@ public class EmailConfirmationPersist {
this.email = email;
}
@Component(EmailConfirmationPersistValidator.ValidatorName)
@Component(MergeAccountConfirmationPersistValidator.ValidatorName)
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class EmailConfirmationPersistValidator extends BaseValidator<EmailConfirmationPersist> {
public static class MergeAccountConfirmationPersistValidator extends BaseValidator<MergeAccountConfirmationPersist> {
public static final String ValidatorName = "EmailConfirmationPersistValidator";
public static final String ValidatorName = "MergeAccountConfirmationPersistValidator";
private final MessageSource messageSource;
protected EmailConfirmationPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
protected MergeAccountConfirmationPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<EmailConfirmationPersist> modelClass() {
return EmailConfirmationPersist.class;
protected Class<MergeAccountConfirmationPersist> modelClass() {
return MergeAccountConfirmationPersist.class;
}
@Override
protected List<Specification> specifications(EmailConfirmationPersist item) {
protected List<Specification> specifications(MergeAccountConfirmationPersist item) {
return Collections.singletonList(
this.spec()
.must(() -> !this.isEmpty(item.getEmail()))
.failOn(EmailConfirmationPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{EmailConfirmationPersist._email}, LocaleContextHolder.getLocale()))
.failOn(MergeAccountConfirmationPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{MergeAccountConfirmationPersist._email}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -237,7 +237,7 @@ public class ActionConfirmationQuery extends QueryBase<ActionConfirmationEntity>
if (item.match(ActionConfirmation._id)) return ActionConfirmationEntity._id;
else if (item.match(ActionConfirmation._type)) return ActionConfirmationEntity._type;
else if (item.match(ActionConfirmation._status)) return ActionConfirmationEntity._status;
else if (item.match(ActionConfirmation._token)) return ActionConfirmationEntity._token;
else if (item.match(ActionConfirmationEntity._token)) return ActionConfirmationEntity._token;
else if (item.match(ActionConfirmation._expiresAt)) return ActionConfirmationEntity._expiresAt;
else if (item.prefix(ActionConfirmation._emailConfirmation)) return ActionConfirmationEntity._data;
else if (item.prefix(ActionConfirmation._dmpInvitation)) return ActionConfirmationEntity._data;

View File

@ -35,6 +35,8 @@ import java.util.*;
public class DescriptionQuery extends QueryBase<DescriptionEntity> {
private String like;
private Collection<UUID> ids;
private Collection<UUID> createdByIds;
private DmpDescriptionTemplateQuery dmpDescriptionTemplateQuery;
private DmpQuery dmpQuery;
private Instant createdAfter;
@ -78,6 +80,21 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
return this;
}
public DescriptionQuery createdByIds(UUID value) {
this.createdByIds = List.of(value);
return this;
}
public DescriptionQuery createdByIds(UUID... value) {
this.createdByIds = Arrays.asList(value);
return this;
}
public DescriptionQuery createdByIds(Collection<UUID> values) {
this.createdByIds = values;
return this;
}
public DescriptionQuery dmpDescriptionTemplateSubQuery(DmpDescriptionTemplateQuery subQuery) {
this.dmpDescriptionTemplateQuery = subQuery;
return this;
@ -174,7 +191,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
protected Boolean isFalseQuery() {
return
this.isEmpty(this.ids) ||
this.isEmpty(this.isActives) ||
this.isEmpty(this.isActives) || this.isEmpty(this.createdByIds) ||
this.isEmpty(this.excludedIds) || this.isFalseQuery(this.dmpQuery) ||
this.isEmpty(this.statuses) || this.isFalseQuery(this.dmpDescriptionTemplateQuery);
}
@ -220,6 +237,12 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.createdByIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._createdById));
for (UUID item : this.createdByIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.createdAfter != null) {
predicates.add(queryContext.CriteriaBuilder.greaterThan(queryContext.Root.get(DescriptionEntity._createdAt), this.createdAfter));
}

View File

@ -31,6 +31,7 @@ public class DmpQuery extends QueryBase<DmpEntity> {
private String like;
private Collection<UUID> ids;
private Collection<UUID> creatorIds;
private Collection<UUID> excludedIds;
@ -79,6 +80,21 @@ public class DmpQuery extends QueryBase<DmpEntity> {
return this;
}
public DmpQuery creatorIds(UUID value) {
this.creatorIds = List.of(value);
return this;
}
public DmpQuery creatorIds(UUID... value) {
this.creatorIds = Arrays.asList(value);
return this;
}
public DmpQuery creatorIds(Collection<UUID> values) {
this.creatorIds = values;
return this;
}
public DmpQuery excludedIds(Collection<UUID> values) {
this.excludedIds = values;
return this;
@ -201,7 +217,7 @@ public class DmpQuery extends QueryBase<DmpEntity> {
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.versionStatuses) || this.isEmpty(this.excludedIds) || this.isEmpty(this.accessTypes)|| this.isEmpty(this.statuses)|| this.isFalseQuery(this.dmpDescriptionTemplateQuery)|| this.isFalseQuery(this.dmpUserQuery);
return this.isEmpty(this.ids) || this.isEmpty(this.creatorIds) ||this.isEmpty(this.isActives) || this.isEmpty(this.versionStatuses) || this.isEmpty(this.excludedIds) || this.isEmpty(this.accessTypes)|| this.isEmpty(this.statuses)|| this.isFalseQuery(this.dmpDescriptionTemplateQuery)|| this.isFalseQuery(this.dmpUserQuery);
}
@Override
@ -248,6 +264,12 @@ public class DmpQuery extends QueryBase<DmpEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.creatorIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpEntity._creatorId));
for (UUID item : this.creatorIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.excludedIds != null) {
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpEntity._id));
for (UUID item : this.excludedIds)

View File

@ -24,6 +24,7 @@ public class LockQuery extends QueryBase<LockEntity> {
private Collection<UUID> ids;
private Collection<UUID> targetIds;
private Collection<UUID> lockedByIds;
private Collection<LockTargetType> targetTypes;
@ -45,6 +46,21 @@ public class LockQuery extends QueryBase<LockEntity> {
this.ids = values;
return this;
}
public LockQuery lockedByIds(UUID value) {
this.lockedByIds = List.of(value);
return this;
}
public LockQuery lockedByIds(UUID... value) {
this.lockedByIds = Arrays.asList(value);
return this;
}
public LockQuery lockedByIds(Collection<UUID> values) {
this.lockedByIds = values;
return this;
}
public LockQuery targetIds(UUID value) {
this.targetIds = List.of(value);
@ -106,7 +122,7 @@ public class LockQuery extends QueryBase<LockEntity> {
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.targetIds) || this.isEmpty(this.excludedIds) || this.isEmpty(this.targetTypes);
return this.isEmpty(this.ids) || this.isEmpty(this.lockedByIds) || this.isEmpty(this.targetIds) || this.isEmpty(this.excludedIds) || this.isEmpty(this.targetTypes);
}
@Override
@ -118,6 +134,12 @@ public class LockQuery extends QueryBase<LockEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.lockedByIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LockEntity._lockedBy));
for (UUID item : this.lockedByIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.targetIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LockEntity._target));
for (UUID item : this.targetIds)

View File

@ -25,6 +25,7 @@ import java.util.*;
public class StorageFileQuery extends QueryBase<StorageFileEntity> {
private String like;
private Collection<UUID> ids;
private Collection<UUID> ownerIds;
private Boolean canPurge;
private Boolean isPurged;
private Instant createdAfter;
@ -58,6 +59,21 @@ public class StorageFileQuery extends QueryBase<StorageFileEntity> {
return this;
}
public StorageFileQuery ownerIds(UUID value) {
this.ownerIds = List.of(value);
return this;
}
public StorageFileQuery ownerIds(UUID... value) {
this.ownerIds = Arrays.asList(value);
return this;
}
public StorageFileQuery ownerIds(Collection<UUID> values) {
this.ownerIds = values;
return this;
}
public StorageFileQuery createdAfter(Instant value) {
this.createdAfter = value;
return this;
@ -97,6 +113,7 @@ public class StorageFileQuery extends QueryBase<StorageFileEntity> {
protected Boolean isFalseQuery() {
return
this.isEmpty(this.ids) ||
this.isEmpty(this.ownerIds) ||
this.isEmpty(this.excludedIds) ;
}
@ -137,6 +154,12 @@ public class StorageFileQuery extends QueryBase<StorageFileEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.ownerIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(StorageFileEntity._ownerId));
for (UUID item : this.ownerIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.createdAfter != null) {
predicates.add(queryContext.CriteriaBuilder.greaterThan(queryContext.Root.get(StorageFileEntity._createdAt), this.createdAfter));
}

View File

@ -1,5 +1,6 @@
package eu.eudat.service.actionconfirmation;
import eu.eudat.model.ActionConfirmation;
import eu.eudat.model.persist.ActionConfirmationPersist;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
@ -14,7 +15,7 @@ import java.util.UUID;
public interface ActionConfirmationService {
void persist(ActionConfirmationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
ActionConfirmation persist(ActionConfirmationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException;

View File

@ -1,19 +1,26 @@
package eu.eudat.service.actionconfirmation;
import eu.eudat.authorization.OwnedResource;
import eu.eudat.authorization.Permission;
import eu.eudat.commons.XmlHandlingService;
import eu.eudat.commons.enums.ActionConfirmationType;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.actionconfirmation.DmpInvitationEntity;
import eu.eudat.commons.types.actionconfirmation.EmailConfirmationEntity;
import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
import eu.eudat.commons.types.actionconfirmation.RemoveCredentialConfirmationEntity;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.ActionConfirmationEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.model.ActionConfirmation;
import eu.eudat.model.Dmp;
import eu.eudat.model.ReferenceType;
import eu.eudat.model.builder.ActionConfirmationBuilder;
import eu.eudat.model.builder.DmpBuilder;
import eu.eudat.model.deleter.ActionConfirmationDeleter;
import eu.eudat.model.persist.ActionConfirmationPersist;
import eu.eudat.model.persist.RemoveCredentialRequestPersist;
import eu.eudat.model.persist.actionconfirmation.DmpInvitationPersist;
import eu.eudat.model.persist.actionconfirmation.EmailConfirmationPersist;
import eu.eudat.model.persist.actionconfirmation.MergeAccountConfirmationPersist;
import eu.eudat.service.dmpblueprint.DmpBlueprintServiceImpl;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
@ -22,6 +29,7 @@ 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;
@ -51,12 +59,12 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
private final MessageSource messageSource;
private final XmlHandlingService xmlHandlingService;
private final ErrorThesaurusProperties errors;
private final UserScope userScope;
public ActionConfirmationServiceImpl(
EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory,
ConventionService conventionService, MessageSource messageSource,
XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors) {
EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory,
ConventionService conventionService, MessageSource messageSource,
XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors, UserScope userScope) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -65,13 +73,13 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
this.messageSource = messageSource;
this.xmlHandlingService = xmlHandlingService;
this.errors = errors;
this.userScope = userScope;
}
public void persist(ActionConfirmationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException{
public ActionConfirmation persist(ActionConfirmationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException{
logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields));
// this.authorizationService.authorizeForce(Permission.EditActionConfirmation); //TODO
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
@ -86,17 +94,19 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
data.setCreatedById(userScope.getUserId());
}
this.authorizationService.authorizeAtLeastOneForce(List.of(new OwnedResource(data.getCreatedById())), Permission.EditActionConfirmation);
data.setToken(model.getToken());
data.setCreatedById(model.getCreatedById());
data.setType(model.getType());
data.setStatus(model.getStatus());
data.setExpiresAt(model.getExpiresAt());
if (model.getType().equals(ActionConfirmationType.MergeAccount) || model.getType().equals(ActionConfirmationType.RemoveCredential)){
data.setData(this.xmlHandlingService.toXmlSafe(this.buildEmailConfirmationEntity(model.getEmailConfirmation())));
}else{
data.setData(this.xmlHandlingService.toXmlSafe(this.buildDmpInvitationEntity(model.getDmpInvitation())));
switch (model.getType()){
case MergeAccount -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildMergeAccountConfirmationEntity(model.getMergeAccountConfirmation())));
case DmpInvitation -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildDmpInvitationEntity(model.getDmpInvitation())));
case RemoveCredential -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildMergeAccountConfirmationEntity(model.getRemoveCredentialRequest())));
default -> throw new InternalError("unknown type: " + model.getType());
}
data.setUpdatedAt(Instant.now());
@ -105,6 +115,7 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
this.entityManager.flush();
return this.builderFactory.builder(ActionConfirmationBuilder.class).build(BaseFieldSet.build(fields, ActionConfirmation._id), data);
}
private @NotNull DmpInvitationEntity buildDmpInvitationEntity(DmpInvitationPersist persist){
@ -118,8 +129,8 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
return data;
}
private @NotNull EmailConfirmationEntity buildEmailConfirmationEntity(EmailConfirmationPersist persist){
EmailConfirmationEntity data = new EmailConfirmationEntity();
private @NotNull MergeAccountConfirmationEntity buildMergeAccountConfirmationEntity(MergeAccountConfirmationPersist persist){
MergeAccountConfirmationEntity data = new MergeAccountConfirmationEntity();
if (persist == null) return data;
data.setEmail(persist.getEmail());
@ -127,6 +138,15 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
return data;
}
private @NotNull RemoveCredentialConfirmationEntity buildMergeAccountConfirmationEntity(RemoveCredentialRequestPersist persist){
RemoveCredentialConfirmationEntity data = new RemoveCredentialConfirmationEntity();
if (persist == null) return data;
data.setCredentialId(persist.getCredentialId());
return data;
}
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting : {}", id);

View File

@ -833,7 +833,6 @@ public class DmpServiceImpl implements DmpService {
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(this.notificationProperties.getEmailExpirationTimeSeconds()));
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
this.actionConfirmationService.persist(persist, null);

View File

@ -2,7 +2,8 @@ package eu.eudat.service.user;
import com.fasterxml.jackson.core.JsonProcessingException;
import eu.eudat.model.User;
import eu.eudat.model.persist.UserRequestPersist;
import eu.eudat.model.persist.RemoveCredentialRequestPersist;
import eu.eudat.model.persist.UserMergeRequestPersist;
import eu.eudat.model.persist.UserPersist;
import eu.eudat.model.persist.UserRolePatchPersist;
import gr.cite.tools.exception.MyApplicationException;
@ -32,11 +33,11 @@ public interface UserService {
User patchRoles(UserRolePatchPersist model, FieldSet fields) throws InvalidApplicationException;
void sendMergeAccountConfirmation(UserRequestPersist model) throws InvalidApplicationException, JAXBException;
void sendMergeAccountConfirmation(UserMergeRequestPersist model) throws InvalidApplicationException, JAXBException;
void sendRemoveCredentialConfirmation(UserRequestPersist model) throws InvalidApplicationException, JAXBException;
void sendRemoveCredentialConfirmation(RemoveCredentialRequestPersist model) throws InvalidApplicationException, JAXBException;
void confirmMergeAccount(String token) throws InvalidApplicationException;
void confirmMergeAccount(String token) throws InvalidApplicationException, IOException;
void confirmRemoveCredential(String token) throws InvalidApplicationException;

View File

@ -12,7 +12,8 @@ import eu.eudat.commons.enums.ContactInfoType;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.enums.notification.NotificationContactType;
import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.actionconfirmation.EmailConfirmationEntity;
import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
import eu.eudat.commons.types.actionconfirmation.RemoveCredentialConfirmationEntity;
import eu.eudat.commons.types.notification.*;
import eu.eudat.commons.types.user.AdditionalInfoEntity;
import eu.eudat.commons.validation.ValidatorFactory;
@ -26,19 +27,23 @@ import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEven
import eu.eudat.integrationevent.outbox.notification.NotificationIntegrationEventHandler;
import eu.eudat.model.User;
import eu.eudat.model.UserContactInfo;
import eu.eudat.model.UserCredential;
import eu.eudat.model.builder.UserBuilder;
import eu.eudat.model.deleter.UserCredentialDeleter;
import eu.eudat.model.deleter.UserDeleter;
import eu.eudat.model.deleter.UserRoleDeleter;
import eu.eudat.model.deleter.UserSettingsSettingsDeleter;
import eu.eudat.model.persist.*;
import eu.eudat.model.persist.actionconfirmation.EmailConfirmationPersist;
import eu.eudat.model.persist.actionconfirmation.MergeAccountConfirmationPersist;
import eu.eudat.query.*;
import eu.eudat.service.actionconfirmation.ActionConfirmationService;
import eu.eudat.service.elastic.ElasticService;
import eu.eudat.service.keycloak.KeycloakRole;
import eu.eudat.service.keycloak.KeycloakService;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
@ -99,19 +104,21 @@ public class UserServiceImpl implements UserService {
private final ValidatorFactory validatorFactory;
private final ElasticService elasticService;
@Autowired
public UserServiceImpl(
EntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource,
EventBroker eventBroker,
JsonHandlingService jsonHandlingService,
XmlHandlingService xmlHandlingService, QueryFactory queryFactory,
UserScope userScope, KeycloakService keycloakService, ActionConfirmationService actionConfirmationService, NotificationProperties notificationProperties, NotificationIntegrationEventHandler eventHandler, ValidatorFactory validatorFactory) {
EntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource,
EventBroker eventBroker,
JsonHandlingService jsonHandlingService,
XmlHandlingService xmlHandlingService, QueryFactory queryFactory,
UserScope userScope, KeycloakService keycloakService, ActionConfirmationService actionConfirmationService, NotificationProperties notificationProperties, NotificationIntegrationEventHandler eventHandler, ValidatorFactory validatorFactory, ElasticService elasticService) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -129,6 +136,7 @@ public class UserServiceImpl implements UserService {
this.notificationProperties = notificationProperties;
this.eventHandler = eventHandler;
this.validatorFactory = validatorFactory;
this.elasticService = elasticService;
}
//region persist
@ -343,12 +351,14 @@ public class UserServiceImpl implements UserService {
//endregion
//notifications
public void sendMergeAccountConfirmation(UserRequestPersist model) throws InvalidApplicationException, JAXBException {
UserEntity user = this.queryFactory.query(UserQuery.class).ids(model.getUserId()).isActive(IsActive.Active).first();
if (user == null){
throw new MyApplicationException("User don't exist");
}
String token = this.createActionConfirmation(model.getEmail(), ActionConfirmationType.MergeAccount);
public void sendMergeAccountConfirmation(UserMergeRequestPersist model) throws InvalidApplicationException, JAXBException {
UserContactInfoEntity userContactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(model.getEmail()).types(ContactInfoType.Email).first();
if (userContactInfoEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getEmail(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserEntity user = this.queryFactory.query(UserQuery.class).ids(userContactInfoEntity.getUserId()).isActive(IsActive.Active).first();
if (user == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userContactInfoEntity.getUserId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
String token = this.createMergeAccountConfirmation(model.getEmail());
createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.EMAIL);
createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.IN_APP);
}
@ -372,52 +382,54 @@ public class UserServiceImpl implements UserService {
eventHandler.handle(event);
}
public void sendRemoveCredentialConfirmation(UserRequestPersist model) throws InvalidApplicationException, JAXBException {
public void sendRemoveCredentialConfirmation(RemoveCredentialRequestPersist model) throws InvalidApplicationException, JAXBException {
UserCredentialEntity data = this.entityManager.find(UserCredentialEntity.class, model.getCredentialId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getCredentialId(), UserCredentialEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!data.getUserId().equals(this.userScope.getUserId())) throw new MyForbiddenException(this.errors.getForbidden().getCode(), this.errors.getForbidden().getMessage());
UserQuery userQuery = this.queryFactory.query(UserQuery.class).ids(model.getUserId()).isActive(IsActive.Active);
if (userQuery == null || userQuery.count() == 0){
throw new MyApplicationException("User don't exist");
}
UserContactInfoEntity userContactInfo = this.queryFactory.query(UserContactInfoQuery.class).types(ContactInfoType.Email).userIds(model.getUserId()).values(model.getEmail()).first();
if(userContactInfo == null){
throw new MyApplicationException("Email does not exist in this user!");
}
UserCredentialQuery query = this.queryFactory.query(UserCredentialQuery.class).userIds(model.getUserId());
if (query == null || query.count() == 0){
throw new MyApplicationException("This user don't have credential!");
}
String token = this.createActionConfirmation(model.getEmail(), ActionConfirmationType.RemoveCredential);
this.createRemoveCredentialNotificationEvent(token, model.getEmail(), model.getUserId(), NotificationContactType.EMAIL);
this.createRemoveCredentialNotificationEvent(token, model.getEmail(), model.getUserId(), NotificationContactType.IN_APP);
String token = this.createRemoveConfirmation(data.getId());
this.createRemoveCredentialNotificationEvent(token, data.getUserId(), NotificationContactType.EMAIL);
this.createRemoveCredentialNotificationEvent(token, data.getUserId(), NotificationContactType.IN_APP);
}
private void createRemoveCredentialNotificationEvent(String token, String email, UUID userId, NotificationContactType type) throws InvalidApplicationException {
private void createRemoveCredentialNotificationEvent(String token, UUID userId, NotificationContactType type) throws InvalidApplicationException {
NotificationIntegrationEvent event = new NotificationIntegrationEvent();
event.setUserId(userId);
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(type);
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(this.notificationProperties.getEmailExpirationTimeSeconds())));
data.setFields(fieldInfoList);
event.setData(jsonHandlingService.toJsonSafe(data));
eventHandler.handle(event);
}
private String createActionConfirmation(String email, ActionConfirmationType type) throws JAXBException, InvalidApplicationException {
private String createMergeAccountConfirmation(String email) throws JAXBException, InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(type);
persist.setType(ActionConfirmationType.MergeAccount);
persist.setStatus(ActionConfirmationStatus.Requested);
persist.setToken(UUID.randomUUID().toString());
persist.setEmailConfirmation(new EmailConfirmationPersist(email));
persist.setCreatedById(this.userScope.getUserId());
persist.setMergeAccountConfirmation(new MergeAccountConfirmationPersist());
persist.getMergeAccountConfirmation().setEmail(email);
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
this.actionConfirmationService.persist(persist, null);
return persist.getToken();
}
private String createRemoveConfirmation(UUID credentialId) throws JAXBException, InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(ActionConfirmationType.RemoveCredential);
persist.setStatus(ActionConfirmationStatus.Requested);
persist.setToken(UUID.randomUUID().toString());
persist.setRemoveCredentialRequest(new RemoveCredentialRequestPersist());
persist.getRemoveCredentialRequest().setCredentialId(credentialId);
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
this.actionConfirmationService.persist(persist, null);
@ -433,19 +445,137 @@ public class UserServiceImpl implements UserService {
return (hour + ":" + min + ":" + sec);
}
public void confirmMergeAccount(String token) throws InvalidApplicationException {
public void confirmMergeAccount(String token) throws IOException, 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());
MergeAccountConfirmationEntity mergeAccountConfirmationEntity = this.xmlHandlingService.fromXmlSafe(MergeAccountConfirmationEntity.class, action.getData());
if (mergeAccountConfirmationEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{mergeAccountConfirmationEntity, MergeAccountConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserContactInfoEntity userContactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(mergeAccountConfirmationEntity.getEmail()).types(ContactInfoType.Email).first();
if (userContactInfoEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{mergeAccountConfirmationEntity.getEmail(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserEntity userToBeMerge = this.queryFactory.query(UserQuery.class).ids(userContactInfoEntity.getUserId()).isActive(IsActive.Active).first();
if (userToBeMerge == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userContactInfoEntity.getUserId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.userScope.getUserIdSafe().equals(userToBeMerge.getId())) throw new MyForbiddenException("Only requested user can approve");
UserEntity newUser = this.queryFactory.query(UserQuery.class).ids(action.getCreatedById()).isActive(IsActive.Active).first();
if (newUser == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{action.getCreatedById(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!newUser.getId().equals(userToBeMerge.getId())){
this.mergeNewUserToOld(newUser, userToBeMerge);
}
action.setUpdatedAt(Instant.now());
action.setStatus(ActionConfirmationStatus.Accepted);
this.entityManager.merge(action);
this.entityManager.flush();
}
private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser) throws IOException, InvalidApplicationException {
List<UserCredentialEntity> userCredentials = this.queryFactory.query(UserCredentialQuery.class).userIds(oldUser.getId()).collect();
for (UserCredentialEntity userCredential : userCredentials){
userCredential.setUserId(newUser.getId());
this.entityManager.merge(userCredential);
}
List<UserContactInfoEntity> userContactInfos = this.queryFactory.query(UserContactInfoQuery.class).userIds(oldUser.getId()).collect();
UserContactInfoQuery newUserContactInfoQuery = this.queryFactory.query(UserContactInfoQuery.class).userIds(newUser.getId());
newUserContactInfoQuery.setOrder(new Ordering().addDescending(UserContactInfo._ordinal));
UserContactInfoEntity newUserContactInfo = newUserContactInfoQuery.first();
int ordinal = newUserContactInfo == null ? 0 : newUserContactInfo.getOrdinal() + 1;
for (UserContactInfoEntity userContactInfo : userContactInfos){
userContactInfo.setUserId(newUser.getId());
userContactInfo.setOrdinal(ordinal);
this.entityManager.merge(userContactInfo);
ordinal++;
}
List<UserRoleEntity> userRoles = this.queryFactory.query(UserRoleQuery.class).userIds(oldUser.getId()).collect();
List<UserRoleEntity> newUserRoles = this.queryFactory.query(UserRoleQuery.class).userIds(newUser.getId()).collect();
List<UserRoleEntity> rolesToDelete = new ArrayList<>();
for (UserRoleEntity userRole : userRoles){
if (newUserRoles.stream().anyMatch(x-> x.getRole().equals(userRole.getRole()))) {
rolesToDelete.add(userRole);
} else {
userRole.setUserId(newUser.getId());
this.entityManager.merge(userRole);
}
}
this.deleterFactory.deleter(UserRoleDeleter.class).delete(rolesToDelete);
List<UserSettingsEntity> userSettings = this.queryFactory.query(UserSettingsQuery.class).entityIds(oldUser.getId()).collect();
List<UserSettingsEntity> newUserSettings = this.queryFactory.query(UserSettingsQuery.class).entityIds(newUser.getId()).collect();
List<UserSettingsEntity> userSettingsToDelete = new ArrayList<>();
for (UserSettingsEntity userSetting : userSettings){
if (newUserSettings.stream().anyMatch(x-> x.getKey().equals(userSetting.getKey()))) {
userSettingsToDelete.add(userSetting);
} else {
userSetting.setEntityId(newUser.getId());
this.entityManager.merge(userSetting);
}
}
this.deleterFactory.deleter(UserSettingsSettingsDeleter.class).delete(userSettingsToDelete);
List<TagEntity> tags = this.queryFactory.query(TagQuery.class).createdByIds(oldUser.getId()).collect();
for (TagEntity tag : tags){
tag.setCreatedById(newUser.getId());
this.entityManager.merge(tag);
}
List<StorageFileEntity> storageFiles = this.queryFactory.query(StorageFileQuery.class).ownerIds(oldUser.getId()).collect();
for (StorageFileEntity storageFile : storageFiles){
storageFile.setOwnerId(newUser.getId());
this.entityManager.merge(storageFile);
}
List<LockEntity> locks = this.queryFactory.query(LockQuery.class).lockedByIds(oldUser.getId()).collect();
for (LockEntity lock : locks){
lock.setLockedBy(newUser.getId());
this.entityManager.merge(lock);
}
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class).userIds(oldUser.getId()).collect();
for (DmpUserEntity dmpUser : dmpUsers){
dmpUser.setUserId(newUser.getId());
this.entityManager.merge(dmpUser);
}
List<UserDescriptionTemplateEntity> userDescriptionTemplates = this.queryFactory.query(UserDescriptionTemplateQuery.class).userIds(oldUser.getId()).collect();
for (UserDescriptionTemplateEntity userDescriptionTemplate : userDescriptionTemplates){
userDescriptionTemplate.setUserId(newUser.getId());
this.entityManager.merge(userDescriptionTemplate);
}
List<DmpEntity> dmps = this.queryFactory.query(DmpQuery.class).creatorIds(oldUser.getId()).collect();
for (DmpEntity dmp : dmps){
dmp.setCreatorId(newUser.getId());
this.entityManager.merge(dmp);
}
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class).createdByIds(oldUser.getId()).collect();
for (DescriptionEntity description : descriptions){
description.setCreatedById(newUser.getId());
this.entityManager.merge(description);
}
//TODO merge
// this.entityManager.merge(action);
oldUser.setIsActive(IsActive.Inactive);
this.entityManager.merge(oldUser);
this.entityManager.flush();
for (DmpEntity dmp : dmps){
this.elasticService.persistDmp(dmp);
}
for (DescriptionEntity description : descriptions){
this.elasticService.persistDescription(description);
}
}
@ -456,14 +586,21 @@ public class UserServiceImpl implements UserService {
this.checkActionState(action);
UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).userIds(this.userScope.getUserIdSafe()).first();
if (userCredential == null){
throw new MyApplicationException("This user does not have credential");
}
this.deleterFactory.deleter(UserCredentialDeleter.class).deleteAndSaveByIds(List.of(userCredential.getId()));
RemoveCredentialConfirmationEntity removeCredentialConfirmationEntity = this.xmlHandlingService.fromXmlSafe(RemoveCredentialConfirmationEntity.class, action.getData());
if (removeCredentialConfirmationEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialConfirmationEntity, RemoveCredentialConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserCredentialEntity userCredentialEntity = this.queryFactory.query(UserCredentialQuery.class).ids(removeCredentialConfirmationEntity.getCredentialId()).first();
if (userCredentialEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialConfirmationEntity.getCredentialId(), UserCredential.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.userScope.getUserIdSafe().equals(userCredentialEntity.getId())) throw new MyForbiddenException("Only requested user can approve");
this.deleterFactory.deleter(UserCredentialDeleter.class).delete(List.of(userCredentialEntity));
action.setUpdatedAt(Instant.now());
action.setStatus(ActionConfirmationStatus.Accepted);
this.entityManager.merge(action);
this.entityManager.flush();
}
private void checkActionState(ActionConfirmationEntity action) throws MyApplicationException {

View File

@ -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<Module> 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);
}
}

View File

@ -14,16 +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.UserRequestPersist;
import eu.eudat.model.persist.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;
@ -38,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.*;
@ -132,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));
@ -180,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<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
@ -271,10 +268,10 @@ public class UserController {
this.auditService.track(AuditableAction.User_Delete, "id", id);
}
@PostMapping("mine/merge-account-request/{email}")
@PostMapping("mine/merge-account-request")
@Transactional
@ValidationFilterAnnotation(validator = UserRequestPersist.UserRequestPersistValidator.ValidatorName, argumentName = "model")
public Boolean mergeAccount(@RequestBody UserRequestPersist model) throws InvalidApplicationException, JAXBException {
@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(model);
@ -288,7 +285,7 @@ public class UserController {
@GetMapping("mine/confirm-merge-account/token/{token}")
@Transactional
public Boolean 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);
@ -300,10 +297,10 @@ public class UserController {
return true;
}
@PostMapping("mine/remove-credential-request/{email}")
@PostMapping("mine/remove-credential-request")
@Transactional
@ValidationFilterAnnotation(validator = UserRequestPersist.UserRequestPersistValidator.ValidatorName, argumentName = "model")
public Boolean removeCredentialAccount(@RequestBody UserRequestPersist model) throws InvalidApplicationException, JAXBException {
@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(model);

View File

@ -457,6 +457,7 @@ permissions:
BrowseReference:
roles:
- Admin
- User
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
@ -711,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