package eu.eudat.logic.managers; import eu.eudat.data.entities.Credential; import eu.eudat.data.entities.EmailConfirmation; import eu.eudat.data.entities.UserDMP; import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserToken; import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.models.data.security.Principal; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.jpa.predicates.OrderByPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.UUID; @Component public class MergeEmailConfirmationManager { private static Logger logger = LoggerFactory.getLogger(MergeEmailConfirmationManager.class); private ApiContext apiContext; private DatabaseRepository databaseRepository; @Autowired public MergeEmailConfirmationManager(ApiContext apiContext) { this.apiContext = apiContext; this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); } public void confirmEmail(String token) throws TokenExpiredException, HasConfirmedEmailException { EmailConfirmation loginConfirmationEmail = apiContext.getOperationsContext() .getDatabaseRepository().getLoginConfirmationEmailDao().asQueryable() .where((builder, root) -> builder.equal(root.get("token"), UUID.fromString(token))).getSingle(); if (loginConfirmationEmail.getExpiresAt().compareTo(new Date()) < 0) throw new TokenExpiredException("Token has expired."); UserInfo userToBeMerged = databaseRepository.getUserInfoDao().asQueryable() .where((builder, root) -> builder.equal(root.get("id"), loginConfirmationEmail.getUserId())).getSingle(); try { UUID otherUserId = new ObjectMapper().readValue(loginConfirmationEmail.getData(), UUID.class); UserInfo user = databaseRepository.getUserInfoDao().asQueryable() .where((builder, root) -> builder.equal(root.get("id"), loginConfirmationEmail.getUserId())).getSingle(); // Checks if mail is used by another user. If it is, merges the new the old. mergeNewUserToOld(user, userToBeMerged); expireUserToken(user); loginConfirmationEmail.setIsConfirmed(true); databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail); } catch (Exception e) { logger.error(e.getMessage(), e); } } public void sendConfirmationEmail(String email, Principal principal, UUID userId) throws HasConfirmedEmailException { UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); apiContext.getUtilitiesService().getConfirmationEmailService().createConfirmationEmail( databaseRepository.getLoginConfirmationEmailDao(), apiContext.getUtilitiesService().getMailService(), email, userId, principal.getId() ); } private void mergeNewUserToOld(UserInfo newUser, UserInfo oldUser) { Credential credential = databaseRepository.getCredentialDao().asQueryable().where((builder, root) -> builder.equal(root.get("userInfo"), oldUser)).getSingle(); credential.setUserInfo(newUser); databaseRepository.getCredentialDao().createOrUpdate(credential); List userDmps = databaseRepository.getUserDmpDao().asQueryable().where((builder, root) -> builder.equal(root.get("user"), oldUser)).toList(); userDmps.forEach(userDmp -> { userDmp.setUser(newUser); databaseRepository.getUserDmpDao().createOrUpdate(userDmp); }); } private void expireUserToken(UserInfo user) { UserToken userToken = databaseRepository.getUserTokenDao().asQueryable() .where((builder, root) -> builder.equal(root.get("user"), user)) .orderBy((builder, root) -> builder.desc(root.get("issuedAt"))) .take(1) .getSingle(); userToken.setExpiresAt(new Date()); databaseRepository.getUserTokenDao().createOrUpdate(userToken); } }