From c30f499f301ee9b1ba82963f740b309596d03587 Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Wed, 24 Jan 2024 10:29:44 +0200 Subject: [PATCH] change notification interceptor --- .../web/interceptors/UserInterceptor.java | 214 +----------------- .../UserInterceptorCacheService.java | 20 +- 2 files changed, 10 insertions(+), 224 deletions(-) diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java index 83e461b18..565b141b7 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptor.java @@ -4,21 +4,11 @@ package gr.cite.notification.web.interceptors; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; import gr.cite.notification.common.JsonHandlingService; -import gr.cite.notification.common.enums.ContactInfoType; -import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.lock.LockByKeyManager; import gr.cite.notification.common.scope.user.UserScope; -import gr.cite.notification.common.types.user.AdditionalInfoEntity; -import gr.cite.notification.data.UserContactInfoEntity; import gr.cite.notification.data.UserCredentialEntity; -import gr.cite.notification.data.UserEntity; -import gr.cite.notification.data.UserRoleEntity; -import gr.cite.notification.model.UserContactInfo; import gr.cite.notification.model.UserCredential; -import gr.cite.notification.model.UserRole; -import gr.cite.notification.query.UserContactInfoQuery; import gr.cite.notification.query.UserCredentialQuery; -import gr.cite.notification.query.UserRoleQuery; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyForbiddenException; import gr.cite.tools.fieldset.BaseFieldSet; @@ -28,21 +18,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.ui.ModelMap; import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequestInterceptor; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; + import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; @Component public class UserInterceptor implements WebRequestInterceptor { @@ -79,214 +62,35 @@ public class UserInterceptor implements WebRequestInterceptor { } @Override - public void preHandle(WebRequest request) throws InterruptedException { + public void preHandle(WebRequest request) { UUID userId = null; if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) { String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal()); if (subjectId == null || subjectId.isBlank()) throw new MyForbiddenException("Empty subjects not allowed"); UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId)); - if (cacheValue != null && emailExistsToUser(cacheValue.getEmails()) && userRolesSynced(cacheValue.getRoles())) { + if (cacheValue != null) { userId = cacheValue.getUserId(); } else { - boolean usedResource = false; - try { - usedResource = this.lockByKeyManager.tryLock(subjectId, 5000, TimeUnit.MILLISECONDS); - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); - - DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); - definition.setName(UUID.randomUUID().toString()); - definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); - definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); - TransactionStatus status = null; - try { - status = transactionManager.getTransaction(definition); - userId = this.findExistingUserFromDb(subjectId); - boolean isNewUser = userId == null; - if (isNewUser) { - UserEntity user = this.addNewUser(subjectId, email); - userId = user.getId(); - } - - if (!isNewUser) this.syncUserWithClaims(userId); - - this.entityManager.flush(); - transactionManager.commit(status); - } catch (Exception ex) { - if (status != null) transactionManager.rollback(status); - throw ex; - } - - cacheValue = new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId); - cacheValue.setEmails(new ArrayList<>()); - if (email != null && !email.isBlank()) cacheValue.getEmails().add(email); - cacheValue.setRoles(claimExtractor.roles(currentPrincipalResolver.currentPrincipal())); - - this.userInterceptorCacheService.put(cacheValue); - } finally { - if (usedResource) this.lockByKeyManager.unlock(subjectId); - } + userId = this.findExistingUserFromDbForce(subjectId); + cacheValue = new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId); + + this.userInterceptorCacheService.put(cacheValue); } } this.userScope.setUserId(userId); } - private void syncUserWithClaims(UUID userId){ - List existingUserEmails = this.collectUserEmails(userId); - List existingUserRoles = this.collectUserRoles(userId); - if (!this.emailExistsToUser(existingUserEmails)){ - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); - long contactUsedByOthersCount = this.queryFactory.query(UserContactInfoQuery.class).excludedUserIds(userId).type(ContactInfoType.Email).values(email).count(); - if (contactUsedByOthersCount > 0) { - logger.warn("user contact exists to other user" + email); - } else { - Long emailContactsCount = this.queryFactory.query(UserContactInfoQuery.class).userIds(userId).type(ContactInfoType.Email).count(); - UserContactInfoEntity contactInfo = this.buildEmailContact(userId, email); - contactInfo.setOrdinal(emailContactsCount.intValue()); - this.entityManager.persist(contactInfo); - } - } - - if (!this.userRolesSynced(existingUserRoles)){ - this.syncRoles(userId); - } - } - - private UUID findExistingUserFromDb(String subjectId){ + private UUID findExistingUserFromDbForce(String subjectId){ UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).externalIds(subjectId).firstAs(new BaseFieldSet().ensure(UserCredential._user)); if (userCredential != null) { return userCredential.getUserId(); } else { - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); - if (email != null && !email.isBlank()) { - UserContactInfoEntity userContactInfo = this.queryFactory.query(UserContactInfoQuery.class).type(ContactInfoType.Email).values(email).firstAs(new BaseFieldSet().ensure(UserContactInfo._user)); - if (userContactInfo != null) { - UserCredentialEntity credential = this.buildCredential(userContactInfo.getUserId(), subjectId); - this.entityManager.persist(credential); - - return credential.getUserId(); - } - } else { - throw new MyForbiddenException("Email is required"); - } - } - return null; - } - - private void syncRoles(UUID userId){ - List claimsRoles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal()); - if (claimsRoles == null) claimsRoles = new ArrayList<>(); - claimsRoles = claimsRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().collect(Collectors.toList()); - - List existingUserRoles = this.queryFactory.query(UserRoleQuery.class).userIds(userId).collect(); - List foundRoles = new ArrayList<>(); - for (String claimRole : claimsRoles) { - UserRoleEntity roleEntity = existingUserRoles.stream().filter(x-> x.getRole().equals(claimRole)).findFirst().orElse(null); - if (roleEntity == null) { - roleEntity = this.buildRole(userId, claimRole); - this.entityManager.persist(roleEntity); - } - foundRoles.add(roleEntity.getId()); - } - for (UserRoleEntity existing: existingUserRoles) { - if (!foundRoles.contains(existing.getId())){ - this.entityManager.remove(existing); - } + throw new MyForbiddenException("User not created try again."); } } - private List collectUserRoles(UUID userId){ - List items = this.queryFactory.query(UserRoleQuery.class).userIds(userId).collectAs(new BaseFieldSet().ensure(UserRole._role)); - return items == null ? new ArrayList<>() : items.stream().map(UserRoleEntity::getRole).collect(Collectors.toList()); - } - - private List collectUserEmails(UUID userId){ - List items = this.queryFactory.query(UserContactInfoQuery.class).userIds(userId).type(ContactInfoType.Email).collectAs(new BaseFieldSet().ensure(UserContactInfo._value)); - return items == null ? new ArrayList<>() : items.stream().map(UserContactInfoEntity::getValue).collect(Collectors.toList()); - } - - private boolean emailExistsToUser(List existingUserEmails){ - String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal()); - return email == null || email.isBlank() || - (existingUserEmails != null && existingUserEmails.stream().anyMatch(email::equals)); - } - - private boolean userRolesSynced(List existingUserRoles){ - List claimsRoles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal()); - if (claimsRoles == null) claimsRoles = new ArrayList<>(); - if (existingUserRoles == null) existingUserRoles = new ArrayList<>(); - claimsRoles = claimsRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().collect(Collectors.toList()); - existingUserRoles = existingUserRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().collect(Collectors.toList()); - if (claimsRoles.size() != existingUserRoles.size()) return false; - - for (String claim : claimsRoles ) { - if (existingUserRoles.stream().noneMatch(claim::equalsIgnoreCase)) return false; - } - return true; - } - - private UserCredentialEntity buildCredential(UUID userId, String subjectId){ - UserCredentialEntity data = new UserCredentialEntity(); - data.setId(UUID.randomUUID()); - data.setUserId(userId); - data.setCreatedAt(Instant.now()); - data.setExternalId(subjectId); - return data; - } - - private UserRoleEntity buildRole(UUID userId, String role){ - UserRoleEntity data = new UserRoleEntity(); - data.setId(UUID.randomUUID()); - data.setUserId(userId); - data.setRole(role); - data.setCreatedAt(Instant.now()); - return data; - } - - private UserContactInfoEntity buildEmailContact(UUID userId, String email){ - UserContactInfoEntity data = new UserContactInfoEntity(); - data.setId(UUID.randomUUID()); - data.setUserId(userId); - data.setValue(email); - data.setType(ContactInfoType.Email); - data.setOrdinal(0); - data.setCreatedAt(Instant.now()); - return data; - } - - - - private UserEntity addNewUser(String subjectId, String email){ - List roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal()); - String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal()); - - UserEntity user = new UserEntity(); - user.setId(UUID.randomUUID()); - user.setName(name); - user.setCreatedAt(Instant.now()); - user.setUpdatedAt(Instant.now()); - user.setIsActive(IsActive.Active); - user.setAdditionalInfo(this.jsonHandlingService.toJsonSafe(new AdditionalInfoEntity())); - this.entityManager.persist(user); - - UserCredentialEntity credential = this.buildCredential(user.getId(), subjectId); - this.entityManager.persist(credential); - - if (email != null && !email.isBlank()) { - UserContactInfoEntity contactInfo = this.buildEmailContact(user.getId(), email); - this.entityManager.persist(contactInfo); - } - if (roles != null) { - for (String role: roles) { - UserRoleEntity roleEntity = this.buildRole(user.getId(), role); - this.entityManager.persist(roleEntity); - } - } - - return user; - } - @Override public void postHandle(@NonNull WebRequest request, ModelMap model) { this.userScope.setUserId(null); diff --git a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptorCacheService.java b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptorCacheService.java index b69813191..e293401f3 100644 --- a/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptorCacheService.java +++ b/dmp-backend/notification-service/notification-web/src/main/java/gr/cite/notification/web/interceptors/UserInterceptorCacheService.java @@ -33,9 +33,6 @@ public class UserInterceptorCacheService extends CacheService roles; - private List emails; - public UUID getUserId() { return userId; } @@ -44,26 +41,11 @@ public class UserInterceptorCacheService extends CacheService getRoles() { - return roles; - } - - public void setRoles(List roles) { - this.roles = roles; - } - - public List getEmails() { - return emails; - } - - public void setEmails(List emails) { - this.emails = emails; - } } @Autowired - public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) { + public UserInterceptorCacheService(UserInterceptorCacheOptions options) { super(options); }