diff --git a/sep490-idp/src/main/java/green_buildings/idp/aop/UserRepositoryAdvice.java b/sep490-idp/src/main/java/green_buildings/idp/aop/UserRepositoryAdvice.java new file mode 100644 index 00000000..051e6a6a --- /dev/null +++ b/sep490-idp/src/main/java/green_buildings/idp/aop/UserRepositoryAdvice.java @@ -0,0 +1,51 @@ +package green_buildings.idp.aop; + +import commons.springfw.impl.utils.SecurityUtils; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import lombok.RequiredArgsConstructor; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.hibernate.Filter; +import org.hibernate.Session; +import org.springframework.stereotype.Component; +import green_buildings.idp.entity.UserEntity; + +import java.util.Objects; +import java.util.UUID; + +@Aspect +@Component +@RequiredArgsConstructor +public class UserRepositoryAdvice { + + @PersistenceContext + private final EntityManager em; + + @Pointcut("execution(* green_buildings.idp.repository.UserRepositoryAdapter.*(..))") + public void userRepositoryMethods() { + // Pointcut for methods in UserRepository have to filter users base on their enterprise + } + + @Around(value = "userRepositoryMethods()") + public Object applyEnterpriseFilter(ProceedingJoinPoint joinPoint) throws Throwable { + Session session = em.unwrap(Session.class); + boolean hasSession = Objects.nonNull(session); + if (hasSession) { + Filter filter = session.enableFilter(UserEntity.BELONG_ENTERPRISE_FILTER); + UUID enterpriseId = SecurityUtils.getCurrentUserEnterpriseId().orElseThrow(); + filter.setParameter(UserEntity.BELONG_ENTERPRISE_PARAM, enterpriseId); + } + + try { + return joinPoint.proceed(); + } finally { + if (hasSession) { + session.disableFilter(UserEntity.BELONG_ENTERPRISE_FILTER); + } + } + } + +} diff --git a/sep490-idp/src/main/java/green_buildings/idp/entity/UserEntity.java b/sep490-idp/src/main/java/green_buildings/idp/entity/UserEntity.java index 0dbead48..041df7f1 100644 --- a/sep490-idp/src/main/java/green_buildings/idp/entity/UserEntity.java +++ b/sep490-idp/src/main/java/green_buildings/idp/entity/UserEntity.java @@ -18,9 +18,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.Filter; +import org.hibernate.annotations.FilterDef; +import org.hibernate.annotations.ParamDef; import java.util.LinkedHashSet; import java.util.Set; +import java.util.UUID; @NamedEntityGraph( name = UserEntity.WITH_ENTERPRISE_PERMISSIONS_ENTITY_GRAPH, @@ -29,6 +33,9 @@ @NamedAttributeNode("buildingPermissions") } ) +@FilterDef(name = UserEntity.BELONG_ENTERPRISE_FILTER, parameters = @ParamDef(name = UserEntity.BELONG_ENTERPRISE_PARAM, type = UUID.class)) +@Filter(name = UserEntity.BELONG_ENTERPRISE_FILTER, + condition = "id IN (SELECT ue.user_id FROM enterprise_users ue WHERE ue.enterprise_id = :" + UserEntity.BELONG_ENTERPRISE_PARAM) @Entity @Table(name = "users") @AllArgsConstructor @@ -38,6 +45,8 @@ public class UserEntity extends AbstractAuditableEntity { public static final String WITH_ENTERPRISE_PERMISSIONS_ENTITY_GRAPH = "user-permissions-entity-graph"; + public static final String BELONG_ENTERPRISE_FILTER = "belongEnterpriseFilter"; + public static final String BELONG_ENTERPRISE_PARAM = "enterpriseId"; @NotNull @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, optional = false) diff --git a/sep490-idp/src/main/java/green_buildings/idp/repository/UserRepositoryAdapter.java b/sep490-idp/src/main/java/green_buildings/idp/repository/UserRepositoryAdapter.java new file mode 100644 index 00000000..1c9001b2 --- /dev/null +++ b/sep490-idp/src/main/java/green_buildings/idp/repository/UserRepositoryAdapter.java @@ -0,0 +1,20 @@ +package green_buildings.idp.repository; + +import green_buildings.idp.entity.UserEntity; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Set; +import java.util.UUID; + +@Component +@RequiredArgsConstructor +public class UserRepositoryAdapter { + private final UserRepository userRepo; + + public List findByIDs(Set ids) { + return userRepo.findByIDs(ids); + } + +} diff --git a/sep490-idp/src/main/java/green_buildings/idp/service/impl/UserServiceImpl.java b/sep490-idp/src/main/java/green_buildings/idp/service/impl/UserServiceImpl.java index 1fbf1f75..ceead0c0 100644 --- a/sep490-idp/src/main/java/green_buildings/idp/service/impl/UserServiceImpl.java +++ b/sep490-idp/src/main/java/green_buildings/idp/service/impl/UserServiceImpl.java @@ -18,6 +18,7 @@ import green_buildings.idp.entity.UserEntity; import green_buildings.idp.producers.IdPEventProducer; import green_buildings.idp.repository.UserRepository; +import green_buildings.idp.repository.UserRepositoryAdapter; import green_buildings.idp.service.UserService; import green_buildings.idp.utils.IEmailUtil; import green_buildings.idp.utils.IMessageUtil; @@ -54,6 +55,7 @@ public class UserServiceImpl extends SagaManager implements UserService { private final UserRepository userRepo; + private final UserRepositoryAdapter userRepositoryAdapter; private final UserValidator userValidator; private final PasswordEncoder passwordEncoder; @Qualifier("signupValidator") @@ -174,7 +176,7 @@ public void deleteUsers(Set userIds) { if (CollectionUtils.isEmpty(userIds)) { throw new BusinessException("userIds", "user.delete.no.ids", Collections.emptyList()); } - var users = userRepo.findByIDs(userIds); + var users = userRepositoryAdapter.findByIDs(userIds); if (users.size() != userIds.size()) { userIds.removeAll(users.stream().map(UserEntity::getId).collect(Collectors.toSet())); throw new BusinessException("userIds", "user.delete.not.found",