]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7835 Select users by query
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 5 Jul 2016 12:53:32 +0000 (14:53 +0200)
committerStas Vilchik <vilchiks@gmail.com>
Tue, 12 Jul 2016 08:16:53 +0000 (10:16 +0200)
30 files changed:
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionFinder.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/OldUsersAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsParametersBuilder.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchGlobalPermissionsAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/TemplateGroupsAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/TemplateUsersAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddGroupToTemplateAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddUserToTemplateAction.java
server/sonar-server/src/test/java/org/sonar/server/permission/PermissionQueryTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddGroupToTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddUserToTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/BulkApplyTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateActionTest.java
sonar-db/src/main/java/org/sonar/db/permission/OldPermissionQuery.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionQuery.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
sonar-db/src/main/java/org/sonar/db/permission/UserRef.java [new file with mode: 0644]
sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml
sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDaoTest.java
sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest.java
sonar-db/src/test/java/org/sonar/db/permission/OldPermissionQueryTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/permission/PermissionDbTester.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDaoTest.java
sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTemplateDaoTest.java

index 554e24a0d7d69d5681520be57af1d85ef5e515d9..15949413fabbb482f8b4440b222a5e06b9e3d5c1 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.db.component.ResourceDto;
 import org.sonar.db.component.ResourceQuery;
 import org.sonar.db.permission.GroupWithPermissionDto;
 import org.sonar.db.permission.PermissionDao;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.server.exceptions.NotFoundException;
 
@@ -55,7 +55,7 @@ public class PermissionFinder {
     this.permissionDao = dbClient.permissionDao();
   }
 
-  public List<UserWithPermissionDto> findUsersWithPermission(DbSession dbSession, PermissionQuery query) {
+  public List<UserWithPermissionDto> findUsersWithPermission(DbSession dbSession, OldPermissionQuery query) {
     Long componentId = componentId(query.component());
     int limit = query.pageSize();
     return permissionDao.selectUsers(dbSession, query, componentId, offset(query), limit);
@@ -64,7 +64,7 @@ public class PermissionFinder {
   /**
    * Paging for groups search is done in Java in order to correctly handle the 'Anyone' group
    */
-  public List<GroupWithPermissionDto> findGroupsWithPermission(DbSession dbSession, PermissionQuery query) {
+  public List<GroupWithPermissionDto> findGroupsWithPermission(DbSession dbSession, OldPermissionQuery query) {
     Long componentId = componentId(query.component());
     return toGroupQueryResult(permissionDao.selectGroups(dbSession, query, componentId), query);
   }
@@ -82,7 +82,7 @@ public class PermissionFinder {
     }
   }
 
-  private static List<GroupWithPermissionDto> toGroupQueryResult(List<GroupWithPermissionDto> dtos, PermissionQuery query) {
+  private static List<GroupWithPermissionDto> toGroupQueryResult(List<GroupWithPermissionDto> dtos, OldPermissionQuery query) {
     addAnyoneGroup(dtos, query);
     List<GroupWithPermissionDto> filteredDtos = filterMembership(dtos, query);
 
@@ -93,13 +93,13 @@ public class PermissionFinder {
     return pagedGroups(filteredDtos, paging);
   }
 
-  private static int offset(PermissionQuery query) {
+  private static int offset(OldPermissionQuery query) {
     int pageSize = query.pageSize();
     int pageIndex = query.pageIndex();
     return (pageIndex - 1) * pageSize;
   }
 
-  private static List<GroupWithPermissionDto> filterMembership(List<GroupWithPermissionDto> dtos, PermissionQuery query) {
+  private static List<GroupWithPermissionDto> filterMembership(List<GroupWithPermissionDto> dtos, OldPermissionQuery query) {
     return newArrayList(Iterables.filter(dtos, new GroupWithPermissionMatchQuery(query)));
   }
 
@@ -107,7 +107,7 @@ public class PermissionFinder {
    * As the anyone group does not exists in db, it's not returned when it has not the permission.
    * We have to manually add it at the begin of the list, if it matched the search text
    */
-  private static void addAnyoneGroup(List<GroupWithPermissionDto> groups, PermissionQuery query) {
+  private static void addAnyoneGroup(List<GroupWithPermissionDto> groups, OldPermissionQuery query) {
     boolean hasAnyoneGroup = Iterables.any(groups, IsAnyoneGroup.INSTANCE);
     if (!hasAnyoneGroup
       && !GlobalPermissions.SYSTEM_ADMIN.equals(query.permission())
@@ -131,17 +131,17 @@ public class PermissionFinder {
   }
 
   private static class GroupWithPermissionMatchQuery implements Predicate<GroupWithPermissionDto> {
-    private final PermissionQuery query;
+    private final OldPermissionQuery query;
 
-    public GroupWithPermissionMatchQuery(PermissionQuery query) {
+    public GroupWithPermissionMatchQuery(OldPermissionQuery query) {
       this.query = query;
     }
 
     @Override
     public boolean apply(@Nonnull GroupWithPermissionDto dto) {
-      if (PermissionQuery.IN.equals(query.membership())) {
+      if (OldPermissionQuery.IN.equals(query.membership())) {
         return dto.getPermission() != null;
-      } else if (PermissionQuery.OUT.equals(query.membership())) {
+      } else if (OldPermissionQuery.OUT.equals(query.membership())) {
         return dto.getPermission() == null;
       }
       return true;
index bf11e1f98133047014c67445f7e588fad8518752..4346b4ae2bfcccda2feaac74a08a95d74f78ac44 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.server.permission.PermissionFinder;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.Common;
@@ -98,7 +98,7 @@ public class GroupsAction implements PermissionsWsAction {
       Optional<ComponentDto> project = dependenciesFinder.searchProject(dbSession, newOptionalWsProjectRef(request.getProjectId(), request.getProjectKey()));
       checkProjectAdminUserByComponentDto(userSession, project);
 
-      PermissionQuery permissionQuery = buildPermissionQuery(request, project);
+      OldPermissionQuery permissionQuery = buildPermissionQuery(request, project);
       Long projectIdIfPresent = project.isPresent() ? project.get().getId() : null;
       int total = dbClient.permissionDao().countGroups(dbSession, permissionQuery.permission(), projectIdIfPresent);
       List<GroupWithPermissionDto> groupsWithPermission = permissionFinder.findGroupsWithPermission(dbSession, permissionQuery);
@@ -128,8 +128,8 @@ public class GroupsAction implements PermissionsWsAction {
       .setSelected(request.mandatoryParam(Param.SELECTED));
   }
 
-  private static PermissionQuery buildPermissionQuery(GroupsWsRequest request, Optional<ComponentDto> project) {
-    PermissionQuery.Builder permissionQuery = PermissionQuery.builder()
+  private static OldPermissionQuery buildPermissionQuery(GroupsWsRequest request, Optional<ComponentDto> project) {
+    OldPermissionQuery.Builder permissionQuery = OldPermissionQuery.builder()
       .permission(request.getPermission())
       .pageIndex(request.getPage())
       .pageSize(request.getPageSize())
index 830964e8993613bc0a56004841b32749f8a12168..fbee4d1eb4d7d8474398be917ddd0ded251c7787 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.utils.Paging;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.server.permission.PermissionFinder;
 import org.sonar.server.user.UserSession;
@@ -99,7 +99,7 @@ public class OldUsersAction implements PermissionsWsAction {
     try {
       Optional<ComponentDto> project = dependenciesFinder.searchProject(dbSession, wsProjectRef);
       checkProjectAdminUserByComponentDto(userSession, project);
-      PermissionQuery permissionQuery = buildPermissionQuery(request, project);
+      OldPermissionQuery permissionQuery = buildPermissionQuery(request, project);
       Long projectIdIfPresent = project.isPresent() ? project.get().getId() : null;
       int total = dbClient.permissionDao().countUsers(dbSession, permissionQuery, projectIdIfPresent);
       List<UserWithPermissionDto> usersWithPermission = permissionFinder.findUsersWithPermission(dbSession, permissionQuery);
@@ -143,8 +143,8 @@ public class OldUsersAction implements PermissionsWsAction {
     return userResponse.build();
   }
 
-  private static PermissionQuery buildPermissionQuery(OldUsersWsRequest request, Optional<ComponentDto> project) {
-    PermissionQuery.Builder permissionQuery = PermissionQuery.builder()
+  private static OldPermissionQuery buildPermissionQuery(OldUsersWsRequest request, Optional<ComponentDto> project) {
+    OldPermissionQuery.Builder permissionQuery = OldPermissionQuery.builder()
       .permission(request.getPermission())
       .pageIndex(request.getPage())
       .pageSize(request.getPageSize())
index 4acfc3b4513fc55c3cab30a02dd38e806bb2b19e..c616ae192fe35fc331ed8503710a70d941be411e 100644 (file)
@@ -58,8 +58,8 @@ public class PermissionsWsParametersBuilder {
     // static methods only
   }
 
-  public static void createPermissionParameter(NewAction action) {
-    action.createParam(PARAM_PERMISSION)
+  public static NewParam createPermissionParameter(NewAction action) {
+    return action.createParam(PARAM_PERMISSION)
       .setDescription(PERMISSION_PARAM_DESCRIPTION)
       .setRequired(true);
   }
index 14321bdb43ee711fd3c3b5a5e0af8396e873ae88..1dc976c276843c6f57dc3f88e84b15e425dc06bd 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.user.GroupMembershipQuery;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.WsPermissions.Permission;
@@ -78,7 +78,7 @@ public class SearchGlobalPermissionsAction implements PermissionsWsAction {
     Permission.Builder permission = newBuilder();
 
     for (String permissionKey : GlobalPermissions.ALL) {
-      PermissionQuery permissionQuery = permissionQuery(permissionKey);
+      OldPermissionQuery permissionQuery = permissionQuery(permissionKey);
 
       response.addPermissions(
         permission
@@ -106,12 +106,12 @@ public class SearchGlobalPermissionsAction implements PermissionsWsAction {
     return dbClient.permissionDao().countGroups(dbSession, permissionKey, null);
   }
 
-  private int countUsers(DbSession dbSession, PermissionQuery permissionQuery) {
+  private int countUsers(DbSession dbSession, OldPermissionQuery permissionQuery) {
     return dbClient.permissionDao().countUsers(dbSession, permissionQuery, null);
   }
 
-  private static PermissionQuery permissionQuery(String permissionKey) {
-    return PermissionQuery.builder()
+  private static OldPermissionQuery permissionQuery(String permissionKey) {
+    return OldPermissionQuery.builder()
       .permission(permissionKey)
       .membership(GroupMembershipQuery.IN)
       .build();
index 94c3871665ab5a9754d0a55d3b4131578d74c4b1..5e92540405f6c3966424acc05965ef01b6a3c768 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.server.ws.WebService.SelectionMode;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.WsPermissions.Group;
@@ -81,7 +81,7 @@ public class TemplateGroupsAction implements PermissionsWsAction {
       WsTemplateRef templateRef = WsTemplateRef.fromRequest(wsRequest);
       PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateRef);
 
-      PermissionQuery query = buildQuery(wsRequest, template);
+      OldPermissionQuery query = buildQuery(wsRequest, template);
       WsGroupsResponse groupsResponse = buildResponse(dbSession, query, template);
 
       writeProtobuf(groupsResponse, wsRequest, wsResponse);
@@ -90,7 +90,7 @@ public class TemplateGroupsAction implements PermissionsWsAction {
     }
   }
 
-  private WsGroupsResponse buildResponse(DbSession dbSession, PermissionQuery query, PermissionTemplateDto template) {
+  private WsGroupsResponse buildResponse(DbSession dbSession, OldPermissionQuery query, PermissionTemplateDto template) {
     int total = dbClient.permissionTemplateDao().countGroups(dbSession, query, template.getId());
     List<GroupWithPermissionDto> groupsWithPermission = dbClient.permissionTemplateDao().selectGroups(dbSession, query, template.getId(), query.pageOffset(), query.pageSize());
 
@@ -109,10 +109,10 @@ public class TemplateGroupsAction implements PermissionsWsAction {
     return groupsResponse.build();
   }
 
-  private static PermissionQuery buildQuery(Request request, PermissionTemplateDto template) {
+  private static OldPermissionQuery buildQuery(Request request, PermissionTemplateDto template) {
     String permission = validateProjectPermission(request.mandatoryParam(PARAM_PERMISSION));
 
-    PermissionQuery.Builder permissionQuery = PermissionQuery.builder()
+    OldPermissionQuery.Builder permissionQuery = OldPermissionQuery.builder()
       .permission(permission)
       .pageIndex(request.mandatoryParamAsInt(Param.PAGE))
       .pageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
index bd63a924e077395d6449523e412f7345561a8b36..b115ad453f03fa13502d5a2b708b0c44159248da 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.server.ws.WebService.SelectionMode;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.server.user.UserSession;
@@ -85,7 +85,7 @@ public class TemplateUsersAction implements PermissionsWsAction {
       WsTemplateRef templateRef = WsTemplateRef.fromRequest(wsRequest);
       PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateRef);
 
-      PermissionQuery query = buildQuery(wsRequest, template);
+      OldPermissionQuery query = buildQuery(wsRequest, template);
       WsPermissions.OldUsersWsResponse templateUsersResponse = buildResponse(dbSession, query, template);
       writeProtobuf(templateUsersResponse, wsRequest, wsResponse);
     } finally {
@@ -93,10 +93,10 @@ public class TemplateUsersAction implements PermissionsWsAction {
     }
   }
 
-  private static PermissionQuery buildQuery(Request wsRequest, PermissionTemplateDto template) {
+  private static OldPermissionQuery buildQuery(Request wsRequest, PermissionTemplateDto template) {
     String permission = validateProjectPermission(wsRequest.mandatoryParam(PARAM_PERMISSION));
 
-    return PermissionQuery.builder()
+    return OldPermissionQuery.builder()
       .template(template.getUuid())
       .permission(permission)
       .membership(fromSelectionModeToMembership(wsRequest.mandatoryParam(Param.SELECTED)))
@@ -106,7 +106,7 @@ public class TemplateUsersAction implements PermissionsWsAction {
       .build();
   }
 
-  private OldUsersWsResponse buildResponse(DbSession dbSession, PermissionQuery query, PermissionTemplateDto template) {
+  private OldUsersWsResponse buildResponse(DbSession dbSession, OldPermissionQuery query, PermissionTemplateDto template) {
     List<UserWithPermissionDto> usersWithPermission = dbClient.permissionTemplateDao().selectUsers(dbSession, query, template.getId(), query.pageOffset(), query.pageSize());
     int total = dbClient.permissionTemplateDao().countUsers(dbSession, query, template.getId());
 
index 40f50538e050aa3eeed521d597ca5a00f4827edd..2950f8733ebd9773a364d674ab18dd34a65eb8fe 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.api.utils.Paging;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionQuery;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.server.permission.PermissionFinder;
@@ -39,6 +40,8 @@ import org.sonarqube.ws.client.permission.UsersWsRequest;
 
 import static com.google.common.base.Strings.nullToEmpty;
 import static org.sonar.api.utils.Paging.forPageIndex;
+import static org.sonar.db.permission.PermissionQuery.DEFAULT_PAGE_SIZE;
+import static org.sonar.db.permission.PermissionQuery.RESULTS_MAX_SIZE;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentDto;
 import static org.sonar.server.permission.ws.PermissionRequestValidator.validatePermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
@@ -51,8 +54,6 @@ import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_P
 
 public class UsersAction implements PermissionsWsAction {
 
-  private static final int MAX_SIZE = 100;
-
   private final DbClient dbClient;
   private final UserSession userSession;
   private final PermissionFinder permissionFinder;
@@ -73,13 +74,15 @@ public class UsersAction implements PermissionsWsAction {
         "This service defaults to global permissions, but can be limited to project permissions by providing project id or project key.<br> " +
         "This service defaults to all users, but can be limited to users with a specific permission by providing the desired permission.<br>" +
         "It requires administration permissions to access.")
-      .addPagingParams(20, MAX_SIZE)
-      .addSearchQuery("stas", "names")
+      .addPagingParams(DEFAULT_PAGE_SIZE, RESULTS_MAX_SIZE)
       .setInternal(true)
       .setResponseExample(getClass().getResource("users-example.json"))
       .setHandler(this);
 
-    createPermissionParameter(action);
+    action.createParam(Param.TEXT_QUERY)
+      .setDescription("Limit search to user names that contain the supplied string. Must have at least %d characters.", PermissionQuery.SEARCH_QUERY_MIN_LENGTH)
+      .setExampleValue("eri");
+    createPermissionParameter(action).setRequired(false);
     createProjectParameters(action);
   }
 
@@ -96,7 +99,7 @@ public class UsersAction implements PermissionsWsAction {
     try {
       Optional<ComponentDto> project = dependenciesFinder.searchProject(dbSession, wsProjectRef);
       checkProjectAdminUserByComponentDto(userSession, project);
-      PermissionQuery permissionQuery = buildPermissionQuery(request, project);
+      OldPermissionQuery permissionQuery = buildPermissionQuery(request, project);
       Long projectIdIfPresent = project.isPresent() ? project.get().getId() : null;
       int total = dbClient.permissionDao().countUsers(dbSession, permissionQuery, projectIdIfPresent);
       List<UserWithPermissionDto> usersWithPermission = permissionFinder.findUsersWithPermission(dbSession, permissionQuery);
@@ -139,8 +142,8 @@ public class UsersAction implements PermissionsWsAction {
     return userResponse.build();
   }
 
-  private static PermissionQuery buildPermissionQuery(UsersWsRequest request, Optional<ComponentDto> project) {
-    PermissionQuery.Builder permissionQuery = PermissionQuery.builder()
+  private static OldPermissionQuery buildPermissionQuery(UsersWsRequest request, Optional<ComponentDto> project) {
+    OldPermissionQuery.Builder permissionQuery = OldPermissionQuery.builder()
       .permission(request.getPermission())
       .pageIndex(request.getPage())
       .pageSize(request.getPageSize())
index 7415ff304262b27f234ff6c8059bf3c1822e382c..ceddba001b5060bcfd5a381b3a298d8fad11074a 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.server.permission.ws.PermissionDependenciesFinder;
@@ -110,7 +110,7 @@ public class AddGroupToTemplateAction implements PermissionsWsAction {
 
   private boolean groupAlreadyAdded(DbSession dbSession, long templateId, @Nullable GroupDto group, String permission) {
     String groupName = group == null ? ANYONE : group.getName();
-    PermissionQuery permissionQuery = PermissionQuery.builder().membership(IN).permission(permission).build();
+    OldPermissionQuery permissionQuery = OldPermissionQuery.builder().membership(IN).permission(permission).build();
     return dbClient.permissionTemplateDao().hasGroup(dbSession, permissionQuery, templateId, groupName);
   }
 
index a6d895e516935058dbcc2117c148e9f163e829b5..c0da46c091158622d4c11e23e2796845396e666e 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.db.user.UserDto;
@@ -108,7 +108,7 @@ public class AddUserToTemplateAction implements PermissionsWsAction {
   }
 
   private boolean isUserAlreadyAdded(DbSession dbSession, long templateId, String userLogin, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    OldPermissionQuery permissionQuery = OldPermissionQuery.builder().permission(permission).membership(IN).build();
     List<UserWithPermissionDto> usersWithPermission = dbClient.permissionTemplateDao().selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE);
     return from(usersWithPermission).anyMatch(new HasUserPredicate(userLogin));
   }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionQueryTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionQueryTest.java
deleted file mode 100644 (file)
index 06d1aa9..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.permission;
-
-import org.junit.Test;
-import org.sonar.db.permission.PermissionQuery;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-public class PermissionQueryTest {
-
-  @Test
-  public void fail_on_null_permission() {
-    PermissionQuery.Builder builder = PermissionQuery.builder();
-    builder.permission(null);
-
-    try {
-      builder.build();
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(NullPointerException.class).hasMessage("Permission cannot be null.");
-    }
-  }
-
-  @Test
-  public void fail_on_invalid_membership() {
-    PermissionQuery.Builder builder = PermissionQuery.builder();
-    builder.permission("admin");
-    builder.membership("unknwown");
-
-    try {
-      builder.build();
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Membership is not valid (got unknwown). Availables values are [ANY, IN, OUT]");
-    }
-  }
-
-}
index f94005ad729ba664f38bd24a9543af4171c843b6..4339c5421de8573213252a38bfe9ad0981fb6f6f 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.server.component.ComponentFinder;
@@ -238,7 +238,7 @@ public class AddGroupToTemplateActionTest {
   }
 
   private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    OldPermissionQuery permissionQuery = OldPermissionQuery.builder().permission(permission).membership(IN).build();
     return from(dbClient.permissionTemplateDao()
       .selectGroups(dbSession, permissionQuery, templateId))
       .transform(GroupWithPermissionToGroupName.INSTANCE)
index d82607564d38ef2a6c6bbd4fd47b5084e6f695ca..5574cad4d15a1b5048340d770289196ec3e84c1c 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ResourceTypesRule;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.db.user.UserDto;
@@ -207,7 +207,7 @@ public class AddUserToTemplateActionTest {
   }
 
   private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    OldPermissionQuery permissionQuery = OldPermissionQuery.builder().permission(permission).membership(IN).build();
     return from(dbClient.permissionTemplateDao()
       .selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE))
       .transform(UserWithPermissionToUserLogin.INSTANCE)
index 973e760cdf82f19f990a0374f8549cb26e38dade..add9707d3648f629022773e8e41037a69dde50f3 100644 (file)
@@ -38,7 +38,7 @@ import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionRepository;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.permission.UserWithPermissionDto;
@@ -301,8 +301,8 @@ public class ApplyTemplateActionTest {
     dbSession.commit();
   }
 
-  private static PermissionQuery query(String permission) {
-    return PermissionQuery.builder().membership(IN).permission(permission).build();
+  private static OldPermissionQuery query(String permission) {
+    return OldPermissionQuery.builder().membership(IN).permission(permission).build();
   }
 
   private static class PermissionNotNull implements Predicate<GroupWithPermissionDto> {
index 100e3843f93ed716e4123f4f0be2b1693b216880..753c03c51915e76c459c317bd8b2df693ed3cd87 100644 (file)
@@ -54,7 +54,7 @@ import org.sonar.db.component.ComponentDbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionRepository;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.permission.UserWithPermissionDto;
@@ -272,8 +272,8 @@ public class BulkApplyTemplateActionTest {
     dbSession.commit();
   }
 
-  private static PermissionQuery query(String permission) {
-    return PermissionQuery.builder().membership(IN).permission(permission).build();
+  private static OldPermissionQuery query(String permission) {
+    return OldPermissionQuery.builder().membership(IN).permission(permission).build();
   }
 
   private static class PermissionNotNull implements Predicate<GroupWithPermissionDto> {
index ad649dd0a388a272ca5131da3362aa4bc9845052..9df6be6c9547f301acb40d1517579698d1279c89 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.server.component.ComponentFinder;
@@ -245,7 +245,7 @@ public class RemoveGroupFromTemplateActionTest {
   }
 
   private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    OldPermissionQuery permissionQuery = OldPermissionQuery.builder().permission(permission).membership(IN).build();
     return from(dbClient.permissionTemplateDao()
       .selectGroups(dbSession, permissionQuery, templateId))
       .transform(GroupWithPermissionToGroupName.INSTANCE)
index 770d3b4f2d9b240fbc89e81cf0511d336cd26075..764d4ad7bea1b357052ee7822c879b0890d96ac4 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ResourceTypesRule;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.OldPermissionQuery;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.permission.UserWithPermissionDto;
 import org.sonar.db.user.UserDto;
@@ -231,7 +231,7 @@ public class RemoveUserFromTemplateActionTest {
   }
 
   private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    OldPermissionQuery permissionQuery = OldPermissionQuery.builder().permission(permission).membership(IN).build();
     return from(dbClient.permissionTemplateDao()
       .selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE))
         .transform(UserWithPermissionToUserLogin.INSTANCE)
diff --git a/sonar-db/src/main/java/org/sonar/db/permission/OldPermissionQuery.java b/sonar-db/src/main/java/org/sonar/db/permission/OldPermissionQuery.java
new file mode 100644 (file)
index 0000000..42f9c5b
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.permission;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Query used to get users and groups from a permission
+ */
+public class OldPermissionQuery {
+
+  public static final int DEFAULT_PAGE_INDEX = 1;
+  public static final int DEFAULT_PAGE_SIZE = 100;
+
+  public static final String ANY = "ANY";
+  public static final String IN = "IN";
+  public static final String OUT = "OUT";
+  public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT);
+
+  private final String permission;
+  private final String component;
+  private final String template;
+  private final String membership;
+  private final String search;
+
+  // for internal use in MyBatis
+  final String searchSql;
+
+  // max results per page
+  private final int pageSize;
+  // index of selected page. Start with 1.
+  private final int pageIndex;
+  // offset. Starts with 0.
+  private final int pageOffset;
+
+  private OldPermissionQuery(Builder builder) {
+    this.permission = builder.permission;
+    this.component = builder.component;
+    this.template = builder.template;
+    this.membership = builder.membership;
+    this.search = builder.search;
+    this.searchSql = searchToSql(search);
+
+    this.pageSize = builder.pageSize;
+    this.pageIndex = builder.pageIndex;
+    this.pageOffset = (builder.pageIndex - 1) * builder.pageSize;
+  }
+
+  private static String searchToSql(@Nullable String s) {
+    String sql = null;
+    if (s != null) {
+      sql = StringUtils.replace(StringUtils.upperCase(s), "%", "/%");
+      sql = StringUtils.replace(sql, "_", "/_");
+      sql = "%" + sql + "%";
+    }
+    return sql;
+  }
+
+  public String permission() {
+    return permission;
+  }
+
+  /**
+   * Used only for permission template
+   */
+  public String template() {
+    return template;
+  }
+
+  /**
+   * Used on project permission
+   */
+  @CheckForNull
+  public String component() {
+    return component;
+  }
+
+  @CheckForNull
+  public String membership() {
+    return membership;
+  }
+
+  @CheckForNull
+  public String search() {
+    return search;
+  }
+
+  public int pageSize() {
+    return pageSize;
+  }
+
+  public int pageOffset() {
+    return pageOffset;
+  }
+
+  public int pageIndex() {
+    return pageIndex;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private String permission;
+    private String component;
+    private String template;
+    private String membership;
+    private String search;
+
+    private Integer pageIndex = DEFAULT_PAGE_INDEX;
+    private Integer pageSize = DEFAULT_PAGE_SIZE;
+
+    private Builder() {
+    }
+
+    public Builder permission(String permission) {
+      this.permission = permission;
+      return this;
+    }
+
+    public Builder template(String template) {
+      this.template = template;
+      return this;
+    }
+
+    public Builder component(@Nullable String component) {
+      this.component = component;
+      return this;
+    }
+
+    public Builder membership(@Nullable String membership) {
+      this.membership = membership;
+      return this;
+    }
+
+    public Builder search(@Nullable String s) {
+      this.search = StringUtils.defaultIfBlank(s, null);
+      return this;
+    }
+
+    public Builder pageSize(@Nullable Integer i) {
+      this.pageSize = i;
+      return this;
+    }
+
+    public Builder pageIndex(@Nullable Integer i) {
+      this.pageIndex = i;
+      return this;
+    }
+
+    private void initMembership() {
+      if (membership == null) {
+        membership = OldPermissionQuery.ANY;
+      } else {
+        Preconditions.checkArgument(AVAILABLE_MEMBERSHIP.contains(membership),
+          "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIP);
+      }
+    }
+
+    private void initPageSize() {
+      if (pageSize == null) {
+        pageSize = DEFAULT_PAGE_SIZE;
+      }
+    }
+
+    private void initPageIndex() {
+      if (pageIndex == null) {
+        pageIndex = DEFAULT_PAGE_INDEX;
+      }
+      Preconditions.checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")");
+    }
+
+    public OldPermissionQuery build() {
+      checkNotNull(permission, "Permission cannot be null.");
+      initMembership();
+      initPageIndex();
+      initPageSize();
+      return new OldPermissionQuery(this);
+    }
+  }
+}
index a365cd96b4f1b54b5c56d2c10684aca8cb04ad83..dbf7d0f38311b53a6643a60e2219c4608879ef1a 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.api.security.DefaultGroups;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 import org.sonar.db.MyBatis;
+import org.sonar.db.user.UserPermissionDto;
 
 import static com.google.common.collect.Maps.newHashMap;
 import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput;
@@ -48,20 +49,37 @@ public class PermissionDao implements Dao {
 
   /**
    * @return a paginated list of users.
+   * @deprecated use {@link #selectUserPermissionsByQuery(DbSession, PermissionQuery)} instead
    */
-  public List<UserWithPermissionDto> selectUsers(DbSession session, PermissionQuery query, @Nullable Long componentId, int offset, int limit) {
+  @Deprecated
+  public List<UserWithPermissionDto> selectUsers(DbSession session, OldPermissionQuery query, @Nullable Long componentId, int offset, int limit) {
     Map<String, Object> params = usersParameters(query, componentId);
 
     return mapper(session).selectUsers(params, new RowBounds(offset, limit));
   }
 
-  public int countUsers(DbSession session, PermissionQuery query, @Nullable Long componentId) {
+  /**
+   * Each row returns <code>{@link UserRef}</code>, ordered by user names
+   */
+  public void selectUsersByQuery(DbSession dbSession, PermissionQuery query, ResultHandler handler) {
+    mapper(dbSession).selectUsersByQuery(query, new RowBounds(query.getPageOffset(), query.getPageSize()), handler);
+  }
+
+  public int countUsersByQuery(DbSession dbSession, PermissionQuery query) {
+    return mapper(dbSession).countUsersByQuery(query);
+  }
+
+  public List<UserPermissionDto> selectUserPermissionsByQuery(DbSession dbSession, PermissionQuery query) {
+    return mapper(dbSession).selectUserPermissionsByQuery(query);
+  }
+
+  public int countUsers(DbSession session, OldPermissionQuery query, @Nullable Long componentId) {
     Map<String, Object> params = usersParameters(query, componentId);
 
     return mapper(session).countUsers(params);
   }
 
-  private static Map<String, Object> usersParameters(PermissionQuery query, @Nullable Long componentId) {
+  private static Map<String, Object> usersParameters(OldPermissionQuery query, @Nullable Long componentId) {
     Map<String, Object> params = newHashMap();
     params.put(QUERY_PARAMETER, query);
     params.put(COMPONENT_ID_PARAMETER, componentId);
@@ -74,12 +92,12 @@ public class PermissionDao implements Dao {
    *
    * @return a non paginated list of groups.
    */
-  public List<GroupWithPermissionDto> selectGroups(DbSession session, PermissionQuery query, @Nullable Long componentId) {
+  public List<GroupWithPermissionDto> selectGroups(DbSession session, OldPermissionQuery query, @Nullable Long componentId) {
     Map<String, Object> params = groupsParameters(query, componentId);
     return mapper(session).selectGroups(params);
   }
 
-  public List<GroupWithPermissionDto> selectGroups(PermissionQuery query, @Nullable Long componentId) {
+  public List<GroupWithPermissionDto> selectGroups(OldPermissionQuery query, @Nullable Long componentId) {
     DbSession session = myBatis.openSession(false);
     try {
       return selectGroups(session, query, componentId);
@@ -128,7 +146,7 @@ public class PermissionDao implements Dao {
       });
   }
 
-  private static Map<String, Object> groupsParameters(PermissionQuery query, @Nullable Long componentId) {
+  private static Map<String, Object> groupsParameters(OldPermissionQuery query, @Nullable Long componentId) {
     Map<String, Object> params = newHashMap();
     params.put(QUERY_PARAMETER, query);
     params.put(COMPONENT_ID_PARAMETER, componentId);
index 949f2b1856a9cc5a423f8b8123e07186b1de2246..f2b94da1b3f6cab67a201c4e88ba102ce82c09f0 100644 (file)
@@ -21,8 +21,10 @@ package org.sonar.db.permission;
 
 import java.util.List;
 import java.util.Map;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.session.ResultHandler;
 import org.apache.ibatis.session.RowBounds;
+import org.sonar.db.user.UserPermissionDto;
 
 public interface PermissionMapper {
 
@@ -30,6 +32,12 @@ public interface PermissionMapper {
 
   int countUsers(Map<String, Object> parameters);
 
+  void selectUsersByQuery(@Param("query") PermissionQuery query, RowBounds rowBounds, ResultHandler handler);
+
+  int countUsersByQuery(@Param("query") PermissionQuery query);
+
+  List<UserPermissionDto> selectUserPermissionsByQuery(PermissionQuery query);
+
   List<GroupWithPermissionDto> selectGroups(Map<String, Object> parameters);
 
   int countGroups(Map<String, Object> parameters);
index f5e705a874e6a5db0425fbc7d3b12d3d69075d1e..d58357d13bca9736deec0d8c55ca0849f70b8f88 100644 (file)
  */
 package org.sonar.db.permission;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import java.util.Set;
+import java.util.Locale;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
+import org.sonar.db.WildcardPosition;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.MoreObjects.firstNonNull;
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.apache.commons.lang.StringUtils.defaultIfBlank;
+import static org.sonar.api.utils.Paging.offset;
+import static org.sonar.db.DatabaseUtils.buildLikeValue;
 
 /**
- * Query used to get users and groups from a permission
+ * Query used to get users and groups permissions
  */
 public class PermissionQuery {
 
+  public static final int RESULTS_MAX_SIZE = 100;
+  public static final int SEARCH_QUERY_MIN_LENGTH = 3;
+  public static final int DEFAULT_PAGE_SIZE = 20;
   public static final int DEFAULT_PAGE_INDEX = 1;
-  public static final int DEFAULT_PAGE_SIZE = 100;
-
-  public static final String ANY = "ANY";
-  public static final String IN = "IN";
-  public static final String OUT = "OUT";
-  public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT);
 
   private final String permission;
-  private final String component;
+  private final String componentUuid;
   private final String template;
-  private final String membership;
-  private final String search;
-
-  // for internal use in MyBatis
-  final String searchSql;
+  private final String searchQuery;
+  private final String searchQueryToSql;
+  private final boolean withPermissionOnly;
 
-  // max results per page
   private final int pageSize;
-  // index of selected page. Start with 1.
-  private final int pageIndex;
-  // offset. Starts with 0.
   private final int pageOffset;
 
   private PermissionQuery(Builder builder) {
     this.permission = builder.permission;
-    this.component = builder.component;
+    this.withPermissionOnly = builder.withPermissionOnly;
+    this.componentUuid = builder.componentUuid;
     this.template = builder.template;
-    this.membership = builder.membership;
-    this.search = builder.search;
-    this.searchSql = searchToSql(search);
-
+    this.searchQuery = builder.searchQuery;
+    this.searchQueryToSql = builder.searchQuery == null ? null : buildLikeValue(builder.searchQuery, WildcardPosition.BEFORE_AND_AFTER).toLowerCase(Locale.ENGLISH);
     this.pageSize = builder.pageSize;
-    this.pageIndex = builder.pageIndex;
-    this.pageOffset = (builder.pageIndex - 1) * builder.pageSize;
+    this.pageOffset = offset(builder.pageIndex, builder.pageSize);
   }
 
-  private static String searchToSql(@Nullable String s) {
-    String sql = null;
-    if (s != null) {
-      sql = StringUtils.replace(StringUtils.upperCase(s), "%", "/%");
-      sql = StringUtils.replace(sql, "_", "/_");
-      sql = "%" + sql + "%";
-    }
-    return sql;
+  @CheckForNull
+  public String getPermission() {
+    return permission;
   }
 
-  public String permission() {
-    return permission;
+  public boolean withPermissionOnly() {
+    return withPermissionOnly;
   }
 
-  /**
-   * Used only for permission template
-   */
   public String template() {
     return template;
   }
 
-  /**
-   * Used on project permission
-   */
   @CheckForNull
-  public String component() {
-    return component;
+  public String getComponentUuid() {
+    return componentUuid;
   }
 
   @CheckForNull
-  public String membership() {
-    return membership;
+  public String getSearchQuery() {
+    return searchQuery;
   }
 
   @CheckForNull
-  public String search() {
-    return search;
+  public String getSearchQueryToSql() {
+    return searchQueryToSql;
   }
 
-  public int pageSize() {
+  public int getPageSize() {
     return pageSize;
   }
 
-  public int pageOffset() {
+  public int getPageOffset() {
     return pageOffset;
   }
 
-  public int pageIndex() {
-    return pageIndex;
-  }
-
   public static Builder builder() {
     return new Builder();
   }
 
   public static class Builder {
     private String permission;
-    private String component;
+    private String componentUuid;
     private String template;
-    private String membership;
-    private String search;
+    private String searchQuery;
+    private boolean withPermissionOnly;
 
     private Integer pageIndex = DEFAULT_PAGE_INDEX;
     private Integer pageSize = DEFAULT_PAGE_SIZE;
 
     private Builder() {
+      // enforce method constructor
     }
 
-    public Builder permission(String permission) {
+    public Builder setPermission(@Nullable String permission) {
       this.permission = permission;
       return this;
     }
 
-    public Builder template(String template) {
+    public Builder setTemplate(@Nullable String template) {
       this.template = template;
       return this;
     }
 
-    public Builder component(@Nullable String component) {
-      this.component = component;
+    public Builder setComponentUuid(@Nullable String componentUuid) {
+      this.componentUuid = componentUuid;
       return this;
     }
 
-    public Builder membership(@Nullable String membership) {
-      this.membership = membership;
+    public Builder setSearchQuery(@Nullable String s) {
+      this.searchQuery = defaultIfBlank(s, null);
       return this;
     }
 
-    public Builder search(@Nullable String s) {
-      this.search = StringUtils.defaultIfBlank(s, null);
+    public Builder setPageIndex(@Nullable Integer i) {
+      this.pageIndex = i;
       return this;
     }
 
-    public Builder pageSize(@Nullable Integer i) {
+    public Builder setPageSize(@Nullable Integer i) {
       this.pageSize = i;
       return this;
     }
 
-    public Builder pageIndex(@Nullable Integer i) {
-      this.pageIndex = i;
+    public Builder withPermissionOnly() {
+      this.withPermissionOnly = true;
       return this;
     }
 
-    private void initMembership() {
-      if (membership == null) {
-        membership = PermissionQuery.ANY;
-      } else {
-        Preconditions.checkArgument(AVAILABLE_MEMBERSHIP.contains(membership),
-          "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIP);
-      }
-    }
-
-    private void initPageSize() {
-      if (pageSize == null) {
-        pageSize = DEFAULT_PAGE_SIZE;
-      }
-    }
-
-    private void initPageIndex() {
-      if (pageIndex == null) {
-        pageIndex = DEFAULT_PAGE_INDEX;
-      }
-      Preconditions.checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")");
-    }
-
     public PermissionQuery build() {
-      checkNotNull(permission, "Permission cannot be null.");
-      initMembership();
-      initPageIndex();
-      initPageSize();
+      this.pageIndex = firstNonNull(pageIndex, DEFAULT_PAGE_INDEX);
+      this.pageSize = firstNonNull(pageSize, DEFAULT_PAGE_SIZE);
+      checkArgument(searchQuery == null || searchQuery.length() >= 3);
+      checkArgument(!(withPermissionOnly && permission == null));
       return new PermissionQuery(this);
     }
   }
index f128410c8ae4353a68880bf8ac628e3d8c1d9f12..71c2d3d79f67bbecbb1f8173de5ae4caaaf478cd 100644 (file)
@@ -60,7 +60,7 @@ public class PermissionTemplateDao implements Dao {
   /**
    * @return a paginated list of users.
    */
-  public List<UserWithPermissionDto> selectUsers(PermissionQuery query, Long templateId, int offset, int limit) {
+  public List<UserWithPermissionDto> selectUsers(OldPermissionQuery query, Long templateId, int offset, int limit) {
     DbSession session = myBatis.openSession(false);
     try {
       return selectUsers(session, query, templateId, offset, limit);
@@ -72,14 +72,14 @@ public class PermissionTemplateDao implements Dao {
   /**
    * @return a paginated list of users.
    */
-  public List<UserWithPermissionDto> selectUsers(DbSession session, PermissionQuery query, Long templateId, int offset, int limit) {
+  public List<UserWithPermissionDto> selectUsers(DbSession session, OldPermissionQuery query, Long templateId, int offset, int limit) {
     Map<String, Object> params = newHashMap();
     params.put(QUERY_PARAMETER, query);
     params.put(TEMPLATE_ID_PARAMETER, templateId);
     return mapper(session).selectUsers(params, new RowBounds(offset, limit));
   }
 
-  public int countUsers(DbSession session, PermissionQuery query, Long templateId) {
+  public int countUsers(DbSession session, OldPermissionQuery query, Long templateId) {
     Map<String, Object> params = newHashMap();
     params.put(QUERY_PARAMETER, query);
     params.put(TEMPLATE_ID_PARAMETER, templateId);
@@ -87,7 +87,7 @@ public class PermissionTemplateDao implements Dao {
   }
 
   @VisibleForTesting
-  List<UserWithPermissionDto> selectUsers(PermissionQuery query, Long templateId) {
+  List<UserWithPermissionDto> selectUsers(OldPermissionQuery query, Long templateId) {
     return selectUsers(query, templateId, 0, Integer.MAX_VALUE);
   }
 
@@ -96,16 +96,16 @@ public class PermissionTemplateDao implements Dao {
    * Membership parameter from query is not taking into account in order to deal more easily with the 'Anyone' group.
    * @return a non paginated list of groups.
    */
-  public List<GroupWithPermissionDto> selectGroups(DbSession session, PermissionQuery query, Long templateId) {
+  public List<GroupWithPermissionDto> selectGroups(DbSession session, OldPermissionQuery query, Long templateId) {
     return selectGroups(session, query, templateId, 0, Integer.MAX_VALUE);
   }
 
-  public List<GroupWithPermissionDto> selectGroups(DbSession session, PermissionQuery query, Long templateId, int offset, int limit) {
+  public List<GroupWithPermissionDto> selectGroups(DbSession session, OldPermissionQuery query, Long templateId, int offset, int limit) {
     Map<String, Object> params = groupsParameters(query, templateId);
     return mapper(session).selectGroups(params, new RowBounds(offset, limit));
   }
 
-  public List<GroupWithPermissionDto> selectGroups(PermissionQuery query, Long templateId) {
+  public List<GroupWithPermissionDto> selectGroups(OldPermissionQuery query, Long templateId) {
     DbSession session = myBatis.openSession(false);
     try {
       return selectGroups(session, query, templateId);
@@ -114,11 +114,11 @@ public class PermissionTemplateDao implements Dao {
     }
   }
 
-  public int countGroups(DbSession session, PermissionQuery query, long templateId) {
+  public int countGroups(DbSession session, OldPermissionQuery query, long templateId) {
     return countGroups(session, query, templateId, null);
   }
 
-  private static int countGroups(DbSession session, PermissionQuery query, long templateId, @Nullable String groupName) {
+  private static int countGroups(DbSession session, OldPermissionQuery query, long templateId, @Nullable String groupName) {
     Map<String, Object> parameters = groupsParameters(query, templateId);
     if (groupName != null) {
       parameters.put("groupName", groupName.toUpperCase(Locale.ENGLISH));
@@ -126,11 +126,11 @@ public class PermissionTemplateDao implements Dao {
     return mapper(session).countGroups(parameters);
   }
 
-  public boolean hasGroup(DbSession session, PermissionQuery query, long templateId, String groupName) {
+  public boolean hasGroup(DbSession session, OldPermissionQuery query, long templateId, String groupName) {
     return countGroups(session, query, templateId, groupName) > 0;
   }
 
-  private static Map<String, Object> groupsParameters(PermissionQuery query, Long templateId) {
+  private static Map<String, Object> groupsParameters(OldPermissionQuery query, Long templateId) {
     Map<String, Object> params = newHashMap();
     params.put(QUERY_PARAMETER, query);
     params.put(TEMPLATE_ID_PARAMETER, templateId);
diff --git a/sonar-db/src/main/java/org/sonar/db/permission/UserRef.java b/sonar-db/src/main/java/org/sonar/db/permission/UserRef.java
new file mode 100644 (file)
index 0000000..4ffd4ff
--- /dev/null
@@ -0,0 +1,34 @@
+package org.sonar.db.permission;
+
+public class UserRef {
+  private String login;
+  private String email;
+  private String name;
+
+  public String getLogin() {
+    return login;
+  }
+
+  public UserRef setLogin(String login) {
+    this.login = login;
+    return this;
+  }
+
+  public String getEmail() {
+    return email;
+  }
+
+  public UserRef setEmail(String email) {
+    this.email = email;
+    return this;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public UserRef setName(String name) {
+    this.name = name;
+    return this;
+  }
+}
index 80630f5835fa151157c021188d1b2fb2532a859d..f93c971998fa429fe119d0219e57c8236ad37122 100644 (file)
     </where>
   </sql>
 
+  <select id="selectUsersByQuery" parameterType="map" resultType="org.sonar.db.permission.UserRef">
+    select distinct <include refid="userColumns" />
+    <include refid="usersByQuery"/>
+    order by lower(u.name), u.name, u.id
+  </select>
+
+  <sql id="userColumns">
+    <!-- lower(u.name) and u.id are present to order by with select distinct -->
+    u.login as login, u.name as name, u.email as email, lower(u.name), u.id
+  </sql>
+
+  <select id="countUsersByQuery" parameterType="map" resultType="int">
+    select count(1)
+    from (
+      select distinct <include refid="userColumns" />
+      <include refid="usersByQuery"/>)
+  </select>
+
+  <sql id="usersByQuery">
+    from users u
+      left join user_roles ur ON ur.user_id=u.id
+        left join projects p on ur.resource_id = p.id
+    <where>
+      and u.active = ${_true}
+      <if test="query.searchQueryToSql != null">
+        and lower(u.name) like #{query.searchQueryToSql} ESCAPE '/'
+      </if>
+      <!-- filter rows with user permissions -->
+      <if test="query.withPermissionOnly()">
+        and ur.role is not null
+        <if test="query.componentUuid==null">
+          and ur.resource_id is null
+        </if>
+        <if test="query.componentUuid!=null">
+          and ur.resource_id is not null
+        </if>
+        <if test="query.permission!=null">
+          and ur.role=#{query.permission}
+        </if>
+      </if>
+    </where>
+  </sql>
+
+  <select id="selectUserPermissionsByQuery" parameterType="map" resultType="UserRole">
+    select ur.user_id as userId, ur.resource_id as componentId, ur.role as permission
+    from user_roles ur
+      inner join users u on ur.user_id = u.id
+      left outer join projects p on ur.resource_id=p.id
+    <where>
+      <if test="query.logins != null">
+      and u.login in
+        <foreach collection="query.logins" open="(" close=")" item="login" separator=",">
+          #{login}
+        </foreach>
+      </if>
+      <if test="query.searchQueryToSql != null">
+        and (lower(u.name) like #{query.searchQueryToSql} ESCAPE '/')
+      </if>
+    </where>
+
+  </select>
+
   <select id="usersCountByProjectIdAndPermission" parameterType="map"
           resultType="org.sonar.db.permission.CountByProjectAndPermissionDto">
     SELECT user_role.resource_id as componentId, user_role.role as permission, count(u.login) as count
index a77ea0debe8e0f5dc6a4a907fb72d79254a92c45..e171fbe2bf94b8f8f5a854407774099760b30ddf 100644 (file)
@@ -23,8 +23,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import javax.annotation.Nullable;
-import org.apache.ibatis.session.ResultContext;
-import org.apache.ibatis.session.ResultHandler;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
@@ -54,7 +52,7 @@ public class GroupWithPermissionDaoTest {
   public void select_groups_for_project_permission() {
     db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, COMPONENT_ID);
     assertThat(result).hasSize(4);
 
@@ -84,7 +82,7 @@ public class GroupWithPermissionDaoTest {
     db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
     // Anyone group has not the permission 'admin', so it's not returned
-    PermissionQuery query = PermissionQuery.builder().permission("admin").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("admin").build();
     List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, COMPONENT_ID);
     assertThat(result).hasSize(3);
 
@@ -105,7 +103,7 @@ public class GroupWithPermissionDaoTest {
   public void select_groups_for_global_permission() {
     db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("admin").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("admin").build();
     List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, null);
     assertThat(result).hasSize(3);
 
@@ -126,11 +124,11 @@ public class GroupWithPermissionDaoTest {
   public void search_by_groups_name() {
     db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("aDMini").build(), COMPONENT_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, OldPermissionQuery.builder().permission("user").search("aDMini").build(), COMPONENT_ID);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("sonar-administrators");
 
-    result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("sonar").build(), COMPONENT_ID);
+    result = underTest.selectGroups(session, OldPermissionQuery.builder().permission("user").search("sonar").build(), COMPONENT_ID);
     assertThat(result).hasSize(3);
   }
 
@@ -138,7 +136,7 @@ public class GroupWithPermissionDaoTest {
   public void search_groups_should_be_sorted_by_group_name() {
     db.prepareDbUnit(getClass(), "groups_with_permissions_should_be_sorted_by_group_name.xml");
 
-    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID);
     int count = underTest.countGroups(session, "user", COMPONENT_ID);
 
     assertThat(result).hasSize(4);
@@ -167,12 +165,7 @@ public class GroupWithPermissionDaoTest {
     commit();
 
     final List<CountByProjectAndPermissionDto> result = new ArrayList<>();
-    underTest.groupsCountByComponentIdAndPermission(session, Arrays.asList(123L, 456L, 789L), new ResultHandler() {
-      @Override
-      public void handleResult(ResultContext context) {
-        result.add((CountByProjectAndPermissionDto) context.getResultObject());
-      }
-    });
+    underTest.groupsCountByComponentIdAndPermission(session, Arrays.asList(123L, 456L, 789L), context -> result.add((CountByProjectAndPermissionDto) context.getResultObject()));
 
     assertThat(result).hasSize(3);
     assertThat(result).extracting("permission").containsOnly(ADMIN, USER);
index b6838b1df5598b567814d9fffe65a8db3e692b75..25fd9d79e6bfd357034da97cd4281b3c4014d4f0 100644 (file)
@@ -44,7 +44,7 @@ public class GroupWithPermissionTemplateDaoTest {
   public void select_groups() {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, TEMPLATE_ID);
     int count = underTest.countGroups(session, query, TEMPLATE_ID);
 
@@ -77,7 +77,7 @@ public class GroupWithPermissionTemplateDaoTest {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
     // Anyone group is returned even if it doesn't have the permission
-    PermissionQuery query = PermissionQuery.builder().permission(UserRole.USER).build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission(UserRole.USER).build();
     List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, TEMPLATE_ID);
     assertThat(result).hasSize(4);
 
@@ -98,11 +98,11 @@ public class GroupWithPermissionTemplateDaoTest {
   public void search_by_groups_name() {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("aDMini").build(), TEMPLATE_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, OldPermissionQuery.builder().permission("user").search("aDMini").build(), TEMPLATE_ID);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("sonar-administrators");
 
-    result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("sonar").build(), TEMPLATE_ID);
+    result = underTest.selectGroups(session, OldPermissionQuery.builder().permission("user").search("sonar").build(), TEMPLATE_ID);
     assertThat(result).hasSize(3);
   }
 
@@ -110,7 +110,7 @@ public class GroupWithPermissionTemplateDaoTest {
   public void search_groups_should_be_sorted_by_group_name() {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions_should_be_sorted_by_group_name.xml");
 
-    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").build(), TEMPLATE_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, OldPermissionQuery.builder().permission("user").build(), TEMPLATE_ID);
     assertThat(result).hasSize(4);
     assertThat(result.get(0).getName()).isEqualTo("Anyone");
     assertThat(result.get(1).getName()).isEqualTo("sonar-administrators");
diff --git a/sonar-db/src/test/java/org/sonar/db/permission/OldPermissionQueryTest.java b/sonar-db/src/test/java/org/sonar/db/permission/OldPermissionQueryTest.java
new file mode 100644 (file)
index 0000000..a86621e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.permission;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+public class OldPermissionQueryTest {
+
+  @Test
+  public void fail_on_null_permission() {
+    OldPermissionQuery.Builder builder = OldPermissionQuery.builder();
+    builder.permission(null);
+
+    try {
+      builder.build();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(NullPointerException.class).hasMessage("Permission cannot be null.");
+    }
+  }
+
+  @Test
+  public void fail_on_invalid_membership() {
+    OldPermissionQuery.Builder builder = OldPermissionQuery.builder();
+    builder.permission("admin");
+    builder.membership("unknwown");
+
+    try {
+      builder.build();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Membership is not valid (got unknwown). Availables values are [ANY, IN, OUT]");
+    }
+  }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/permission/PermissionDbTester.java b/sonar-db/src/test/java/org/sonar/db/permission/PermissionDbTester.java
new file mode 100644 (file)
index 0000000..c3f1ef2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.db.permission;
+
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.UserRoleDto;
+
+public class PermissionDbTester {
+  private final DbTester db;
+  private final DbClient dbClient;
+  private final DbSession dbSession;
+
+  public PermissionDbTester(DbTester db) {
+    this.db = db;
+    this.dbClient = db.getDbClient();
+    this.dbSession = db.getSession();
+  }
+
+  public void addProjectPermissionToUser(String permission, long userId, long componentId) {
+    dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto()
+      .setRole(permission)
+      .setUserId(userId)
+      .setResourceId(componentId));
+    db.commit();
+  }
+
+  public void addGlobalPermissionToUser(String permission, long userId) {
+    dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto()
+      .setRole(permission)
+      .setUserId(userId));
+    db.commit();
+  }
+}
index 5b37c0897c0c07473d741949ae51c96d948aa0c3..a85760ec55e1edf0a4263600d3516dbe29968eb3 100644 (file)
  */
 package org.sonar.db.permission;
 
-import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.IntStream;
 import javax.annotation.Nullable;
-import org.apache.ibatis.session.ResultContext;
-import org.apache.ibatis.session.ResultHandler;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.user.UserDbTester;
 import org.sonar.db.user.UserDto;
 import org.sonar.db.user.UserRoleDto;
 
@@ -39,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.web.UserRole.ADMIN;
 import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
 import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
 import static org.sonar.db.user.UserTesting.newUserDto;
 
 public class UserWithPermissionDaoTest {
@@ -47,6 +51,9 @@ public class UserWithPermissionDaoTest {
 
   @Rule
   public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  UserDbTester userDb = new UserDbTester(dbTester);
+  PermissionDbTester permissionDb = new PermissionDbTester(dbTester);
+  ComponentDbTester componentDb = new ComponentDbTester(dbTester);
   DbSession session = dbTester.getSession();
 
   PermissionDao underTest = new PermissionDao(dbTester.myBatis());
@@ -55,7 +62,7 @@ public class UserWithPermissionDaoTest {
   public void select_all_users_for_project_permission() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<UserWithPermissionDto> result = selectUsers(session, query, COMPONENT_ID);
     assertThat(result).hasSize(3);
 
@@ -79,7 +86,7 @@ public class UserWithPermissionDaoTest {
   public void select_all_users_for_global_permission() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("admin").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("admin").build();
     List<UserWithPermissionDto> result = selectUsers(session, query, null);
     assertThat(result).hasSize(3);
 
@@ -101,7 +108,7 @@ public class UserWithPermissionDaoTest {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
     // user1 and user2 have permission user
-    assertThat(selectUsers(session, PermissionQuery.builder().permission("user").membership(PermissionQuery.IN).build(), COMPONENT_ID)).hasSize(2);
+    assertThat(selectUsers(session, OldPermissionQuery.builder().permission("user").membership(OldPermissionQuery.IN).build(), COMPONENT_ID)).hasSize(2);
   }
 
   @Test
@@ -109,18 +116,18 @@ public class UserWithPermissionDaoTest {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
     // Only user3 has not the user permission
-    assertThat(selectUsers(session, PermissionQuery.builder().permission("user").membership(PermissionQuery.OUT).build(), COMPONENT_ID)).hasSize(1);
+    assertThat(selectUsers(session, OldPermissionQuery.builder().permission("user").membership(OldPermissionQuery.OUT).build(), COMPONENT_ID)).hasSize(1);
   }
 
   @Test
   public void search_by_user_name() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    List<UserWithPermissionDto> result = selectUsers(session, PermissionQuery.builder().permission("user").search("SEr1").build(), COMPONENT_ID);
+    List<UserWithPermissionDto> result = selectUsers(session, OldPermissionQuery.builder().permission("user").search("SEr1").build(), COMPONENT_ID);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("User1");
 
-    result = selectUsers(session, PermissionQuery.builder().permission("user").search("user").build(), COMPONENT_ID);
+    result = selectUsers(session, OldPermissionQuery.builder().permission("user").search("user").build(), COMPONENT_ID);
     assertThat(result).hasSize(3);
   }
 
@@ -128,24 +135,132 @@ public class UserWithPermissionDaoTest {
   public void select_only_enable_users() {
     dbTester.prepareDbUnit(getClass(), "select_only_enable_users.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<UserWithPermissionDto> result = selectUsers(session, query, COMPONENT_ID);
     assertThat(result).hasSize(3);
 
     // Disabled user should not be returned
-    assertThat(Iterables.find(result, new Predicate<UserWithPermissionDto>() {
-      @Override
-      public boolean apply(@Nullable UserWithPermissionDto input) {
-        return input.getLogin().equals("disabledUser");
-      }
-    }, null)).isNull();
+    assertThat(Iterables.find(result, input -> input.getLogin().equals("disabledUser"), null)).isNull();
+  }
+
+  @Test
+  public void select_users() {
+    UserDto user3 = userDb.insertUser(newUserDto().setName("3-name"));
+    UserDto user2 = userDb.insertUser(newUserDto().setName("2-name"));
+    UserDto user1 = userDb.insertUser(newUserDto().setName("1-name"));
+    UserDto user4 = userDb.insertUser(newUserDto().setName("4-name"));
+
+    ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid"));
+
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user3.getId());
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.PROVISIONING, user3.getId());
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user2.getId());
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user1.getId());
+    permissionDb.addProjectPermissionToUser(UserRole.USER, user4.getId(), project.getId());
+
+    PermissionQuery.Builder dbQuery = PermissionQuery.builder();
+    List<UserRef> result = selectUsersByQuery(dbQuery);
+    int count = countUsersByQuery(dbQuery);
+
+    assertThat(result)
+      .hasSize(4)
+      .extracting(UserRef::getName)
+      .containsExactly("1-name", "2-name", "3-name", "4-name");
+    assertThat(result.get(0)).extracting(UserRef::getEmail, UserRef::getLogin)
+      .containsExactly(user1.getEmail(), user1.getLogin());
+    assertThat(count).isEqualTo(4);
+  }
+
+  @Test
+  public void select_users_paginated() {
+    IntStream.rangeClosed(0, 9)
+      .forEach(i -> userDb.insertUser(newUserDto().setName(i + "-name")));
+
+    PermissionQuery.Builder dbQuery = PermissionQuery.builder().setPageIndex(2).setPageSize(3);
+    List<UserRef> result = selectUsersByQuery(dbQuery);
+    int count = countUsersByQuery(dbQuery);
+
+    assertThat(result).hasSize(3).extracting(UserRef::getName)
+      .containsExactly("3-name", "4-name", "5-name");
+    assertThat(count).isEqualTo(10);
+  }
+
+  @Test
+  public void select_users_with_query() {
+    userDb.insertUser(newUserDto().setName("1-name"));
+    userDb.insertUser(newUserDto().setName("unknown"));
+
+    PermissionQuery.Builder dbQuery = PermissionQuery.builder().setSearchQuery("nam");
+    List<UserRef> result = selectUsersByQuery(dbQuery);
+    int count = countUsersByQuery(dbQuery);
+
+    assertThat(result).hasSize(1);
+    assertThat(result.get(0).getName()).isEqualTo("1-name");
+    assertThat(count).isEqualTo(1);
+  }
+
+  @Test
+  public void select_users_with_global_permissions() {
+    UserDto user3 = userDb.insertUser(newUserDto().setName("3-name"));
+    UserDto user2 = userDb.insertUser(newUserDto().setName("2-name"));
+    UserDto user1 = userDb.insertUser(newUserDto().setName("1-name"));
+    UserDto user4 = userDb.insertUser(newUserDto().setName("4-name"));
+
+    ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid"));
+
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user3.getId());
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.PROVISIONING, user3.getId());
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user2.getId());
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user1.getId());
+    // project permission
+    permissionDb.addProjectPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user4.getId(), project.getId());
+
+    PermissionQuery.Builder dbQuery = PermissionQuery.builder()
+      .setComponentUuid(null)
+      .setPermission(GlobalPermissions.SCAN_EXECUTION)
+      .withPermissionOnly();
+    List<UserRef> result = selectUsersByQuery(dbQuery);
+    int count = countUsersByQuery(dbQuery);
+
+    assertThat(result).hasSize(2).extracting(UserRef::getName)
+      .containsExactly("2-name", "3-name");
+    assertThat(count).isEqualTo(2);
+  }
+
+  @Test
+  public void select_users_with_project_permissions() {
+    UserDto user3 = userDb.insertUser(newUserDto().setName("3-name"));
+    UserDto user2 = userDb.insertUser(newUserDto().setName("2-name"));
+    UserDto user1 = userDb.insertUser(newUserDto().setName("1-name"));
+    UserDto user4 = userDb.insertUser(newUserDto().setName("4-name"));
+
+    ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid"));
+
+    permissionDb.addProjectPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user3.getId(), project.getId());
+    permissionDb.addProjectPermissionToUser(GlobalPermissions.PROVISIONING, user3.getId(), project.getId());
+    permissionDb.addProjectPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user2.getId(), project.getId());
+    permissionDb.addProjectPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user1.getId(), project.getId());
+    // global permission
+    permissionDb.addGlobalPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user4.getId());
+
+    PermissionQuery.Builder dbQuery = PermissionQuery.builder()
+      .setComponentUuid(null)
+      .setPermission(GlobalPermissions.SCAN_EXECUTION)
+      .withPermissionOnly()
+      .setComponentUuid(project.uuid());
+    List<UserRef> result = selectUsersByQuery(dbQuery);
+    int count = countUsersByQuery(dbQuery);
+
+    assertThat(result).hasSize(2).extracting(UserRef::getName)
+      .containsExactly("2-name", "3-name");
+    assertThat(count).isEqualTo(2);
   }
 
   @Test
   public void should_be_sorted_by_user_name() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions_should_be_sorted_by_user_name.xml");
 
-    List<UserWithPermissionDto> result = selectUsers(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID);
+    List<UserWithPermissionDto> result = selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID);
     assertThat(result).hasSize(3);
     assertThat(result.get(0).getName()).isEqualTo("User1");
     assertThat(result.get(1).getName()).isEqualTo("User2");
@@ -156,64 +271,63 @@ public class UserWithPermissionDaoTest {
   public void should_be_paginated() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    List<UserWithPermissionDto> result = underTest.selectUsers(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID, 0, 2);
+    List<UserWithPermissionDto> result = underTest.selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID, 0, 2);
     assertThat(result).hasSize(2);
     assertThat(result.get(0).getName()).isEqualTo("User1");
     assertThat(result.get(1).getName()).isEqualTo("User2");
 
-    result = underTest.selectUsers(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID, 1, 2);
+    result = underTest.selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID, 1, 2);
     assertThat(result).hasSize(2);
     assertThat(result.get(0).getName()).isEqualTo("User2");
     assertThat(result.get(1).getName()).isEqualTo("User3");
 
-    result = underTest.selectUsers(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID, 2, 1);
+    result = underTest.selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID, 2, 1);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("User3");
   }
 
   @Test
   public void user_count_by_component_and_permission() {
-    UserDto user1 = insertUser(newUserDto());
-    UserDto user2 = insertUser(newUserDto());
-    UserDto user3 = insertUser(newUserDto());
-
-    insertUserRole(ISSUE_ADMIN, user1.getId(), 42L);
-    insertUserRole(ADMIN, user1.getId(), 123L);
-    insertUserRole(ADMIN, user2.getId(), 123L);
-    insertUserRole(ADMIN, user3.getId(), 123L);
-    insertUserRole(USER, user1.getId(), 123L);
-    insertUserRole(USER, user1.getId(), 456L);
-    commit();
+    UserDto user1 = userDb.insertUser();
+    UserDto user2 = userDb.insertUser();
+    UserDto user3 = userDb.insertUser();
+
+    addPermissionToUser(ISSUE_ADMIN, user1.getId(), 42L);
+    addPermissionToUser(ADMIN, user1.getId(), 123L);
+    addPermissionToUser(ADMIN, user2.getId(), 123L);
+    addPermissionToUser(ADMIN, user3.getId(), 123L);
+    addPermissionToUser(USER, user1.getId(), 123L);
+    addPermissionToUser(USER, user1.getId(), 456L);
 
     final List<CountByProjectAndPermissionDto> result = new ArrayList<>();
-    underTest.usersCountByComponentIdAndPermission(dbTester.getSession(), Arrays.asList(123L, 456L, 789L), new ResultHandler() {
-      @Override
-      public void handleResult(ResultContext context) {
-        result.add((CountByProjectAndPermissionDto) context.getResultObject());
-      }
-    });
+    underTest.usersCountByComponentIdAndPermission(dbTester.getSession(), Arrays.asList(123L, 456L, 789L),
+      context -> result.add((CountByProjectAndPermissionDto) context.getResultObject()));
     assertThat(result).hasSize(3);
     assertThat(result).extracting("permission").containsOnly(ADMIN, USER);
     assertThat(result).extracting("componentId").containsOnly(123L, 456L);
     assertThat(result).extracting("count").containsOnly(3, 1);
   }
 
-  private List<UserWithPermissionDto> selectUsers(DbSession session, PermissionQuery query, @Nullable Long componentId) {
+  private List<UserWithPermissionDto> selectUsers(DbSession session, OldPermissionQuery query, @Nullable Long componentId) {
     return underTest.selectUsers(session, query, componentId, 0, Integer.MAX_VALUE);
   }
 
-  private UserDto insertUser(UserDto userDto) {
-    return dbTester.getDbClient().userDao().insert(dbTester.getSession(), userDto.setActive(true));
+  private List<UserRef> selectUsersByQuery(PermissionQuery.Builder query) {
+    List<UserRef> result = new ArrayList<>();
+    underTest.selectUsersByQuery(session, query.build(), context -> result.add((UserRef) context.getResultObject()));
+    return result;
   }
 
-  private void insertUserRole(String permission, long userId, long resourceId) {
+  private int countUsersByQuery(PermissionQuery.Builder query) {
+    return underTest.countUsersByQuery(session, query.build());
+  }
+
+  private void addPermissionToUser(String permission, long userId, long resourceId) {
     dbTester.getDbClient().roleDao().insertUserRole(dbTester.getSession(), new UserRoleDto()
       .setRole(permission)
       .setUserId(userId)
       .setResourceId(resourceId));
+    dbTester.commit();
   }
 
-  private void commit() {
-    dbTester.getSession().commit();
-  }
 }
index 7665ce965eabfe67d51d177e712fdc32cdb16093..1deb0bb874b838a91fd934bca0afb838e88391aa 100644 (file)
@@ -44,7 +44,7 @@ public class UserWithPermissionTemplateDaoTest {
   public void select_all_users() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<UserWithPermissionDto> result = dao.selectUsers(query, TEMPLATE_ID);
     assertThat(result).hasSize(3);
 
@@ -68,7 +68,7 @@ public class UserWithPermissionTemplateDaoTest {
   public void return_nothing_on_unknown_template_key() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<UserWithPermissionDto> result = dao.selectUsers(query, 999L);
     assertThat(result).hasSize(3);
 
@@ -87,7 +87,7 @@ public class UserWithPermissionTemplateDaoTest {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
     // user1 and user2 have permission user
-    assertThat(dao.selectUsers(PermissionQuery.builder().permission("user").membership(PermissionQuery.IN).build(), TEMPLATE_ID)).hasSize(2);
+    assertThat(dao.selectUsers(OldPermissionQuery.builder().permission("user").membership(OldPermissionQuery.IN).build(), TEMPLATE_ID)).hasSize(2);
   }
 
   @Test
@@ -95,14 +95,14 @@ public class UserWithPermissionTemplateDaoTest {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
     // Only user3 has not the user permission
-    assertThat(dao.selectUsers(PermissionQuery.builder().permission("user").membership(PermissionQuery.OUT).build(), TEMPLATE_ID)).hasSize(1);
+    assertThat(dao.selectUsers(OldPermissionQuery.builder().permission("user").membership(OldPermissionQuery.OUT).build(), TEMPLATE_ID)).hasSize(1);
   }
 
   @Test
   public void select_only_enable_users() {
     dbTester.prepareDbUnit(getClass(), "select_only_enable_users.xml");
 
-    PermissionQuery query = PermissionQuery.builder().permission("user").build();
+    OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
     List<UserWithPermissionDto> result = dao.selectUsers(query, 999L);
     assertThat(result).hasSize(3);
 
@@ -119,11 +119,11 @@ public class UserWithPermissionTemplateDaoTest {
   public void search_by_user_name() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").search("SEr1").build(), TEMPLATE_ID);
+    List<UserWithPermissionDto> result = dao.selectUsers(OldPermissionQuery.builder().permission("user").search("SEr1").build(), TEMPLATE_ID);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("User1");
 
-    result = dao.selectUsers(PermissionQuery.builder().permission("user").search("user").build(), TEMPLATE_ID);
+    result = dao.selectUsers(OldPermissionQuery.builder().permission("user").search("user").build(), TEMPLATE_ID);
     assertThat(result).hasSize(3);
   }
 
@@ -131,7 +131,7 @@ public class UserWithPermissionTemplateDaoTest {
   public void should_be_sorted_by_user_name() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions_should_be_sorted_by_user_name.xml");
 
-    List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID);
+    List<UserWithPermissionDto> result = dao.selectUsers(OldPermissionQuery.builder().permission("user").build(), TEMPLATE_ID);
     assertThat(result).hasSize(3);
     assertThat(result.get(0).getName()).isEqualTo("User1");
     assertThat(result.get(1).getName()).isEqualTo("User2");
@@ -142,17 +142,17 @@ public class UserWithPermissionTemplateDaoTest {
   public void should_be_paginated() {
     dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
 
-    List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 0, 2);
+    List<UserWithPermissionDto> result = dao.selectUsers(OldPermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 0, 2);
     assertThat(result).hasSize(2);
     assertThat(result.get(0).getName()).isEqualTo("User1");
     assertThat(result.get(1).getName()).isEqualTo("User2");
 
-    result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 1, 2);
+    result = dao.selectUsers(OldPermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 1, 2);
     assertThat(result).hasSize(2);
     assertThat(result.get(0).getName()).isEqualTo("User2");
     assertThat(result.get(1).getName()).isEqualTo("User3");
 
-    result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 2, 1);
+    result = dao.selectUsers(OldPermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 2, 1);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("User3");
   }