2023-11-20 16:08:43 +01:00
|
|
|
package eu.eudat.service.user;
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
2023-11-20 16:08:43 +01:00
|
|
|
import eu.eudat.authorization.AuthorizationFlags;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.authorization.OwnedResource;
|
2023-11-20 16:08:43 +01:00
|
|
|
import eu.eudat.authorization.Permission;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.commons.JsonHandlingService;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.commons.XmlHandlingService;
|
|
|
|
import eu.eudat.commons.enums.ActionConfirmationStatus;
|
|
|
|
import eu.eudat.commons.enums.ActionConfirmationType;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.commons.enums.ContactInfoType;
|
2023-11-20 16:08:43 +01:00
|
|
|
import eu.eudat.commons.enums.IsActive;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.commons.enums.notification.NotificationContactType;
|
2023-11-29 16:41:15 +01:00
|
|
|
import eu.eudat.commons.scope.user.UserScope;
|
2024-01-15 12:57:33 +01:00
|
|
|
import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
|
2024-01-15 17:03:12 +01:00
|
|
|
import eu.eudat.commons.types.actionconfirmation.RemoveCredentialRequestEntity;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.commons.types.notification.*;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.commons.types.user.AdditionalInfoEntity;
|
2024-01-16 11:56:48 +01:00
|
|
|
import eu.eudat.commons.types.usercredential.UserCredentialDataEntity;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.configurations.notification.NotificationProperties;
|
2023-11-20 16:08:43 +01:00
|
|
|
import eu.eudat.convention.ConventionService;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.data.*;
|
2023-11-20 16:08:43 +01:00
|
|
|
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.event.UserTouchedEvent;
|
2023-11-20 16:08:43 +01:00
|
|
|
import eu.eudat.event.EventBroker;
|
2024-01-19 14:12:33 +01:00
|
|
|
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
|
|
|
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
2024-01-29 17:10:55 +01:00
|
|
|
import eu.eudat.integrationevent.outbox.userremoval.UserRemovalIntegrationEventHandler;
|
|
|
|
import eu.eudat.integrationevent.outbox.usertouched.UserTouchedIntegrationEventHandler;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.model.User;
|
|
|
|
import eu.eudat.model.UserContactInfo;
|
2024-01-15 12:57:33 +01:00
|
|
|
import eu.eudat.model.UserCredential;
|
2023-11-20 16:09:24 +01:00
|
|
|
import eu.eudat.model.builder.UserBuilder;
|
2024-01-16 11:56:48 +01:00
|
|
|
import eu.eudat.model.deleter.*;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.model.persist.*;
|
2024-01-15 12:57:33 +01:00
|
|
|
import eu.eudat.model.persist.actionconfirmation.MergeAccountConfirmationPersist;
|
2024-01-15 17:03:12 +01:00
|
|
|
import eu.eudat.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
|
2023-12-14 17:19:43 +01:00
|
|
|
import eu.eudat.query.*;
|
|
|
|
import eu.eudat.service.actionconfirmation.ActionConfirmationService;
|
2024-01-15 12:57:33 +01:00
|
|
|
import eu.eudat.service.elastic.ElasticService;
|
2023-12-08 10:48:32 +01:00
|
|
|
import eu.eudat.service.keycloak.KeycloakRole;
|
|
|
|
import eu.eudat.service.keycloak.KeycloakService;
|
2023-11-20 16:08:43 +01:00
|
|
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
|
|
|
import gr.cite.tools.data.builder.BuilderFactory;
|
|
|
|
import gr.cite.tools.data.deleter.DeleterFactory;
|
2024-01-15 12:57:33 +01:00
|
|
|
import gr.cite.tools.data.query.Ordering;
|
2023-11-20 16:09:24 +01:00
|
|
|
import gr.cite.tools.data.query.QueryFactory;
|
2023-11-20 16:08:43 +01:00
|
|
|
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;
|
2024-01-17 10:20:02 +01:00
|
|
|
import gr.cite.tools.validation.ValidatorFactory;
|
2023-11-20 16:08:43 +01:00
|
|
|
import jakarta.persistence.EntityManager;
|
2023-12-14 17:19:43 +01:00
|
|
|
import jakarta.xml.bind.JAXBException;
|
2023-11-20 16:09:24 +01:00
|
|
|
import org.apache.commons.csv.CSVFormat;
|
|
|
|
import org.apache.commons.csv.CSVPrinter;
|
|
|
|
import org.apache.commons.csv.QuoteMode;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
2023-11-20 16:08:43 +01:00
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
import org.springframework.context.MessageSource;
|
|
|
|
import org.springframework.context.i18n.LocaleContextHolder;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import javax.management.InvalidApplicationException;
|
2023-11-20 16:09:24 +01:00
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.PrintWriter;
|
2023-11-20 16:08:43 +01:00
|
|
|
import java.time.Instant;
|
2024-01-04 15:25:07 +01:00
|
|
|
import java.util.*;
|
2023-11-20 16:09:24 +01:00
|
|
|
import java.util.stream.Collectors;
|
2023-11-20 16:08:43 +01:00
|
|
|
|
|
|
|
@Service
|
2023-11-20 16:09:24 +01:00
|
|
|
public class UserServiceImpl implements UserService {
|
2023-11-20 16:08:43 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserServiceImpl.class));
|
2023-11-20 16:08:43 +01:00
|
|
|
|
|
|
|
private final EntityManager entityManager;
|
|
|
|
|
|
|
|
private final AuthorizationService authorizationService;
|
|
|
|
|
|
|
|
private final DeleterFactory deleterFactory;
|
|
|
|
|
|
|
|
private final BuilderFactory builderFactory;
|
|
|
|
|
|
|
|
private final ConventionService conventionService;
|
|
|
|
|
|
|
|
private final ErrorThesaurusProperties errors;
|
|
|
|
|
|
|
|
private final MessageSource messageSource;
|
|
|
|
private final EventBroker eventBroker;
|
2023-11-20 16:09:24 +01:00
|
|
|
private final JsonHandlingService jsonHandlingService;
|
2023-12-14 17:19:43 +01:00
|
|
|
private final XmlHandlingService xmlHandlingService;
|
2023-11-20 16:09:24 +01:00
|
|
|
private final QueryFactory queryFactory;
|
2023-11-29 16:41:15 +01:00
|
|
|
private final UserScope userScope;
|
2023-12-08 10:48:32 +01:00
|
|
|
|
|
|
|
private final KeycloakService keycloakService;
|
2023-12-14 17:19:43 +01:00
|
|
|
private final ActionConfirmationService actionConfirmationService;
|
|
|
|
private final NotificationProperties notificationProperties;
|
2024-01-19 14:12:33 +01:00
|
|
|
private final NotifyIntegrationEventHandler eventHandler;
|
2023-12-08 10:48:32 +01:00
|
|
|
|
2023-12-21 17:45:49 +01:00
|
|
|
private final ValidatorFactory validatorFactory;
|
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
private final ElasticService elasticService;
|
2024-01-29 17:10:55 +01:00
|
|
|
private final UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler;
|
|
|
|
private final UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler;
|
|
|
|
|
2023-11-20 16:08:43 +01:00
|
|
|
@Autowired
|
2023-11-20 16:09:24 +01:00
|
|
|
public UserServiceImpl(
|
2024-01-29 17:10:55 +01:00
|
|
|
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, NotifyIntegrationEventHandler eventHandler, ValidatorFactory validatorFactory, ElasticService elasticService, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler) {
|
2023-11-20 16:08:43 +01:00
|
|
|
this.entityManager = entityManager;
|
|
|
|
this.authorizationService = authorizationService;
|
|
|
|
this.deleterFactory = deleterFactory;
|
|
|
|
this.builderFactory = builderFactory;
|
|
|
|
this.conventionService = conventionService;
|
|
|
|
this.errors = errors;
|
|
|
|
this.messageSource = messageSource;
|
|
|
|
this.eventBroker = eventBroker;
|
2023-11-20 16:09:24 +01:00
|
|
|
this.jsonHandlingService = jsonHandlingService;
|
2023-12-14 17:19:43 +01:00
|
|
|
this.xmlHandlingService = xmlHandlingService;
|
2023-11-20 16:09:24 +01:00
|
|
|
this.queryFactory = queryFactory;
|
2023-11-29 16:41:15 +01:00
|
|
|
this.userScope = userScope;
|
2023-12-08 10:48:32 +01:00
|
|
|
this.keycloakService = keycloakService;
|
2023-12-14 17:19:43 +01:00
|
|
|
this.actionConfirmationService = actionConfirmationService;
|
|
|
|
this.notificationProperties = notificationProperties;
|
|
|
|
this.eventHandler = eventHandler;
|
2023-12-21 17:45:49 +01:00
|
|
|
this.validatorFactory = validatorFactory;
|
2024-01-15 12:57:33 +01:00
|
|
|
this.elasticService = elasticService;
|
2024-01-29 17:10:55 +01:00
|
|
|
this.userTouchedIntegrationEventHandler = userTouchedIntegrationEventHandler;
|
|
|
|
this.userRemovalIntegrationEventHandler = userRemovalIntegrationEventHandler;
|
2023-11-20 16:08:43 +01:00
|
|
|
}
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
//region persist
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public User persist(UserPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException {
|
|
|
|
logger.debug(new MapLogEntry("persisting data User").And("model", model).And("fields", fields));
|
2023-11-20 16:08:43 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
this.authorizationService.authorizeAtLeastOneForce(model.getId() != null ? List.of(new OwnedResource(model.getId())) : null, Permission.EditUser);
|
|
|
|
|
2023-11-20 16:08:43 +01:00
|
|
|
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
UserEntity data;
|
2023-11-20 16:08:43 +01:00
|
|
|
if (isUpdate) {
|
2023-11-20 16:09:24 +01:00
|
|
|
data = this.entityManager.find(UserEntity.class, model.getId());
|
|
|
|
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2023-11-20 16:08:43 +01:00
|
|
|
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
|
|
|
} else {
|
2023-11-20 16:09:24 +01:00
|
|
|
data = new UserEntity();
|
2023-11-20 16:08:43 +01:00
|
|
|
data.setId(UUID.randomUUID());
|
|
|
|
data.setIsActive(IsActive.Active);
|
|
|
|
data.setCreatedAt(Instant.now());
|
|
|
|
}
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
data.setAdditionalInfo(this.jsonHandlingService.toJson(this.buildAdditionalInfoEntity(model.getAdditionalInfo())));
|
|
|
|
|
2023-11-20 16:08:43 +01:00
|
|
|
data.setName(model.getName());
|
|
|
|
data.setUpdatedAt(Instant.now());
|
2023-11-20 16:09:24 +01:00
|
|
|
if (isUpdate) this.entityManager.merge(data);
|
|
|
|
else this.entityManager.persist(data);
|
2023-11-20 16:08:43 +01:00
|
|
|
|
|
|
|
this.entityManager.flush();
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
2024-01-29 17:10:55 +01:00
|
|
|
|
|
|
|
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
2023-11-20 16:09:24 +01:00
|
|
|
return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, User._id), data);
|
2023-11-20 16:08:43 +01:00
|
|
|
}
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
private @NotNull AdditionalInfoEntity buildAdditionalInfoEntity(UserAdditionalInfoPersist persist){
|
|
|
|
AdditionalInfoEntity data = new AdditionalInfoEntity();
|
|
|
|
if (persist == null) return data;
|
|
|
|
data.setOrganizationId(persist.getOrganizationId());
|
|
|
|
data.setRoleOrganization(persist.getRoleOrganization());
|
|
|
|
data.setCulture(persist.getCulture());
|
|
|
|
data.setTimezone(persist.getTimezone());
|
|
|
|
data.setLanguage(persist.getLanguage());
|
|
|
|
data.setAvatarUrl(persist.getAvatarUrl());
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
//region delete
|
|
|
|
|
|
|
|
@Override
|
2023-11-20 16:08:43 +01:00
|
|
|
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
|
2023-11-20 16:09:24 +01:00
|
|
|
logger.debug("deleting User: {}", id);
|
2023-11-20 16:08:43 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
this.authorizationService.authorizeForce(Permission.DeleteUser);
|
2023-11-20 16:08:43 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id));
|
2024-01-29 17:10:55 +01:00
|
|
|
this.userRemovalIntegrationEventHandler.handle(id);
|
2023-11-20 16:08:43 +01:00
|
|
|
}
|
2023-11-20 16:09:24 +01:00
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
//region export
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public byte[] exportCsv() throws IOException {
|
|
|
|
this.authorizationService.authorizeForce(Permission.ExportUsers);
|
|
|
|
|
|
|
|
FieldSet fieldSet = new BaseFieldSet().ensure(User._id).ensure(User._name).ensure(User._contacts + "." + UserContactInfo._value).ensure(User._contacts + "." + UserContactInfo._type);
|
|
|
|
List<User> users = this.builderFactory.builder(UserBuilder.class).build(fieldSet, this.queryFactory.query(UserQuery.class).collectAs(fieldSet));
|
|
|
|
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
|
final CSVFormat format = CSVFormat.DEFAULT.withHeader("User Id", "User Name", "User Email").withQuoteMode(QuoteMode.NON_NUMERIC);
|
|
|
|
final CSVPrinter csvPrinter = new CSVPrinter(new PrintWriter(out), format);
|
|
|
|
|
|
|
|
for (User user : users) {
|
|
|
|
csvPrinter.printRecord(user.getId(), user.getName(), (user.getContacts() != null ? String.join(" ", user.getContacts().stream().filter(x-> ContactInfoType.Email.equals(x.getType())).map(UserContactInfo::getValue).toList()) : ""));
|
|
|
|
}
|
|
|
|
|
|
|
|
csvPrinter.flush();
|
|
|
|
return out.toByteArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public User patchRoles(UserRolePatchPersist model, FieldSet fields) throws InvalidApplicationException {
|
|
|
|
logger.debug(new MapLogEntry("persisting data UserRole").And("model", model).And("fields", fields));
|
|
|
|
this.authorizationService.authorizeForce(Permission.EditUser);
|
|
|
|
|
|
|
|
UserEntity data = this.entityManager.find(UserEntity.class, model.getId());
|
|
|
|
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
|
|
|
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
|
|
|
|
2023-12-12 15:17:08 +01:00
|
|
|
List<UserCredentialEntity> userCredentials = this.queryFactory.query(UserCredentialQuery.class).userIds(data.getId()).collect();
|
2023-12-12 16:04:01 +01:00
|
|
|
if (userCredentials.isEmpty())
|
|
|
|
throw new MyApplicationException("Currently cannot update roles for this user");
|
|
|
|
if (userCredentials.getFirst().getExternalId() == null)
|
|
|
|
throw new MyApplicationException("Currently cannot update roles for this user");
|
|
|
|
UUID subjectId = UUID.fromString(userCredentials.getFirst().getExternalId());
|
|
|
|
|
2023-12-12 15:17:08 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(data.getId()).collect();
|
|
|
|
List<UUID> foundIds = new ArrayList<>();
|
|
|
|
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank()).distinct().toList()) {
|
|
|
|
UserRoleEntity item = existingItems.stream().filter(x-> x.getRole().equals(roleName)).findFirst().orElse(null);
|
|
|
|
if (item == null) {
|
|
|
|
item = new UserRoleEntity();
|
|
|
|
item.setId(UUID.randomUUID());
|
|
|
|
item.setUserId(data.getId());
|
|
|
|
item.setRole(roleName);
|
|
|
|
item.setCreatedAt(Instant.now());
|
|
|
|
this.entityManager.persist(item);
|
2023-12-12 16:04:01 +01:00
|
|
|
this.keycloakService.addUserToGroup(subjectId, KeycloakRole.valueOf(roleName));
|
2023-11-20 16:09:24 +01:00
|
|
|
}
|
|
|
|
foundIds.add(item.getId());
|
|
|
|
}
|
2023-11-20 16:08:43 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
this.entityManager.flush();
|
|
|
|
|
|
|
|
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
|
2023-12-12 16:04:01 +01:00
|
|
|
toDelete.forEach(x -> this.keycloakService.removeUserFromGroup(subjectId, KeycloakRole.valueOf(x.getRole())));
|
2023-11-20 16:09:24 +01:00
|
|
|
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
|
2023-11-20 16:08:43 +01:00
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
this.entityManager.flush();
|
|
|
|
|
|
|
|
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
2024-01-29 17:10:55 +01:00
|
|
|
|
|
|
|
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
2023-11-20 16:09:24 +01:00
|
|
|
return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, User._id), data);
|
|
|
|
}
|
2023-12-14 17:19:43 +01:00
|
|
|
|
2023-11-29 16:41:15 +01:00
|
|
|
//region mine
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void updateLanguageMine(String language) throws JsonProcessingException {
|
|
|
|
logger.debug(new MapLogEntry("persisting User language").And("language", language));
|
|
|
|
|
|
|
|
UUID userId = this.userScope.getUserIdSafe();
|
|
|
|
|
|
|
|
if (userId == null) throw new MyForbiddenException(this.errors.getForbidden().getCode(), this.errors.getForbidden().getMessage());
|
|
|
|
|
|
|
|
|
|
|
|
UserEntity data = this.entityManager.find(UserEntity.class, userId);
|
2023-11-29 16:49:00 +01:00
|
|
|
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userId, User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2023-11-29 16:41:15 +01:00
|
|
|
|
|
|
|
AdditionalInfoEntity additionalInfoEntity = this.jsonHandlingService.fromJsonSafe(AdditionalInfoEntity.class, data.getAdditionalInfo());
|
|
|
|
if (additionalInfoEntity == null) additionalInfoEntity = new AdditionalInfoEntity();
|
|
|
|
additionalInfoEntity.setLanguage(language);
|
|
|
|
|
|
|
|
data.setAdditionalInfo(this.jsonHandlingService.toJson(additionalInfoEntity));
|
|
|
|
|
|
|
|
data.setUpdatedAt(Instant.now());
|
|
|
|
this.entityManager.merge(data);
|
|
|
|
|
|
|
|
this.entityManager.flush();
|
|
|
|
|
2024-01-29 17:10:55 +01:00
|
|
|
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
|
|
|
|
2023-11-29 16:41:15 +01:00
|
|
|
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void updateTimezoneMine(String timezone) throws JsonProcessingException {
|
|
|
|
logger.debug(new MapLogEntry("persisting User timezone").And("timezone", timezone));
|
|
|
|
|
|
|
|
UUID userId = this.userScope.getUserIdSafe();
|
|
|
|
|
|
|
|
if (userId == null) throw new MyForbiddenException(this.errors.getForbidden().getCode(), this.errors.getForbidden().getMessage());
|
|
|
|
|
|
|
|
|
|
|
|
UserEntity data = this.entityManager.find(UserEntity.class, userId);
|
2023-11-29 16:49:00 +01:00
|
|
|
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userId, User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2023-11-29 16:41:15 +01:00
|
|
|
|
|
|
|
AdditionalInfoEntity additionalInfoEntity = this.jsonHandlingService.fromJsonSafe(AdditionalInfoEntity.class, data.getAdditionalInfo());
|
|
|
|
if (additionalInfoEntity == null) additionalInfoEntity = new AdditionalInfoEntity();
|
|
|
|
additionalInfoEntity.setTimezone(timezone);
|
|
|
|
|
|
|
|
data.setAdditionalInfo(this.jsonHandlingService.toJson(additionalInfoEntity));
|
|
|
|
|
|
|
|
data.setUpdatedAt(Instant.now());
|
|
|
|
this.entityManager.merge(data);
|
|
|
|
|
|
|
|
this.entityManager.flush();
|
|
|
|
|
2024-01-29 17:10:55 +01:00
|
|
|
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
|
|
|
|
2023-11-29 16:41:15 +01:00
|
|
|
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void updateCultureMine(String culture) throws JsonProcessingException {
|
|
|
|
logger.debug(new MapLogEntry("persisting User culture").And("culture", culture));
|
|
|
|
|
|
|
|
UUID userId = this.userScope.getUserIdSafe();
|
|
|
|
|
|
|
|
if (userId == null) throw new MyForbiddenException(this.errors.getForbidden().getCode(), this.errors.getForbidden().getMessage());
|
|
|
|
|
|
|
|
UserEntity data = this.entityManager.find(UserEntity.class, userId);
|
2023-11-29 16:49:00 +01:00
|
|
|
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userId, User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2023-11-29 16:41:15 +01:00
|
|
|
|
|
|
|
AdditionalInfoEntity additionalInfoEntity = this.jsonHandlingService.fromJsonSafe(AdditionalInfoEntity.class, data.getAdditionalInfo());
|
|
|
|
if (additionalInfoEntity == null) additionalInfoEntity = new AdditionalInfoEntity();
|
|
|
|
additionalInfoEntity.setCulture(culture);
|
|
|
|
|
|
|
|
data.setAdditionalInfo(this.jsonHandlingService.toJson(additionalInfoEntity));
|
|
|
|
|
|
|
|
data.setUpdatedAt(Instant.now());
|
|
|
|
this.entityManager.merge(data);
|
|
|
|
|
|
|
|
this.entityManager.flush();
|
|
|
|
|
2024-01-29 17:10:55 +01:00
|
|
|
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
|
|
|
|
2023-11-29 16:41:15 +01:00
|
|
|
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
|
|
|
}
|
|
|
|
|
|
|
|
//endregion
|
2023-12-14 17:19:43 +01:00
|
|
|
|
|
|
|
//notifications
|
2024-01-15 12:57:33 +01:00
|
|
|
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());
|
2024-01-10 16:46:45 +01:00
|
|
|
createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.EMAIL);
|
|
|
|
createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.IN_APP);
|
|
|
|
}
|
2023-12-14 17:19:43 +01:00
|
|
|
|
2024-01-10 16:46:45 +01:00
|
|
|
private void createMergeNotificationEvent(String token, UserEntity user, String email, NotificationContactType type) throws InvalidApplicationException {
|
2024-01-19 14:12:33 +01:00
|
|
|
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
2024-01-10 16:46:45 +01:00
|
|
|
event.setUserId(user.getId());
|
2023-12-14 17:19:43 +01:00
|
|
|
List<ContactPair> contactPairs = new ArrayList<>();
|
|
|
|
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
|
|
|
|
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
|
|
|
|
event.setContactHint(jsonHandlingService.toJsonSafe(contactData));
|
2024-01-10 16:46:45 +01:00
|
|
|
event.setContactTypeHint(type);
|
2024-01-04 15:25:07 +01:00
|
|
|
event.setNotificationType(notificationProperties.getMergeAccountConfirmationType());
|
2023-12-14 17:19:43 +01:00
|
|
|
NotificationFieldData data = new NotificationFieldData();
|
|
|
|
List<FieldInfo> fieldInfoList = new ArrayList<>();
|
2024-01-10 16:46:45 +01:00
|
|
|
fieldInfoList.add(new FieldInfo("{userName}", DataType.String, user.getName()));
|
2023-12-15 10:51:08 +01:00
|
|
|
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
|
2024-01-04 15:25:07 +01:00
|
|
|
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
|
2023-12-14 17:19:43 +01:00
|
|
|
data.setFields(fieldInfoList);
|
|
|
|
event.setData(jsonHandlingService.toJsonSafe(data));
|
|
|
|
eventHandler.handle(event);
|
|
|
|
}
|
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
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());
|
2023-12-14 17:19:43 +01:00
|
|
|
|
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
String token = this.createRemoveConfirmation(data.getId());
|
|
|
|
this.createRemoveCredentialNotificationEvent(token, data.getUserId(), NotificationContactType.EMAIL);
|
|
|
|
this.createRemoveCredentialNotificationEvent(token, data.getUserId(), NotificationContactType.IN_APP);
|
2024-01-10 16:46:45 +01:00
|
|
|
}
|
2023-12-14 17:19:43 +01:00
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
private void createRemoveCredentialNotificationEvent(String token, UUID userId, NotificationContactType type) throws InvalidApplicationException {
|
2024-01-19 14:12:33 +01:00
|
|
|
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
2024-01-10 16:46:45 +01:00
|
|
|
event.setUserId(userId);
|
|
|
|
event.setContactTypeHint(type);
|
2024-01-04 15:25:07 +01:00
|
|
|
event.setNotificationType(notificationProperties.getRemoveCredentialConfirmationType());
|
2023-12-14 17:19:43 +01:00
|
|
|
NotificationFieldData data = new NotificationFieldData();
|
|
|
|
List<FieldInfo> fieldInfoList = new ArrayList<>();
|
2023-12-15 10:51:08 +01:00
|
|
|
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
|
2024-01-04 15:25:07 +01:00
|
|
|
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
|
2023-12-14 17:19:43 +01:00
|
|
|
data.setFields(fieldInfoList);
|
|
|
|
event.setData(jsonHandlingService.toJsonSafe(data));
|
|
|
|
eventHandler.handle(event);
|
|
|
|
}
|
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
private String createMergeAccountConfirmation(String email) throws JAXBException, InvalidApplicationException {
|
|
|
|
ActionConfirmationPersist persist = new ActionConfirmationPersist();
|
|
|
|
persist.setType(ActionConfirmationType.MergeAccount);
|
|
|
|
persist.setStatus(ActionConfirmationStatus.Requested);
|
|
|
|
persist.setToken(UUID.randomUUID().toString());
|
|
|
|
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 {
|
2023-12-15 10:51:08 +01:00
|
|
|
ActionConfirmationPersist persist = new ActionConfirmationPersist();
|
2024-01-15 12:57:33 +01:00
|
|
|
persist.setType(ActionConfirmationType.RemoveCredential);
|
2023-12-15 10:51:08 +01:00
|
|
|
persist.setStatus(ActionConfirmationStatus.Requested);
|
|
|
|
persist.setToken(UUID.randomUUID().toString());
|
2024-01-15 12:57:33 +01:00
|
|
|
persist.setRemoveCredentialRequest(new RemoveCredentialRequestPersist());
|
|
|
|
persist.getRemoveCredentialRequest().setCredentialId(credentialId);
|
2024-01-04 15:25:07 +01:00
|
|
|
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
|
2023-12-21 17:45:49 +01:00
|
|
|
validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
|
2023-12-15 10:51:08 +01:00
|
|
|
this.actionConfirmationService.persist(persist, null);
|
|
|
|
|
|
|
|
return persist.getToken();
|
|
|
|
}
|
2023-12-14 17:19:43 +01:00
|
|
|
|
|
|
|
private String secondsToTime(int seconds) {
|
|
|
|
int sec = seconds % 60;
|
|
|
|
int hour = seconds / 60;
|
|
|
|
int min = hour % 60;
|
|
|
|
hour = hour / 60;
|
|
|
|
return (hour + ":" + min + ":" + sec);
|
|
|
|
}
|
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
public void confirmMergeAccount(String token) throws IOException, InvalidApplicationException {
|
2023-12-14 17:19:43 +01:00
|
|
|
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.MergeAccount).isActive(IsActive.Active).first();
|
2024-01-04 15:25:07 +01:00
|
|
|
if (action == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2023-12-14 17:19:43 +01:00
|
|
|
|
|
|
|
this.checkActionState(action);
|
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
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");
|
2023-12-14 17:19:43 +01:00
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
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());
|
2023-12-14 17:19:43 +01:00
|
|
|
action.setStatus(ActionConfirmationStatus.Accepted);
|
2024-01-15 12:57:33 +01:00
|
|
|
this.entityManager.merge(action);
|
|
|
|
|
|
|
|
this.entityManager.flush();
|
2024-01-29 17:10:55 +01:00
|
|
|
|
|
|
|
this.userTouchedIntegrationEventHandler.handle(newUser.getId());
|
|
|
|
this.userRemovalIntegrationEventHandler.handle(userToBeMerge.getId());
|
2024-01-15 12:57:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2024-01-04 15:25:07 +01:00
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
oldUser.setIsActive(IsActive.Inactive);
|
|
|
|
|
|
|
|
this.entityManager.merge(oldUser);
|
2024-01-04 15:25:07 +01:00
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
this.entityManager.flush();
|
|
|
|
|
|
|
|
for (DmpEntity dmp : dmps){
|
|
|
|
this.elasticService.persistDmp(dmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (DescriptionEntity description : descriptions){
|
|
|
|
this.elasticService.persistDescription(description);
|
|
|
|
}
|
2023-12-14 17:19:43 +01:00
|
|
|
}
|
|
|
|
|
2024-01-04 15:25:07 +01:00
|
|
|
|
|
|
|
|
2023-12-14 17:19:43 +01:00
|
|
|
public void confirmRemoveCredential(String token) throws InvalidApplicationException {
|
|
|
|
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.RemoveCredential).isActive(IsActive.Active).first();
|
2024-01-04 15:25:07 +01:00
|
|
|
if (action == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2023-12-14 17:19:43 +01:00
|
|
|
|
|
|
|
this.checkActionState(action);
|
|
|
|
|
2024-01-15 17:03:12 +01:00
|
|
|
RemoveCredentialRequestEntity removeCredentialRequestEntity = this.xmlHandlingService.fromXmlSafe(RemoveCredentialRequestEntity.class, action.getData());
|
|
|
|
if (removeCredentialRequestEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialRequestEntity, RemoveCredentialRequestEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2024-01-15 12:57:33 +01:00
|
|
|
|
2024-01-15 17:03:12 +01:00
|
|
|
UserCredentialEntity userCredentialEntity = this.queryFactory.query(UserCredentialQuery.class).ids(removeCredentialRequestEntity.getCredentialId()).first();
|
|
|
|
if (userCredentialEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialRequestEntity.getCredentialId(), UserCredential.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
2024-01-16 11:56:48 +01:00
|
|
|
|
2024-01-15 12:57:33 +01:00
|
|
|
if (!this.userScope.getUserIdSafe().equals(userCredentialEntity.getId())) throw new MyForbiddenException("Only requested user can approve");
|
|
|
|
|
2024-01-16 11:56:48 +01:00
|
|
|
if (userCredentialEntity.getData() != null){
|
|
|
|
UserCredentialDataEntity userCredentialDataEntity = this.jsonHandlingService.fromJsonSafe(UserCredentialDataEntity.class, userCredentialEntity.getData());
|
|
|
|
if (userCredentialDataEntity != null && !this.conventionService.isNullOrEmpty(userCredentialDataEntity.getEmail())) {
|
|
|
|
List<UserContactInfoEntity> userContactInfos = this.queryFactory.query(UserContactInfoQuery.class).values(userCredentialDataEntity.getEmail()).userIds(userCredentialEntity.getUserId()).collect();
|
|
|
|
if (!this.conventionService.isListNullOrEmpty(userContactInfos))
|
|
|
|
this.deleterFactory.deleter(UserContactInfoDeleter.class).delete(userContactInfos);
|
|
|
|
}
|
|
|
|
}
|
2024-01-15 12:57:33 +01:00
|
|
|
this.deleterFactory.deleter(UserCredentialDeleter.class).delete(List.of(userCredentialEntity));
|
|
|
|
|
|
|
|
action.setUpdatedAt(Instant.now());
|
2023-12-14 17:19:43 +01:00
|
|
|
action.setStatus(ActionConfirmationStatus.Accepted);
|
|
|
|
this.entityManager.merge(action);
|
2024-01-15 12:57:33 +01:00
|
|
|
|
|
|
|
this.entityManager.flush();
|
2024-01-29 17:10:55 +01:00
|
|
|
|
|
|
|
this.userTouchedIntegrationEventHandler.handle(userCredentialEntity.getUserId());
|
2023-12-14 17:19:43 +01:00
|
|
|
}
|
|
|
|
|
2023-12-15 10:51:08 +01:00
|
|
|
private void checkActionState(ActionConfirmationEntity action) throws MyApplicationException {
|
2023-12-14 17:19:43 +01:00
|
|
|
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){
|
2023-12-15 10:51:08 +01:00
|
|
|
throw new MyApplicationException("Account is already confirmed!");
|
2023-12-14 17:19:43 +01:00
|
|
|
}
|
|
|
|
if (action.getExpiresAt().compareTo(Instant.now()) < 0){
|
2023-12-15 10:51:08 +01:00
|
|
|
throw new MyApplicationException("Token has expired!");
|
2023-12-14 17:19:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-20 16:09:24 +01:00
|
|
|
}
|