From e1212383ff4526f2d122b0e152599fcc2e7587c2 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Fri, 23 Oct 2020 18:40:17 +0300 Subject: [PATCH] Add expirimental logic for userMerge (+ some updates for DB) --- .../criteria/EmailConfirmationCriteria.java | 6 ++ .../LoginConfirmationEmailCriteria.java | 6 -- .../dao/entities/EmailConfirmationDao.java | 13 +++ .../entities/EmailConfirmationDaoImpl.java | 56 ++++++++++ .../entities/LoginConfirmationEmailDao.java | 13 --- .../LoginConfirmationEmailDaoImpl.java | 56 ---------- .../eu/eudat/data/entities/Credential.java | 11 ++ ...ationEmail.java => EmailConfirmation.java} | 18 +++- .../controllers/EmailMergeConfirmation.java | 63 +++++++++++ .../main/java/eu/eudat/controllers/Users.java | 10 ++ .../managers/EmailConfirmationManager.java | 4 +- .../MergeEmailConfirmationManager.java | 100 ++++++++++++++++++ .../eu/eudat/logic/managers/UserManager.java | 15 +++ .../operations/DatabaseRepository.java | 2 +- .../operations/DatabaseRepositoryImpl.java | 6 +- .../AbstractAuthenticationService.java | 1 + .../utilities/ConfirmationEmailService.java | 10 +- .../ConfirmationEmailServiceImpl.java | 37 ++++++- .../models/data/userinfo/UserCredential.java | 19 ++++ .../data/userinfo/UserMergeRequestModel.java | 21 ++++ .../00.00.006_add_email_to_credential.sql | 1 + ...EmailConfirmation - Αντιγραφή.sql | 1 + ...8_add_column_data_to_EmailConfirmation.sql | 1 + 23 files changed, 375 insertions(+), 95 deletions(-) create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/EmailConfirmationCriteria.java delete mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/LoginConfirmationEmailCriteria.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDao.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDaoImpl.java delete mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDao.java delete mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDaoImpl.java rename dmp-backend/data/src/main/java/eu/eudat/data/entities/{LoginConfirmationEmail.java => EmailConfirmation.java} (79%) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserCredential.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserMergeRequestModel.java create mode 100644 dmp-db-scema/updates/00.00.006_add_email_to_credential.sql create mode 100644 dmp-db-scema/updates/00.00.007_rename_LogicConfirmationEmail_to_EmailConfirmation - Αντιγραφή.sql create mode 100644 dmp-db-scema/updates/00.00.008_add_column_data_to_EmailConfirmation.sql diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/EmailConfirmationCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/EmailConfirmationCriteria.java new file mode 100644 index 000000000..1436752b9 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/EmailConfirmationCriteria.java @@ -0,0 +1,6 @@ +package eu.eudat.data.dao.criteria; + +import eu.eudat.data.entities.EmailConfirmation; + +public class EmailConfirmationCriteria extends Criteria{ +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/LoginConfirmationEmailCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/LoginConfirmationEmailCriteria.java deleted file mode 100644 index 4ec5be026..000000000 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/LoginConfirmationEmailCriteria.java +++ /dev/null @@ -1,6 +0,0 @@ -package eu.eudat.data.dao.criteria; - -import eu.eudat.data.entities.LoginConfirmationEmail; - -public class LoginConfirmationEmailCriteria extends Criteria{ -} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDao.java new file mode 100644 index 000000000..b379d964d --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDao.java @@ -0,0 +1,13 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccessLayer; +import eu.eudat.data.dao.criteria.EmailConfirmationCriteria; +import eu.eudat.data.entities.EmailConfirmation; +import eu.eudat.queryable.QueryableList; + +import java.util.UUID; + +public interface EmailConfirmationDao extends DatabaseAccessLayer { + + QueryableList getWithCriteria(EmailConfirmationCriteria criteria); +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDaoImpl.java new file mode 100644 index 000000000..d53fc9774 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EmailConfirmationDaoImpl.java @@ -0,0 +1,56 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccess; +import eu.eudat.data.dao.criteria.EmailConfirmationCriteria; +import eu.eudat.data.dao.databaselayer.service.DatabaseService; +import eu.eudat.data.entities.EmailConfirmation; +import eu.eudat.queryable.QueryableList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@Service("LoginConfirmationEmailDao") +public class EmailConfirmationDaoImpl extends DatabaseAccess implements EmailConfirmationDao { + + @Autowired + public EmailConfirmationDaoImpl(DatabaseService databaseService) { + super(databaseService); + } + + @Override + public QueryableList getWithCriteria(EmailConfirmationCriteria criteria) { + return null; + } + + @Override + public EmailConfirmation createOrUpdate(EmailConfirmation item) { + return this.getDatabaseService().createOrUpdate(item, EmailConfirmation.class); + } + + @Override + public CompletableFuture createOrUpdateAsync(EmailConfirmation item) { + return null; + } + + @Override + public EmailConfirmation find(UUID id) { + return this.getDatabaseService().getQueryable(EmailConfirmation.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle(); + } + + @Override + public EmailConfirmation find(UUID id, String hint) { + throw new UnsupportedOperationException(); + } + + @Override + public void delete(EmailConfirmation item) { + throw new UnsupportedOperationException(); + } + + @Override + public QueryableList asQueryable() { + return this.getDatabaseService().getQueryable(EmailConfirmation.class); + } +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDao.java deleted file mode 100644 index 71edce65e..000000000 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDao.java +++ /dev/null @@ -1,13 +0,0 @@ -package eu.eudat.data.dao.entities; - -import eu.eudat.data.dao.DatabaseAccessLayer; -import eu.eudat.data.dao.criteria.LoginConfirmationEmailCriteria; -import eu.eudat.data.entities.LoginConfirmationEmail; -import eu.eudat.queryable.QueryableList; - -import java.util.UUID; - -public interface LoginConfirmationEmailDao extends DatabaseAccessLayer { - - QueryableList getWithCriteria(LoginConfirmationEmailCriteria criteria); -} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDaoImpl.java deleted file mode 100644 index 691c6b663..000000000 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/LoginConfirmationEmailDaoImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -package eu.eudat.data.dao.entities; - -import eu.eudat.data.dao.DatabaseAccess; -import eu.eudat.data.dao.criteria.LoginConfirmationEmailCriteria; -import eu.eudat.data.dao.databaselayer.service.DatabaseService; -import eu.eudat.data.entities.LoginConfirmationEmail; -import eu.eudat.queryable.QueryableList; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -@Service("LoginConfirmationEmailDao") -public class LoginConfirmationEmailDaoImpl extends DatabaseAccess implements LoginConfirmationEmailDao { - - @Autowired - public LoginConfirmationEmailDaoImpl(DatabaseService databaseService) { - super(databaseService); - } - - @Override - public QueryableList getWithCriteria(LoginConfirmationEmailCriteria criteria) { - return null; - } - - @Override - public LoginConfirmationEmail createOrUpdate(LoginConfirmationEmail item) { - return this.getDatabaseService().createOrUpdate(item, LoginConfirmationEmail.class); - } - - @Override - public CompletableFuture createOrUpdateAsync(LoginConfirmationEmail item) { - return null; - } - - @Override - public LoginConfirmationEmail find(UUID id) { - return this.getDatabaseService().getQueryable(LoginConfirmationEmail.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle(); - } - - @Override - public LoginConfirmationEmail find(UUID id, String hint) { - throw new UnsupportedOperationException(); - } - - @Override - public void delete(LoginConfirmationEmail item) { - throw new UnsupportedOperationException(); - } - - @Override - public QueryableList asQueryable() { - return this.getDatabaseService().getQueryable(LoginConfirmationEmail.class); - } -} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Credential.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Credential.java index 7181abfb9..88e3dc36d 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Credential.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Credential.java @@ -34,6 +34,8 @@ public class Credential implements DataEntity { private Integer provider; @Column(name = "\"Public\"", nullable = false) private String publicValue; + @Column(name = "\"Email\"", nullable = false) + private String email; @Column(name = "\"Secret\"", nullable = false) private String secret; @@ -88,6 +90,14 @@ public class Credential implements DataEntity { this.publicValue = publicValue; } + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + public String getSecret() { return secret; } @@ -139,6 +149,7 @@ public class Credential implements DataEntity { public void update(Credential entity) { this.status = entity.status; this.publicValue = entity.getPublicValue(); + this.email = entity.getEmail(); this.secret = entity.getSecret(); this.lastUpdateTime = new Date(); } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/LoginConfirmationEmail.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EmailConfirmation.java similarity index 79% rename from dmp-backend/data/src/main/java/eu/eudat/data/entities/LoginConfirmationEmail.java rename to dmp-backend/data/src/main/java/eu/eudat/data/entities/EmailConfirmation.java index 2bc9f53c8..8d4363e9e 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/LoginConfirmationEmail.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EmailConfirmation.java @@ -10,8 +10,8 @@ import java.util.List; import java.util.UUID; @Entity -@Table(name = "\"LoginConfirmationEmail\"") -public class LoginConfirmationEmail implements DataEntity { +@Table(name = "\"EmailConfirmation\"") +public class EmailConfirmation implements DataEntity { @Id @GeneratedValue @@ -30,6 +30,9 @@ public class LoginConfirmationEmail implements DataEntity tuple, List fields, String base) { + public EmailConfirmation buildFromTuple(List tuple, List fields, String base) { return null; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java new file mode 100644 index 000000000..aca3817af --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailMergeConfirmation.java @@ -0,0 +1,63 @@ +package eu.eudat.controllers; + +import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; +import eu.eudat.exceptions.emailconfirmation.TokenExpiredException; +import eu.eudat.logic.managers.EmailConfirmationManager; +import eu.eudat.logic.managers.MergeEmailConfirmationManager; +import eu.eudat.logic.security.CustomAuthenticationProvider; +import eu.eudat.logic.services.operations.authentication.AuthenticationService; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.security.Principal; +import eu.eudat.models.data.userinfo.UserMergeRequestModel; +import eu.eudat.types.ApiMessageCode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.transaction.Transactional; + +@RestController +@CrossOrigin +@RequestMapping(value = "api/emailMergeConfirmation") +public class EmailMergeConfirmation { + + private MergeEmailConfirmationManager emailConfirmationManager; + + @Autowired + public EmailMergeConfirmation(MergeEmailConfirmationManager emailConfirmationManager) { + this.emailConfirmationManager = emailConfirmationManager; + } + + @Transactional + @RequestMapping(method = RequestMethod.GET, value = {"/{emailToken}"}) + public @ResponseBody + ResponseEntity emailConfirmation(@PathVariable(value = "emailToken") String token) { + try { + this.emailConfirmationManager.confirmEmail(token); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); + } catch + (HasConfirmedEmailException | TokenExpiredException ex) { + if (ex instanceof TokenExpiredException) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); + } else { + return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); + } + } + } + + @Transactional + @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity sendConfirmatioEmail(@RequestBody UserMergeRequestModel requestModel, Principal principal) { + try { + this.emailConfirmationManager.sendConfirmationEmail(requestModel.getEmail(), principal, requestModel.getUserId()); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); + } catch (Exception ex) { + if (ex instanceof HasConfirmedEmailException) { + return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); + } + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); + } + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Users.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Users.java index a33cf582f..d4d108b42 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Users.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Users.java @@ -11,6 +11,7 @@ import eu.eudat.models.data.doi.DOIRequest; import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; +import eu.eudat.models.data.userinfo.UserCredential; import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.models.data.userinfo.UserProfile; import eu.eudat.types.ApiMessageCode; @@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -62,6 +64,14 @@ public class Users extends BaseController { UserProfile user = userManager.getSingle(userId); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(user).status(ApiMessageCode.NO_MESSAGE)); } + + @RequestMapping(method = RequestMethod.GET, value = {"/{id}/emails"}, produces = "application/json") + public @ResponseBody + ResponseEntity>> getEmails(@PathVariable String id, Principal principal) throws Exception { + UUID userId = id.equals("me") ? principal.getId() : UUID.fromString(id); + List user = userManager.getCredentials(userId); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(user).status(ApiMessageCode.NO_MESSAGE)); + } @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/settings"}, produces = "application/json") diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java index bf26fa3e4..f6ad1d6fc 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java @@ -1,7 +1,7 @@ package eu.eudat.logic.managers; import eu.eudat.data.entities.Credential; -import eu.eudat.data.entities.LoginConfirmationEmail; +import eu.eudat.data.entities.EmailConfirmation; import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserToken; import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException; @@ -30,7 +30,7 @@ public class EmailConfirmationManager { } public void confirmEmail(String token) throws TokenExpiredException, HasConfirmedEmailException { - LoginConfirmationEmail loginConfirmationEmail = apiContext.getOperationsContext() + EmailConfirmation loginConfirmationEmail = apiContext.getOperationsContext() .getDatabaseRepository().getLoginConfirmationEmailDao().asQueryable() .where((builder, root) -> builder.equal(root.get("token"), UUID.fromString(token))).getSingle(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java new file mode 100644 index 000000000..7b41ee712 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/MergeEmailConfirmationManager.java @@ -0,0 +1,100 @@ +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); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java index a0d346020..d1ba1f31d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java @@ -3,6 +3,7 @@ package eu.eudat.logic.managers; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; import eu.eudat.data.dao.entities.UserInfoDao; +import eu.eudat.data.entities.Credential; import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserRole; @@ -26,6 +27,7 @@ import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.login.Credentials; import eu.eudat.models.data.principal.PrincipalModel; import eu.eudat.models.data.security.Principal; +import eu.eudat.models.data.userinfo.UserCredential; import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.models.data.userinfo.UserProfile; import eu.eudat.queryable.QueryableList; @@ -88,6 +90,19 @@ public class UserManager { List modelUsers = pagedUsers.select(item -> new UserListingModel().fromDataModel(item)); return apiContext.getOperationsContext().getBuilderFactory().getBuilder(DataTableDataBuilder.class).totalCount(users.count()).data(modelUsers).build(); } + + public List getCredentials(UUID userId) { + List results = new ArrayList<>(); + eu.eudat.data.entities.UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userId); + List credentials = apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao().asQueryable().where((builder, root) -> builder.equal(root.get("userInfo").get("id"), userId)).toList(); + credentials.forEach(credential -> { + UserCredential userCredential = new UserCredential(); + userCredential.setEmail(credential.getEmail()); + userCredential.setProvider(credential.getProvider()); + results.add(userCredential); + }); + return results; + } public UserProfile getSingle(UUID userId) throws Exception { eu.eudat.data.entities.UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userId); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index 63790784e..d77af5779 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -46,7 +46,7 @@ public interface DatabaseRepository { DatasetServiceDao getDatasetServiceDao(); - LoginConfirmationEmailDao getLoginConfirmationEmailDao(); + EmailConfirmationDao getLoginConfirmationEmailDao(); ProjectDao getProjectDao(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index 5e456a26b..cad146eaf 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -32,7 +32,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { private DMPProfileDao dmpProfileDao; private DatasetExternalDatasetDao datasetExternalDatasetDao; private DatasetServiceDao datasetServiceDao; - private LoginConfirmationEmailDao loginConfirmationEmailDao; + private EmailConfirmationDao loginConfirmationEmailDao; private ProjectDao projectDao; private FunderDao funderDao; private LockDao lockDao; @@ -247,12 +247,12 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { } @Override - public LoginConfirmationEmailDao getLoginConfirmationEmailDao() { + public EmailConfirmationDao getLoginConfirmationEmailDao() { return loginConfirmationEmailDao; } @Autowired - public void setLoginConfirmationEmailDao(LoginConfirmationEmailDao loginConfirmationEmailDao) { + public void setLoginConfirmationEmailDao(EmailConfirmationDao loginConfirmationEmailDao) { this.loginConfirmationEmailDao = loginConfirmationEmailDao; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java index 50d5e12dd..a43ec4ac7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java @@ -145,6 +145,7 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().createOrUpdate(userInfo); credential.setPublicValue(userInfo.getName()); + credential.setEmail(userInfo.getEmail()); credential.setUserInfo(userInfo); apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao().createOrUpdate(credential); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java index 831e48b9d..57d02345b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailService.java @@ -1,13 +1,15 @@ package eu.eudat.logic.services.utilities; -import eu.eudat.data.dao.entities.LoginConfirmationEmailDao; -import eu.eudat.data.entities.LoginConfirmationEmail; +import eu.eudat.data.dao.entities.EmailConfirmationDao; +import eu.eudat.data.entities.EmailConfirmation; import java.util.UUID; import java.util.concurrent.CompletableFuture; public interface ConfirmationEmailService { - public void createConfirmationEmail(LoginConfirmationEmailDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId); + public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId); + + public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId, UUID anotheruserId); - public CompletableFuture sentConfirmationEmail(LoginConfirmationEmail confirmationEmail, MailService mailService); + public CompletableFuture sentConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService); } \ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java index dec804949..6ff0be763 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java @@ -1,13 +1,16 @@ package eu.eudat.logic.services.utilities; -import eu.eudat.data.dao.entities.LoginConfirmationEmailDao; -import eu.eudat.data.entities.LoginConfirmationEmail; +import eu.eudat.data.dao.entities.EmailConfirmationDao; +import eu.eudat.data.entities.EmailConfirmation; import eu.eudat.models.data.mail.SimpleMail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import java.util.Date; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -24,8 +27,8 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { } @Override - public void createConfirmationEmail(LoginConfirmationEmailDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId) { - LoginConfirmationEmail confirmationEmail = new LoginConfirmationEmail(); + public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId) { + EmailConfirmation confirmationEmail = new EmailConfirmation(); confirmationEmail.setEmail(email); confirmationEmail.setExpiresAt(Date .from(new Date() @@ -41,7 +44,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { } @Override - public CompletableFuture sentConfirmationEmail(LoginConfirmationEmail confirmationEmail, MailService mailService) { + public CompletableFuture sentConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService) { return CompletableFuture.runAsync(() -> { SimpleMail mail = new SimpleMail(); mail.setSubject(environment.getProperty("conf_email.subject")); @@ -71,4 +74,28 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { hour = hour / 60; return (hour + ":" + min + ":" + sec); } + + @Override + public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, + String email, UUID userId, UUID anotheruserId) { + EmailConfirmation confirmationEmail = new EmailConfirmation(); + confirmationEmail.setEmail(email); + confirmationEmail.setExpiresAt(Date + .from(new Date() + .toInstant() + .plusSeconds(Long.parseLong(this.environment.getProperty("conf_email.expiration_time_seconds"))) + ) + ); + confirmationEmail.setUserId(userId); + try { + confirmationEmail.setData(new ObjectMapper().writeValueAsString(anotheruserId)); + } catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); + } + confirmationEmail.setIsConfirmed(false); + confirmationEmail.setToken(UUID.randomUUID()); + confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail); + sentConfirmationEmail(confirmationEmail, mailService); + + } } \ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserCredential.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserCredential.java new file mode 100644 index 000000000..e2ce326f8 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserCredential.java @@ -0,0 +1,19 @@ +package eu.eudat.models.data.userinfo; + +public class UserCredential { + private String email; + private Integer provider; + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public Integer getProvider() { + return provider; + } + public void setProvider(Integer provider) { + this.provider = provider; + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserMergeRequestModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserMergeRequestModel.java new file mode 100644 index 000000000..dab3bab4e --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/userinfo/UserMergeRequestModel.java @@ -0,0 +1,21 @@ +package eu.eudat.models.data.userinfo; + +import java.util.UUID; + +public class UserMergeRequestModel { + private UUID userId; + private String 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; + } + +} diff --git a/dmp-db-scema/updates/00.00.006_add_email_to_credential.sql b/dmp-db-scema/updates/00.00.006_add_email_to_credential.sql new file mode 100644 index 000000000..f60e3ceb1 --- /dev/null +++ b/dmp-db-scema/updates/00.00.006_add_email_to_credential.sql @@ -0,0 +1 @@ +ALTER TABLE public."Credential" ADD COLUMN email character varying; diff --git a/dmp-db-scema/updates/00.00.007_rename_LogicConfirmationEmail_to_EmailConfirmation - Αντιγραφή.sql b/dmp-db-scema/updates/00.00.007_rename_LogicConfirmationEmail_to_EmailConfirmation - Αντιγραφή.sql new file mode 100644 index 000000000..a43076fc9 --- /dev/null +++ b/dmp-db-scema/updates/00.00.007_rename_LogicConfirmationEmail_to_EmailConfirmation - Αντιγραφή.sql @@ -0,0 +1 @@ +ALTER TABLE public."LoginConfirmationEmail" RENAME TO "EmailConfirmation"; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.008_add_column_data_to_EmailConfirmation.sql b/dmp-db-scema/updates/00.00.008_add_column_data_to_EmailConfirmation.sql new file mode 100644 index 000000000..38b964a5a --- /dev/null +++ b/dmp-db-scema/updates/00.00.008_add_column_data_to_EmailConfirmation.sql @@ -0,0 +1 @@ +ALTER TABLE public."EmailConfirmation" ADD COLUMN data text; \ No newline at end of file