]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6481 SONAR-6484 SONAR-4475 do not remove the last admin user or group permission
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 31 Jul 2015 09:15:27 +0000 (11:15 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 31 Jul 2015 09:57:49 +0000 (11:57 +0200)
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserAction.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ProjectsActionTest.java
server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java
server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java
sonar-db/src/main/java/org/sonar/db/user/RoleDao.java
sonar-db/src/main/java/org/sonar/db/user/RoleMapper.java
sonar-db/src/main/resources/org/sonar/db/user/RoleMapper.xml
sonar-db/src/test/java/org/sonar/db/user/RoleDaoTest.java

index 001a00d7507ae3d69be00a384ed7bb10c7a09440..2389efba4ec068482be3f807c3807d0c7eb4f307 100644 (file)
@@ -63,7 +63,7 @@ public class PermissionService {
   private final ComponentFinder componentFinder;
 
   public PermissionService(DbClient dbClient, PermissionRepository permissionRepository, PermissionFinder finder,
-                           IssueAuthorizationIndexer issueAuthorizationIndexer, UserSession userSession, ComponentFinder componentFinder) {
+    IssueAuthorizationIndexer issueAuthorizationIndexer, UserSession userSession, ComponentFinder componentFinder) {
     this.dbClient = dbClient;
     this.permissionRepository = permissionRepository;
     this.finder = finder;
@@ -206,6 +206,7 @@ public class PermissionService {
     if (Operation.ADD == operation) {
       permissionRepository.insertGroupPermission(componentId, targetedGroup, permissionChange.permission(), session);
     } else {
+      checkAdminUsersExistOutsideTheRemovedGroup(session, permissionChange, targetedGroup);
       permissionRepository.deleteGroupPermission(componentId, targetedGroup, permissionChange.permission(), session);
     }
     return true;
@@ -224,12 +225,27 @@ public class PermissionService {
     if (Operation.ADD == operation) {
       permissionRepository.insertUserPermission(componentId, targetedUser, permissionChange.permission(), session);
     } else {
+      checkOtherAdminUsersExist(session, permissionChange);
       permissionRepository.deleteUserPermission(componentId, targetedUser, permissionChange.permission(), session);
     }
     return true;
 
   }
 
+  private void checkOtherAdminUsersExist(DbSession session, PermissionChange permissionChange) {
+    if (GlobalPermissions.SYSTEM_ADMIN.equals(permissionChange.permission())
+      && dbClient.roleDao().countUserPermissions(session, permissionChange.permission(), null) <= 1) {
+      throw new BadRequestException(String.format("Last user with '%s' permission. Permission cannot be removed.", GlobalPermissions.SYSTEM_ADMIN));
+    }
+  }
+
+  private void checkAdminUsersExistOutsideTheRemovedGroup(DbSession session, PermissionChange permissionChange, Long groupIdToExclude) {
+    if (GlobalPermissions.SYSTEM_ADMIN.equals(permissionChange.permission())
+      && dbClient.roleDao().countUserPermissions(session, permissionChange.permission(), groupIdToExclude) <= 0) {
+      throw new BadRequestException(String.format("Last group with '%s' permission. Permission cannot be removed.", GlobalPermissions.SYSTEM_ADMIN));
+    }
+  }
+
   private Long getTargetedUser(DbSession session, String userLogin) {
     UserDto user = dbClient.userDao().selectActiveUserByLogin(session, userLogin);
     badRequestIfNullResult(user, OBJECT_TYPE_USER, userLogin);
index 87d4ff5f566e0929a47a4b2e24fc7fd99ea81c2d..708fecc0c9525e5c990d72025b94f2e31c3bf55c 100644 (file)
@@ -24,8 +24,8 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.permission.PermissionService;
 import org.sonar.server.permission.PermissionChange;
+import org.sonar.server.permission.PermissionService;
 
 public class RemoveUserAction implements PermissionsWsAction {
 
@@ -42,7 +42,7 @@ public class RemoveUserAction implements PermissionsWsAction {
   @Override
   public void define(WebService.NewController context) {
     WebService.NewAction action = context.createAction(ACTION)
-      .setDescription("Remove permission to a user.<br /> Requires 'Administer System' permission.")
+      .setDescription("Remove permission from a user.<br /> Requires 'Administer System' permission.")
       .setSince("5.2")
       .setPost(true)
       .setHandler(this);
index 6e730589b4d4331cdf0dc6d6297e22598b21f78a..780421e168bfb4d9a493f08f103c2c7a84c01277 100644 (file)
@@ -134,7 +134,7 @@ public class ApplyPermissionsStepTest extends BaseStepTest {
     ComponentDto projectDto = ComponentTesting.newProjectDto(PROJECT_UUID).setKey(PROJECT_KEY).setAuthorizationUpdatedAt(authorizationUpdatedAt);
     dbClient.componentDao().insert(dbSession, projectDto);
     // Permissions are already set on the project
-    dbClient.roleDao().insertGroupRole(new GroupRoleDto().setRole(UserRole.USER).setGroupId(null).setResourceId(projectDto.getId()), dbSession);
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto().setRole(UserRole.USER).setGroupId(null).setResourceId(projectDto.getId()));
 
     dbSession.commit();
 
index a254c97e6a76a546281a92c2913263fd322a08cf..c0cddb928cd8986938d2da140779a0406394fc7b 100644 (file)
@@ -117,7 +117,7 @@ public class ProjectsActionTest {
     dbClient.componentDao().insert(session, project1, project2);
 
     // user only sees project1
-    roleDao.insertUserRole(new UserRoleDto().setUserId(userId).setResourceId(project1.getId()).setRole(UserRole.USER), session);
+    roleDao.insertUserRole(session, new UserRoleDto().setUserId(userId).setResourceId(project1.getId()).setRole(UserRole.USER));
 
     associateProjectsWithProfile(session, xooP1, project1, project2);
 
@@ -231,7 +231,7 @@ public class ProjectsActionTest {
 
   private void addBrowsePermissionToAnyone(DbSession session, ComponentDto... projects) {
     for (ComponentDto project : projects) {
-      roleDao.insertGroupRole(new GroupRoleDto().setGroupId(null).setResourceId(project.getId()).setRole(UserRole.USER), session);
+      roleDao.insertGroupRole(session, new GroupRoleDto().setGroupId(null).setResourceId(project.getId()).setRole(UserRole.USER));
     }
   }
 
index 68365e85afbdff2736badd54fad15e8409701cf6..5465772752efc033543a96f105d81a6ac539f592 100644 (file)
@@ -125,7 +125,7 @@ public class DeleteActionTest {
   @Test
   public void delete_with_permissions() throws Exception {
     GroupDto group = groupDao.insert(session, new GroupDto().setName("to-delete"));
-    roleDao.insertGroupRole(new GroupRoleDto().setGroupId(group.getId()).setResourceId(42L).setRole(UserRole.ADMIN), session);
+    roleDao.insertGroupRole(session, new GroupRoleDto().setGroupId(group.getId()).setResourceId(42L).setRole(UserRole.ADMIN));
     session.commit();
 
     loginAsAdmin();
index c989b76e8c8f549b00100d54ea54c0b8b417a23e..75e86390690109dc5f3dbf4c08bb3e21dd16dd68 100644 (file)
@@ -213,7 +213,7 @@ public class ViewIndexerTest {
     ComponentDto project = ComponentTesting.newProjectDto();
     ComponentDto file = ComponentTesting.newFileDto(project);
     dbClient.componentDao().insert(dbSession, project, file);
-    dbClient.roleDao().insertGroupRole(new GroupRoleDto().setRole(UserRole.USER).setGroupId(null).setResourceId(project.getId()), dbSession);
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto().setRole(UserRole.USER).setGroupId(null).setResourceId(project.getId()));
 
     IssueDto issue = IssueTesting.newDto(rule, file, project);
     dbClient.issueDao().insert(dbSession, issue);
index aeaaceb1bf6de179667132afcb068392ee6e14c8..f34ce6cc9f8624f2b6934c3d1451e5a7f8b5ed09 100644 (file)
@@ -65,7 +65,7 @@ public class PermissionRepository {
     if (updateProjectAuthorizationDate) {
       updateProjectAuthorizationDate(session, resourceId);
     }
-    dbClient.roleDao().insertUserRole(userRoleDto, session);
+    dbClient.roleDao().insertUserRole(session, userRoleDto);
   }
 
   public void insertUserPermission(@Nullable Long resourceId, Long userId, String permission, DbSession session) {
@@ -87,7 +87,7 @@ public class PermissionRepository {
       .setGroupId(groupId)
       .setResourceId(resourceId);
     updateProjectAuthorizationDate(session, resourceId);
-    dbClient.roleDao().insertGroupRole(groupRole, session);
+    dbClient.roleDao().insertGroupRole(session, groupRole);
   }
 
   public void insertGroupPermission(@Nullable Long resourceId, @Nullable Long groupId, String permission, DbSession session) {
index 5833798adb6a3e94995b61bd17d089150849241c..a2cd68cffc4a2496459d13a965e33179e6a97942 100644 (file)
@@ -37,11 +37,11 @@ public class RoleDao implements Dao {
     return session.getMapper(RoleMapper.class).selectGroupPermissions(groupName, resourceId, DefaultGroups.isAnyone(groupName));
   }
 
-  public void insertGroupRole(GroupRoleDto groupRole, SqlSession session) {
+  public void insertGroupRole(DbSession session, GroupRoleDto groupRole) {
     mapper(session).insertGroupRole(groupRole);
   }
 
-  public void insertUserRole(UserRoleDto userRole, SqlSession session) {
+  public void insertUserRole(DbSession session, UserRoleDto userRole) {
     mapper(session).insertUserRole(userRole);
   }
 
@@ -77,6 +77,10 @@ public class RoleDao implements Dao {
     return countResourceGroupRoles(session, componentId) + countResourceUserRoles(session, componentId);
   }
 
+  public int countUserPermissions(DbSession session, String permission, @Nullable Long allGroupsExceptThisGroupId) {
+    return mapper(session).countUsersWithPermission(permission, allGroupsExceptThisGroupId);
+  }
+
   public void removeAllPermissions(DbSession session, Long resourceId) {
     deleteGroupRolesByResourceId(session, resourceId);
     deleteUserRolesByResourceId(session, resourceId);
index f26b59874bf03b8245f1013c272fa6427d9cac38..0667a4672c77267649ed7454ccfd3fca3fb7648d 100644 (file)
@@ -56,4 +56,5 @@ public interface RoleMapper {
 
   void deleteGroupRolesByGroupId(long groupId);
 
+  int countUsersWithPermission(@Param("permission") String permission, @Nullable @Param("groupId") Long groupId);
 }
index 41303206013de2df915d35713bf97c500560bb3f..d1f70ebd133250cbe1e905eed005f55e0d4751e3 100644 (file)
     FROM group_roles WHERE resource_id=#{id}
   </select>
 
+  <select id="countUsersWithPermission" parameterType="map" resultType="int">
+    SELECT count(id)
+    FROM (
+      SELECT DISTINCT ur.user_id as id
+      FROM user_roles ur
+      INNER JOIN users u ON u.id=ur.user_id AND u.active=${_true}
+      WHERE
+        ur.role = #{permission} and ur.resource_id IS NULL
+      UNION ALL
+      SELECT DISTINCT u.ID as id
+      FROM users u
+      INNER JOIN groups_users gu ON gu.user_id = u.id
+      INNER JOIN group_roles gr ON gr.group_id = gu.group_id
+      INNER JOIN groups g ON g.id = gu.group_id
+      WHERE
+        gr.role = #{permission}
+        AND gr.resource_id IS NULL
+        AND u.active = true
+        <if test="groupId!=null">
+          AND g.id!=#{groupId}
+        </if>
+    )
+  </select>
+
   <delete id="deleteGroupRolesByGroupId" parameterType="long">
     delete from group_roles where group_id=#{id}
   </delete>
index 9c1af133dca0ea5f687d930826991d93c18aa6d8..28bd8251c066119705fee6ad0097d93a7e40c877 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.test.DbTests;
 
@@ -36,127 +37,190 @@ import static org.assertj.core.api.Assertions.assertThat;
 public class RoleDaoTest {
 
   @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create(System2.INSTANCE);
 
-  RoleDao underTest = dbTester.getDbClient().roleDao();
+  RoleDao underTest = db.getDbClient().roleDao();
 
   @Test
   public void retrieve_global_user_permissions() {
-    dbTester.prepareDbUnit(getClass(), "globalUserPermissions.xml");
+    db.prepareDbUnit(getClass(), "globalUserPermissions.xml");
 
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "admin_user", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "profile_admin_user", null)).containsOnly(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    assertThat(underTest.selectUserPermissions(db.getSession(), "admin_user", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    assertThat(underTest.selectUserPermissions(db.getSession(), "profile_admin_user", null)).containsOnly(GlobalPermissions.QUALITY_PROFILE_ADMIN);
   }
 
   @Test
   public void retrieve_resource_user_permissions() {
-    dbTester.prepareDbUnit(getClass(), "resourceUserPermissions.xml");
+    db.prepareDbUnit(getClass(), "resourceUserPermissions.xml");
 
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "admin_user", 1L)).containsOnly(UserRole.ADMIN, UserRole.USER);
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "browse_admin_user", 1L)).containsOnly(UserRole.USER);
+    assertThat(underTest.selectUserPermissions(db.getSession(), "admin_user", 1L)).containsOnly(UserRole.ADMIN, UserRole.USER);
+    assertThat(underTest.selectUserPermissions(db.getSession(), "browse_admin_user", 1L)).containsOnly(UserRole.USER);
   }
 
   @Test
   public void retrieve_global_group_permissions() {
-    dbTester.prepareDbUnit(getClass(), "globalGroupPermissions.xml");
+    db.prepareDbUnit(getClass(), "globalGroupPermissions.xml");
 
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "sonar-administrators", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN,
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "sonar-administrators", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN,
+      GlobalPermissions.QUALITY_PROFILE_ADMIN,
       GlobalPermissions.DASHBOARD_SHARING);
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "sonar-users", null)).containsOnly(GlobalPermissions.DASHBOARD_SHARING);
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), DefaultGroups.ANYONE, null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION);
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "anyone", null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION);
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "AnYoNe", null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "sonar-users", null)).containsOnly(GlobalPermissions.DASHBOARD_SHARING);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), DefaultGroups.ANYONE, null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION,
+      GlobalPermissions.SCAN_EXECUTION);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "anyone", null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "AnYoNe", null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION);
   }
 
   @Test
   public void retrieve_resource_group_permissions() {
-    dbTester.prepareDbUnit(getClass(), "resourceGroupPermissions.xml");
+    db.prepareDbUnit(getClass(), "resourceGroupPermissions.xml");
 
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "sonar-administrators", 1L)).containsOnly(UserRole.ADMIN, UserRole.CODEVIEWER);
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "sonar-users", 1L)).containsOnly(UserRole.CODEVIEWER);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "sonar-administrators", 1L)).containsOnly(UserRole.ADMIN, UserRole.CODEVIEWER);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "sonar-users", 1L)).containsOnly(UserRole.CODEVIEWER);
   }
 
   @Test
   public void delete_global_user_permission() {
-    dbTester.prepareDbUnit(getClass(), "globalUserPermissions.xml");
+    db.prepareDbUnit(getClass(), "globalUserPermissions.xml");
 
     UserRoleDto userRoleToDelete = new UserRoleDto().setUserId(200L).setRole(GlobalPermissions.QUALITY_PROFILE_ADMIN);
 
-    underTest.deleteUserRole(userRoleToDelete, dbTester.getSession());
-    dbTester.getSession().commit();
+    underTest.deleteUserRole(userRoleToDelete, db.getSession());
+    db.getSession().commit();
 
-    dbTester.assertDbUnit(getClass(), "globalUserPermissions-result.xml", "user_roles");
+    db.assertDbUnit(getClass(), "globalUserPermissions-result.xml", "user_roles");
   }
 
   @Test
   public void delete_resource_user_permission() {
-    dbTester.prepareDbUnit(getClass(), "resourceUserPermissions.xml");
+    db.prepareDbUnit(getClass(), "resourceUserPermissions.xml");
 
     UserRoleDto userRoleToDelete = new UserRoleDto().setUserId(200L).setRole(UserRole.USER).setResourceId(1L);
 
-    underTest.deleteUserRole(userRoleToDelete, dbTester.getSession());
-    dbTester.getSession().commit();
+    underTest.deleteUserRole(userRoleToDelete, db.getSession());
+    db.getSession().commit();
 
-    dbTester.assertDbUnit(getClass(), "resourceUserPermissions-result.xml", "user_roles");
+    db.assertDbUnit(getClass(), "resourceUserPermissions-result.xml", "user_roles");
   }
 
   @Test
   public void delete_global_group_permission() {
-    dbTester.prepareDbUnit(getClass(), "globalGroupPermissions.xml");
+    db.prepareDbUnit(getClass(), "globalGroupPermissions.xml");
 
     GroupRoleDto groupRoleToDelete = new GroupRoleDto().setGroupId(100L).setRole(GlobalPermissions.QUALITY_PROFILE_ADMIN);
 
-    underTest.deleteGroupRole(groupRoleToDelete, dbTester.getSession());
-    dbTester.getSession().commit();
+    underTest.deleteGroupRole(groupRoleToDelete, db.getSession());
+    db.getSession().commit();
 
-    dbTester.assertDbUnit(getClass(), "globalGroupPermissions-result.xml", "group_roles");
+    db.assertDbUnit(getClass(), "globalGroupPermissions-result.xml", "group_roles");
   }
 
   @Test
   public void delete_resource_group_permission() {
-    dbTester.prepareDbUnit(getClass(), "resourceGroupPermissions.xml");
+    db.prepareDbUnit(getClass(), "resourceGroupPermissions.xml");
 
     GroupRoleDto groupRoleToDelete = new GroupRoleDto().setGroupId(100L).setRole(UserRole.CODEVIEWER).setResourceId(1L);
 
-    underTest.deleteGroupRole(groupRoleToDelete, dbTester.getSession());
-    dbTester.getSession().commit();
+    underTest.deleteGroupRole(groupRoleToDelete, db.getSession());
+    db.getSession().commit();
 
-    dbTester.assertDbUnit(getClass(), "resourceGroupPermissions-result.xml", "group_roles");
+    db.assertDbUnit(getClass(), "resourceGroupPermissions-result.xml", "group_roles");
   }
 
   @Test
   public void delete_all_group_permissions_by_group_id() {
-    dbTester.prepareDbUnit(getClass(), "deleteGroupPermissionsByGroupId.xml");
+    db.prepareDbUnit(getClass(), "deleteGroupPermissionsByGroupId.xml");
 
-    underTest.deleteGroupRolesByGroupId(dbTester.getSession(), 100L);
-    dbTester.getSession().commit();
+    underTest.deleteGroupRolesByGroupId(db.getSession(), 100L);
+    db.getSession().commit();
 
-    dbTester.assertDbUnit(getClass(), "deleteGroupPermissionsByGroupId-result.xml", "group_roles");
+    db.assertDbUnit(getClass(), "deleteGroupPermissionsByGroupId-result.xml", "group_roles");
   }
 
   @Test
   public void should_count_component_permissions() {
-    dbTester.prepareDbUnit(getClass(), "should_count_component_permissions.xml");
+    db.prepareDbUnit(getClass(), "should_count_component_permissions.xml");
 
-    assertThat(underTest.countComponentPermissions(dbTester.getSession(), 123L)).isEqualTo(2);
+    assertThat(underTest.countComponentPermissions(db.getSession(), 123L)).isEqualTo(2);
   }
 
   @Test
   public void should_remove_all_permissions() {
-    dbTester.prepareDbUnit(getClass(), "should_remove_all_permissions.xml");
+    db.prepareDbUnit(getClass(), "should_remove_all_permissions.xml");
 
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "devs", 123L)).hasSize(1);
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "other", 123L)).isEmpty();
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "dave.loper", 123L)).hasSize(1);
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "other.user", 123L)).isEmpty();
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "devs", 123L)).hasSize(1);
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "other", 123L)).isEmpty();
+    assertThat(underTest.selectUserPermissions(db.getSession(), "dave.loper", 123L)).hasSize(1);
+    assertThat(underTest.selectUserPermissions(db.getSession(), "other.user", 123L)).isEmpty();
 
-    underTest.removeAllPermissions(dbTester.getSession(), 123L);
-    dbTester.getSession().commit();
+    underTest.removeAllPermissions(db.getSession(), 123L);
+    db.getSession().commit();
 
-    dbTester.assertDbUnitTable(getClass(), "should_remove_all_permissions-result.xml", "group_roles", "group_id", "resource_id", "role");
-    dbTester.assertDbUnitTable(getClass(), "should_remove_all_permissions-result.xml", "user_roles", "user_id", "resource_id", "role");
+    db.assertDbUnitTable(getClass(), "should_remove_all_permissions-result.xml", "group_roles", "group_id", "resource_id", "role");
+    db.assertDbUnitTable(getClass(), "should_remove_all_permissions-result.xml", "user_roles", "user_id", "resource_id", "role");
 
-    assertThat(underTest.selectGroupPermissions(dbTester.getSession(), "devs", 123L)).isEmpty();
-    assertThat(underTest.selectUserPermissions(dbTester.getSession(), "dave.loper", 123L)).isEmpty();
+    assertThat(underTest.selectGroupPermissions(db.getSession(), "devs", 123L)).isEmpty();
+    assertThat(underTest.selectUserPermissions(db.getSession(), "dave.loper", 123L)).isEmpty();
+  }
+
+  @Test
+  public void count_users_with_one_specific_permission() {
+    DbClient dbClient = db.getDbClient();
+    UserDto user = dbClient.userDao().insert(db.getSession(), new UserDto().setActive(true));
+    dbClient.roleDao().insertUserRole(db.getSession(), new UserRoleDto()
+      .setUserId(user.getId())
+      .setResourceId(123L)
+      .setRole(GlobalPermissions.SYSTEM_ADMIN));
+    dbClient.roleDao().insertUserRole(db.getSession(), new UserRoleDto()
+      .setUserId(user.getId())
+      .setRole(GlobalPermissions.SYSTEM_ADMIN));
+    dbClient.roleDao().insertUserRole(db.getSession(), new UserRoleDto()
+      .setUserId(user.getId())
+      .setRole(GlobalPermissions.SCAN_EXECUTION));
+
+    int result = underTest.countUserPermissions(db.getSession(), GlobalPermissions.SYSTEM_ADMIN, null);
+
+    assertThat(result).isEqualTo(1);
+  }
+
+  @Test
+  public void count_users_with_one_permission_when_the_last_one_is_in_a_group() {
+    DbClient dbClient = db.getDbClient();
+
+    UserDto user = dbClient.userDao().insert(db.getSession(), new UserDto().setActive(true));
+    GroupDto group = dbClient.groupDao().insert(db.getSession(), new GroupDto());
+    dbClient.userGroupDao().insert(db.getSession(), new UserGroupDto()
+      .setGroupId(group.getId())
+      .setUserId(user.getId()));
+    dbClient.roleDao().insertGroupRole(db.getSession(), new GroupRoleDto()
+      .setGroupId(group.getId())
+      .setRole(GlobalPermissions.SYSTEM_ADMIN));
+
+    int resultWithoutExcludingGroup = underTest.countUserPermissions(db.getSession(), GlobalPermissions.SYSTEM_ADMIN, null);
+    int resultWithGroupExclusion = underTest.countUserPermissions(db.getSession(), GlobalPermissions.SYSTEM_ADMIN, group.getId());
+
+    assertThat(resultWithoutExcludingGroup).isEqualTo(1);
+    assertThat(resultWithGroupExclusion).isEqualTo(0);
+  }
+
+  @Test
+  public void count_user_twice_when_user_and_group_permission() {
+    DbClient dbClient = db.getDbClient();
+
+    UserDto user = dbClient.userDao().insert(db.getSession(), new UserDto().setActive(true));
+    GroupDto group = dbClient.groupDao().insert(db.getSession(), new GroupDto());
+    dbClient.userGroupDao().insert(db.getSession(), new UserGroupDto()
+      .setGroupId(group.getId())
+      .setUserId(user.getId()));
+    dbClient.roleDao().insertGroupRole(db.getSession(), new GroupRoleDto()
+      .setGroupId(group.getId())
+      .setRole(GlobalPermissions.SYSTEM_ADMIN));
+    dbClient.roleDao().insertUserRole(db.getSession(), new UserRoleDto()
+      .setUserId(user.getId())
+      .setRole(GlobalPermissions.SYSTEM_ADMIN));
+
+    int result = underTest.countUserPermissions(db.getSession(), GlobalPermissions.SYSTEM_ADMIN, null);
+
+    assertThat(result).isEqualTo(2);
   }
 }