From ba640e1b8208b7d7214aa2e268b532b79e14a7af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Boris=20Jadu=C5=A1?= <445343@mail.muni.cz>
Date: Tue, 19 Nov 2019 16:29:04 +0000
Subject: [PATCH] Resolve "Fix role access for accessing users with ids"

---
 .../userandgroup/api/facade/UserFacade.java    | 18 ++++++++++++++++++
 .../rest/controllers/RolesRestController.java  |  4 +---
 .../rest/controllers/UsersRestController.java  |  3 +--
 .../userandgroup/facade/UserFacadeImpl.java    | 17 +++++++++++++++++
 .../service/impl/UserServiceImpl.java          | 14 ++++++++++++++
 .../service/interfaces/UserService.java        | 18 ++++++++++++++++++
 6 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/kypo2-api-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/api/facade/UserFacade.java b/kypo2-api-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/api/facade/UserFacade.java
index 8ffeb25f..62f5c33c 100644
--- a/kypo2-api-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/api/facade/UserFacade.java
+++ b/kypo2-api-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/api/facade/UserFacade.java
@@ -129,6 +129,14 @@ public interface UserFacade {
      */
     PageResultResource<UserDTO> getUsersWithGivenIds(Set<Long> ids, Pageable pageable);
 
+
+    /**
+     * Gets users with given ids.
+     *
+     * @param ids ids of users.
+     * @return set of {@link UserDTO}s with given ids wrapped up in {@link PageResultResource}.
+     */
+    PageResultResource<UserDTO> getUsersWithGivenIds(Set<Long> ids, Pageable pageable, Predicate predicate);
     /**
      *  Returns a page of users specified by given role type and not with given ids.
      *
@@ -137,4 +145,14 @@ public interface UserFacade {
      * @return set of {@link UserDTO}s with given role type and not with given ids wrapped up in {@link PageResultResource}.
      */
     PageResultResource<UserDTO> getUsersWithGivenRoleAndNotWithGivenIds(String roleType, Set<Long> ids, Pageable pageable);
+
+
+    /**
+     * Gets a page of users specified by given predicate and pageable.
+     *
+     * @param predicate specifies query to database.
+     * @param pageable  pageable parameter with information about pagination.
+     * @return a list of the {@link UserDTO}s wrapped up in {@link PageResultResource}.
+     */
+    PageResultResource<UserDTO> getUsers(Predicate predicate, Pageable pageable, String roleType, Set<Long> userIds);
 }
diff --git a/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/RolesRestController.java b/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/RolesRestController.java
index 45bb399b..d855cf1e 100644
--- a/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/RolesRestController.java
+++ b/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/RolesRestController.java
@@ -237,9 +237,7 @@ public class RolesRestController {
             throw new BadRequestException("Choose page size lower than 1000");
         }
         try {
-            Predicate usersWithRoles = QUser.user.groups.any().roles.any().roleType.eq(roleType);
-            Predicate finalPredicate = QUser.user.id.notIn(userIds).and(usersWithRoles).and(predicate);
-            PageResultResource<UserDTO> userDTOs = userFacade.getUsers(finalPredicate, pageable);
+            PageResultResource<UserDTO> userDTOs = userFacade.getUsers(predicate, pageable, roleType, userIds);
             Squiggly.init(objectMapper, fields);
             return new ResponseEntity<>(SquigglyUtils.stringify(objectMapper, userDTOs), HttpStatus.OK);
         } catch (UserAndGroupFacadeException e) {
diff --git a/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/UsersRestController.java b/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/UsersRestController.java
index 8d4c982a..d6525cf1 100644
--- a/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/UsersRestController.java
+++ b/kypo2-rest-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/rest/controllers/UsersRestController.java
@@ -333,8 +333,7 @@ public class UsersRestController {
         if (ids.isEmpty()) {
             userDTOs = new PageResultResource<>(Collections.emptyList(), new PageResultResource.Pagination(0, 0, 0, 0, 0 ));
         } else {
-            Predicate finalPredicate = QUser.user.id.in(ids).and(predicate);
-            userDTOs = userFacade.getUsers(finalPredicate, pageable);
+            userDTOs = userFacade.getUsersWithGivenIds(ids, pageable, predicate);
         }
         Squiggly.init(objectMapper, fields);
         return new ResponseEntity<>(SquigglyUtils.stringify(objectMapper, userDTOs), HttpStatus.OK);
diff --git a/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/facade/UserFacadeImpl.java b/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/facade/UserFacadeImpl.java
index 1a060ad5..d41aec88 100644
--- a/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/facade/UserFacadeImpl.java
+++ b/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/facade/UserFacadeImpl.java
@@ -60,6 +60,12 @@ public class UserFacadeImpl implements UserFacade {
         return  userMapper.mapToPageResultResource(userService.getAllUsers(predicate, pageable));
     }
 
+    @Override
+    @TransactionalRO
+    public PageResultResource<UserDTO> getUsers(Predicate predicate, Pageable pageable, String roleType, Set<Long> userIds) {
+        return  userMapper.mapToPageResultResource(userService.getAllUsers(predicate, pageable, roleType, userIds));
+    }
+
     @Override
     @TransactionalRO
     public UserDTO getUser(Long id) {
@@ -195,6 +201,17 @@ public class UserFacadeImpl implements UserFacade {
     }
 
     @Override
+    public PageResultResource<UserDTO> getUsersWithGivenIds(Set<Long> ids, Pageable pageable, Predicate predicate) {
+        try {
+            return userMapper.mapToPageResultResource(userService.getUsersWithGivenIds(ids, pageable, predicate));
+
+        } catch (UserAndGroupServiceException ex) {
+            throw new UserAndGroupFacadeException(ex.getLocalizedMessage());
+        }
+    }
+
+    @Override
+    @TransactionalRO
     public PageResultResource<UserDTO> getUsersWithGivenRoleAndNotWithGivenIds(String roleType, Set<Long> ids, Pageable pageable) {
         try {
             return userMapper.mapToPageResultResource(userService.getUsersWithGivenRoleAndNotWithGivenIds(roleType, ids, pageable));
diff --git a/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/impl/UserServiceImpl.java b/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/impl/UserServiceImpl.java
index 23f969f5..240f06b5 100644
--- a/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/impl/UserServiceImpl.java
+++ b/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/impl/UserServiceImpl.java
@@ -5,6 +5,7 @@ import cz.muni.ics.kypo.userandgroup.annotations.security.IsAdmin;
 import cz.muni.ics.kypo.userandgroup.api.dto.enums.UserDeletionStatusDTO;
 import cz.muni.ics.kypo.userandgroup.exceptions.UserAndGroupServiceException;
 import cz.muni.ics.kypo.userandgroup.model.IDMGroup;
+import cz.muni.ics.kypo.userandgroup.model.QUser;
 import cz.muni.ics.kypo.userandgroup.model.Role;
 import cz.muni.ics.kypo.userandgroup.model.User;
 import cz.muni.ics.kypo.userandgroup.model.enums.UserAndGroupStatus;
@@ -135,6 +136,13 @@ public class UserServiceImpl implements UserService {
         return userRepository.findAll(predicate, pageable);
     }
 
+    @Override
+    public Page<User> getAllUsers(Predicate predicate, Pageable pageable, String roleType, Set<Long> userIds) {
+        Predicate usersWithRoles = QUser.user.groups.any().roles.any().roleType.eq(roleType);
+        Predicate finalPredicate = QUser.user.id.notIn(userIds).and(usersWithRoles).and(predicate);
+        return userRepository.findAll(finalPredicate, pageable);
+    }
+
     @Override
     @IsAdmin
     public Page<User> getAllUsersNotInGivenGroup(Long groupId, Pageable pageable) {
@@ -214,6 +222,12 @@ public class UserServiceImpl implements UserService {
         return userRepository.findAllWithGivenIds(ids, pageable);
     }
 
+    @Override
+    public Page<User> getUsersWithGivenIds(Set<Long> ids, Pageable pageable, Predicate predicate) {
+        Predicate finalPredicate = QUser.user.id.in(ids).and(predicate);
+        return userRepository.findAll(finalPredicate, pageable);
+    }
+
     @Override
     public Page<User> getUsersWithGivenRoleAndNotWithGivenIds(String roleType, Set<Long> ids, Pageable pageable) {
         Assert.notNull(roleType, "Role type must not be null");
diff --git a/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/interfaces/UserService.java b/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/interfaces/UserService.java
index eee1b1c8..71420e6c 100644
--- a/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/interfaces/UserService.java
+++ b/kypo2-service-user-and-group/src/main/java/cz/muni/ics/kypo/userandgroup/service/interfaces/UserService.java
@@ -82,6 +82,15 @@ public interface UserService {
      */
     Page<User> getAllUsers(Predicate predicate, Pageable pageable);
 
+    /**
+     * Gets all users from the database.
+     *
+     * @param predicate represents a predicate (boolean-valued function) of one argument.
+     * @param pageable  pageable parameter with information about pagination.
+     * @return list of {@link User}s wrapped up in {@link Page}.
+     */
+    Page<User> getAllUsers(Predicate predicate, Pageable pageable, String roleType, Set<Long> userIds);
+
     /**
      * Gets all users, not in a given IDMGroup with the given ID.
      *
@@ -165,6 +174,15 @@ public interface UserService {
      */
     Page<User> getUsersWithGivenIds(Set<Long> ids, Pageable pageable);
 
+    /**
+     * Gets users with a given set of ids.
+     *
+     * @param ids set of ids.
+     * @return set of {@link User}s with ids wrapped up in {@link Page}.
+     */
+    Page<User> getUsersWithGivenIds(Set<Long> ids, Pageable pageable, Predicate predicate);
+
+
     /**
      *  Returns a page of users specified by given role type and not with given ids.
      *
-- 
GitLab