]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6892 WS permissions/search_project_permissions filter by qualifier 657/head
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 27 Nov 2015 17:09:46 +0000 (18:09 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 30 Nov 2015 13:04:40 +0000 (14:04 +0100)
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.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/SearchProjectPermissionsAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchProjectPermissionsActionTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsWsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/permission/SearchProjectPermissionsWsRequest.java

index daf061e8e54ab0c16f59a1cfad12c00614f8a768..4b2247a19bbc997e4c471154d84e6c6c7a522b80 100644 (file)
 package org.sonar.server.permission.ws;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
 import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import javax.annotation.Nullable;
+import org.sonar.api.resources.ResourceTypes;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.permission.ProjectPermissions;
 import org.sonar.server.exceptions.BadRequestException;
@@ -33,10 +35,11 @@ import static com.google.common.base.Strings.isNullOrEmpty;
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.isBlank;
 import static org.sonar.api.security.DefaultGroups.isAnyone;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN;
+import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
+import static org.sonar.server.ws.WsUtils.checkRequest;
 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN;
 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
-import static org.sonar.server.ws.WsUtils.checkRequest;
 
 public class PermissionRequestValidator {
   public static final String MSG_TEMPLATE_WITH_SAME_NAME = "A template with the name '%s' already exists (case insensitive).";
@@ -79,6 +82,17 @@ public class PermissionRequestValidator {
       format("The '%s' parameter must be one of %s. '%s' was passed.", PARAM_QUALIFIER, rootQualifiers, qualifier));
   }
 
+  public static void validateQualifier(@Nullable String qualifier, ResourceTypes resourceTypes) {
+    if (qualifier == null) {
+      return;
+    }
+    Set<String> rootQualifiers = FluentIterable.from(resourceTypes.getRoots())
+      .transform(RESOURCE_TYPE_TO_QUALIFIER)
+      .toSet();
+    checkRequest(rootQualifiers.contains(qualifier),
+      format("The '%s' parameter must be one of %s. '%s' was passed.", PARAM_QUALIFIER, rootQualifiers, qualifier));
+  }
+
   public static void validateProjectPattern(@Nullable String projectPattern) {
     if (isNullOrEmpty(projectPattern)) {
       return;
index bb9fe7cf40367d01def5120e27b172d3f2000cbc..72d39c950d4cc72491349c13ce1327861f61fa9a 100644 (file)
 
 package org.sonar.server.permission.ws;
 
+import java.util.Set;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewParam;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.permission.ProjectPermissions;
 import org.sonar.core.util.Uuids;
+import org.sonar.server.user.UserSession;
 
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Ordering.natural;
 import static java.lang.String.format;
+import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_DESCRIPTION;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN;
 
 public class PermissionsWsParametersBuilder {
 
@@ -47,25 +67,25 @@ public class PermissionsWsParametersBuilder {
   }
 
   public static void createPermissionParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION)
+    action.createParam(PARAM_PERMISSION)
       .setDescription(PERMISSION_PARAM_DESCRIPTION)
       .setRequired(true);
   }
 
   public static void createProjectPermissionParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION)
+    action.createParam(PARAM_PERMISSION)
       .setDescription(PROJECT_PERMISSION_PARAM_DESCRIPTION)
       .setRequired(true);
   }
 
   public static void createGroupNameParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME)
+    action.createParam(PARAM_GROUP_NAME)
       .setDescription("Group name or 'anyone' (case insensitive)")
       .setExampleValue("sonar-administrators");
   }
 
   public static void createGroupIdParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID)
+    action.createParam(PARAM_GROUP_ID)
       .setDescription("Group id")
       .setExampleValue("42");
   }
@@ -76,19 +96,19 @@ public class PermissionsWsParametersBuilder {
   }
 
   private static void createProjectIdParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID)
+    action.createParam(PARAM_PROJECT_ID)
       .setDescription("Project id")
       .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
   }
 
   private static void createProjectKeyParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY)
+    action.createParam(PARAM_PROJECT_KEY)
       .setDescription("Project key")
       .setExampleValue("org.apache.hbas:hbase");
   }
 
   public static void createUserLoginParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN)
+    action.createParam(PARAM_USER_LOGIN)
       .setRequired(true)
       .setDescription("User login")
       .setExampleValue("g.hopper");
@@ -100,33 +120,90 @@ public class PermissionsWsParametersBuilder {
   }
 
   private static void createTemplateIdParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID)
+    action.createParam(PARAM_TEMPLATE_ID)
       .setDescription("Template id")
       .setExampleValue(Uuids.UUID_EXAMPLE_01);
   }
 
   private static void createTemplateNameParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME)
+    action.createParam(PARAM_TEMPLATE_NAME)
       .setDescription("Template name")
       .setExampleValue("Default Permission Template for Projects");
   }
 
   public static void createTemplateProjectKeyPatternParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN)
+    action.createParam(PARAM_PROJECT_KEY_PATTERN)
       .setDescription("Project key pattern. Must be a valid Java regular expression")
       .setExampleValue(".*\\.finance\\..*");
   }
 
   public static void createTemplateDescriptionParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_DESCRIPTION)
+    action.createParam(PARAM_DESCRIPTION)
       .setDescription("Description")
       .setExampleValue("Permissions for all projects related to the financial service");
   }
 
   public static void createIdParameter(NewAction action) {
-    action.createParam(org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ID)
+    action.createParam(PARAM_ID)
       .setRequired(true)
       .setDescription("Id")
       .setExampleValue("af8cb8cc-1e78-4c4e-8c00-ee8e814009a5");
   }
+
+  public static NewParam createQualifierParameter(NewAction action, QualifierParameterContext context) {
+    return action.createParam(PARAM_QUALIFIER)
+      .setDescription("Project qualifier. Filter the results with the specified qualifier. Possible values are:" + buildRootQualifiersDescription(context))
+      .setPossibleValues(getRootQualifiers(context.getResourceTypes()));
+  }
+
+  private static Set<String> getRootQualifiers(ResourceTypes resourceTypes) {
+    return from(resourceTypes.getRoots())
+      .transform(RESOURCE_TYPE_TO_QUALIFIER)
+      .toSortedSet(natural());
+  }
+
+  private static String buildRootQualifiersDescription(QualifierParameterContext context) {
+    StringBuilder description = new StringBuilder();
+    description.append("<ul>");
+    String qualifierPattern = "<li>%s - %s</li>";
+    for (String qualifier : getRootQualifiers(context.getResourceTypes())) {
+      description.append(format(qualifierPattern, qualifier, qualifierLabel(context, qualifier)));
+    }
+    description.append("</ul>");
+
+    return description.toString();
+  }
+
+  private static String qualifierLabel(QualifierParameterContext context, String qualifier) {
+    String qualifiersPropertyPrefix = "qualifiers.";
+    return context.getI18n().message(context.getUserSession().locale(), qualifiersPropertyPrefix + qualifier, "");
+  }
+
+  public static class QualifierParameterContext {
+    private final I18n i18n;
+    private final ResourceTypes resourceTypes;
+    private final UserSession userSession;
+
+    private QualifierParameterContext(UserSession userSession, I18n i18n, ResourceTypes resourceTypes) {
+      this.i18n = i18n;
+      this.resourceTypes = resourceTypes;
+      this.userSession = userSession;
+    }
+
+    public static QualifierParameterContext newQualifierParameterContext(UserSession userSession, I18n i18n, ResourceTypes resourceTypes) {
+      return new QualifierParameterContext(userSession, i18n, resourceTypes);
+    }
+
+    public I18n getI18n() {
+      return i18n;
+    }
+
+    public ResourceTypes getResourceTypes() {
+      return resourceTypes;
+    }
+
+    public UserSession getUserSession() {
+      return userSession;
+    }
+  }
 }
index 5d61994d0a281c3251642f063d5d9ff026aee5b3..41f5000ea2baa04a00ef0aa9a3a7bdb3accfa235 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.permission.ws;
 
 import com.google.common.base.Optional;
 import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
@@ -41,11 +42,15 @@ import org.sonarqube.ws.client.permission.SearchProjectPermissionsWsRequest;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentKey;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentUuid;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
+import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.QualifierParameterContext.newQualifierParameterContext;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createProjectParameter;
+import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createQualifierParameter;
 import static org.sonar.server.permission.ws.WsProjectRef.newOptionalWsProjectRef;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
 
 public class SearchProjectPermissionsAction implements PermissionsWsAction {
   private static final String PROPERTY_PREFIX = "projects_role.";
@@ -54,12 +59,14 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
   private final DbClient dbClient;
   private final UserSession userSession;
   private final I18n i18n;
+  private final ResourceTypes resourceTypes;
   private final SearchProjectPermissionsDataLoader dataLoader;
 
-  public SearchProjectPermissionsAction(DbClient dbClient, UserSession userSession, I18n i18n, SearchProjectPermissionsDataLoader dataLoader) {
+  public SearchProjectPermissionsAction(DbClient dbClient, UserSession userSession, I18n i18n, ResourceTypes resourceTypes, SearchProjectPermissionsDataLoader dataLoader) {
     this.dbClient = dbClient;
     this.userSession = userSession;
     this.i18n = i18n;
+    this.resourceTypes = resourceTypes;
     this.dataLoader = dataLoader;
   }
 
@@ -75,6 +82,8 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
       .setHandler(this);
 
     createProjectParameter(action);
+    createQualifierParameter(action, newQualifierParameterContext(userSession, i18n, resourceTypes))
+      .setSince("5.3");
   }
 
   @Override
@@ -87,6 +96,7 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
     checkRequestAndPermissions(request);
     DbSession dbSession = dbClient.openSession(false);
     try {
+      validateQualifier(request.getQualifier(), resourceTypes);
       SearchProjectPermissionsData data = dataLoader.load(request);
       return buildResponse(data);
     } finally {
@@ -98,6 +108,7 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
     return new SearchProjectPermissionsWsRequest()
       .setProjectId(request.param(PARAM_PROJECT_ID))
       .setProjectKey(request.param(PARAM_PROJECT_KEY))
+      .setQualifier(request.param(PARAM_QUALIFIER))
       .setPage(request.mandatoryParamAsInt(Param.PAGE))
       .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
       .setQuery(request.param(Param.TEXT_QUERY));
index b1b96ff4a14c392aa0a7e0a512423b6942471b8e..1d352f1a1d6d6fbefec6ed59f482acdf794b9f69 100644 (file)
@@ -29,6 +29,7 @@ import com.google.common.collect.TreeBasedTable;
 import java.util.Collection;
 import java.util.List;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.apache.ibatis.session.ResultContext;
 import org.apache.ibatis.session.ResultHandler;
 import org.sonar.api.resources.ResourceTypes;
@@ -39,6 +40,7 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.permission.CountByProjectAndPermissionDto;
 import org.sonarqube.ws.client.permission.SearchProjectPermissionsWsRequest;
 
+import static java.util.Collections.singleton;
 import static java.util.Collections.singletonList;
 import static org.sonar.api.utils.Paging.forPageIndex;
 import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
@@ -60,7 +62,7 @@ public class SearchProjectPermissionsDataLoader {
     DbSession dbSession = dbClient.openSession(false);
     try {
       SearchProjectPermissionsData.Builder data = newBuilder();
-      int countRootComponents = countRootComponents(dbSession, rootQualifiers, request);
+      int countRootComponents = countRootComponents(dbSession, qualifiers(request.getQualifier()), request);
       List<ComponentDto> rootComponents = searchRootComponents(dbSession, request, paging(request, countRootComponents));
       List<Long> rootComponentIds = Lists.transform(rootComponents, ComponentToIdFunction.INSTANCE);
 
@@ -93,7 +95,13 @@ public class SearchProjectPermissionsDataLoader {
       return singletonList(finder.getRootComponentOrModule(dbSession, project.get()));
     }
 
-    return dbClient.componentDao().selectComponents(dbSession, rootQualifiers, paging.offset(), paging.pageSize(), query);
+    return dbClient.componentDao().selectComponents(dbSession, qualifiers(request.getQualifier()), paging.offset(), paging.pageSize(), query);
+  }
+
+  private Collection<String> qualifiers(@Nullable String requestQualifier) {
+    return requestQualifier == null
+      ? rootQualifiers
+      : singleton(requestQualifier);
   }
 
   private Table<Long, String, Integer> userCountByRootComponentIdAndPermission(DbSession dbSession, List<Long> rootComponentIds) {
index b1d9c7962a82a18dbf095855ff34bfdda358fdb3..5d98cfb0b85ceec257e4d1c21c4b994fe9c92525 100644 (file)
@@ -20,7 +20,6 @@
 
 package org.sonar.server.permission.ws.template;
 
-import java.util.Set;
 import org.sonar.api.i18n.I18n;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
@@ -36,13 +35,11 @@ import org.sonar.server.platform.PersistentSettings;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.client.permission.SetDefaultTemplateWsRequest;
 
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Ordering.natural;
-import static java.lang.String.format;
-import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
 import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
 import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
+import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.QualifierParameterContext.newQualifierParameterContext;
+import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createQualifierParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createTemplateParameters;
 import static org.sonar.server.permission.ws.WsTemplateRef.newTemplateRef;
 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
@@ -77,11 +74,8 @@ public class SetDefaultTemplateAction implements PermissionsWsAction {
       .setHandler(this);
 
     createTemplateParameters(action);
-
-    action.createParam(PARAM_QUALIFIER)
-      .setDescription("Project qualifier. Possible values are:" + buildRootQualifiersDescription())
-      .setDefaultValue(Qualifiers.PROJECT)
-      .setPossibleValues(getRootQualifiers());
+    createQualifierParameter(action, newQualifierParameterContext(userSession, i18n, resourceTypes))
+      .setDefaultValue(Qualifiers.PROJECT);
   }
 
   @Override
@@ -95,7 +89,7 @@ public class SetDefaultTemplateAction implements PermissionsWsAction {
 
     String qualifier = request.getQualifier();
     PermissionTemplateDto template = getTemplate(request);
-    validateQualifier(qualifier, getRootQualifiers());
+    validateQualifier(qualifier, resourceTypes);
     setDefaultTemplateUuid(template.getUuid(), qualifier);
   }
 
@@ -106,29 +100,6 @@ public class SetDefaultTemplateAction implements PermissionsWsAction {
       .setTemplateName(request.param(PARAM_TEMPLATE_NAME));
   }
 
-  private Set<String> getRootQualifiers() {
-    return from(resourceTypes.getRoots())
-      .transform(RESOURCE_TYPE_TO_QUALIFIER)
-      .toSortedSet(natural());
-  }
-
-  private String buildRootQualifiersDescription() {
-    StringBuilder description = new StringBuilder();
-    description.append("<ul>");
-    String qualifierPattern = "<li>%s - %s</li>";
-    for (String qualifier : getRootQualifiers()) {
-      description.append(format(qualifierPattern, qualifier, i18n(qualifier)));
-    }
-    description.append("</ul>");
-
-    return description.toString();
-  }
-
-  private String i18n(String qualifier) {
-    String qualifiersPropertyPrefix = "qualifiers.";
-    return i18n.message(userSession.locale(), qualifiersPropertyPrefix + qualifier, "");
-  }
-
   private PermissionTemplateDto getTemplate(SetDefaultTemplateWsRequest request) {
     DbSession dbSession = dbClient.openSession(false);
     try {
index 792392e14e266d5c2f7fc132c5e71bb06acf3482..8d3d2f6d4ca68d41feaa583f00c3b98a7368b05e 100644 (file)
 
 package org.sonar.server.permission.ws;
 
-import java.util.List;
+import java.io.IOException;
 import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.permission.GlobalPermissions;
@@ -36,6 +35,7 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.GroupRoleDto;
 import org.sonar.db.user.UserDto;
@@ -46,12 +46,13 @@ import org.sonar.server.exceptions.UnauthorizedException;
 import org.sonar.server.i18n.I18nRule;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.usergroups.ws.UserGroupFinder;
+import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse;
 
-import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import static org.sonar.api.server.ws.WebService.Param.PAGE;
 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
 import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
@@ -61,9 +62,11 @@ import static org.sonar.db.component.ComponentTesting.newProjectDto;
 import static org.sonar.db.component.ComponentTesting.newView;
 import static org.sonar.db.user.GroupTesting.newGroupDto;
 import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
 import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
 
+@Category(DbTests.class)
 public class SearchProjectPermissionsActionTest {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
@@ -76,21 +79,20 @@ public class SearchProjectPermissionsActionTest {
   I18nRule i18n = new I18nRule();
   DbClient dbClient = db.getDbClient();
   DbSession dbSession = db.getSession();
-  ResourceTypes resourceTypes = mock(ResourceTypes.class);
+  ResourceTypesRule resourceTypes = new ResourceTypesRule();
   SearchProjectPermissionsDataLoader dataLoader;
 
   SearchProjectPermissionsAction underTest;
 
   @Before
   public void setUp() {
-    resourceTypes = mock(ResourceTypes.class);
-    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
+    resourceTypes.setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV");
     ComponentFinder componentFinder = new ComponentFinder(dbClient);
     PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, componentFinder, new UserGroupFinder(dbClient), resourceTypes);
     i18n.setProjectPermissions();
 
     dataLoader = new SearchProjectPermissionsDataLoader(dbClient, finder, resourceTypes);
-    underTest = new SearchProjectPermissionsAction(dbClient, userSession, i18n, dataLoader);
+    underTest = new SearchProjectPermissionsAction(dbClient, userSession, i18n, resourceTypes, dataLoader);
 
     ws = new WsActionTester(underTest);
 
@@ -220,15 +222,15 @@ public class SearchProjectPermissionsActionTest {
 
   @Test
   public void result_depends_of_root_types() {
-    ResourceType projectResourceType = ResourceType.builder(Qualifiers.PROJECT).build();
-    when(resourceTypes.getRoots()).thenReturn(asList(projectResourceType));
+    resourceTypes.setRootQualifiers(Qualifiers.PROJECT);
     insertComponent(newView("view-uuid"));
     insertComponent(newDeveloper("developer-name"));
     insertComponent(newProjectDto("project-uuid"));
     commit();
-    dataLoader = new SearchProjectPermissionsDataLoader(dbClient, new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient), new UserGroupFinder(dbClient), resourceTypes),
+    dataLoader = new SearchProjectPermissionsDataLoader(dbClient,
+      new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient), new UserGroupFinder(dbClient), resourceTypes),
       resourceTypes);
-    underTest = new SearchProjectPermissionsAction(dbClient, userSession, i18n, dataLoader);
+    underTest = new SearchProjectPermissionsAction(dbClient, userSession, i18n, resourceTypes, dataLoader);
     ws = new WsActionTester(underTest);
 
     String result = ws.newRequest().execute().getInput();
@@ -238,6 +240,26 @@ public class SearchProjectPermissionsActionTest {
       .doesNotContain("developer-name");
   }
 
+  @Test
+  public void filter_by_qualifier() throws IOException {
+    insertComponent(newView("view-uuid"));
+    insertComponent(newDeveloper("developer-name"));
+    insertComponent(newProjectDto("project-uuid"));
+    commit();
+
+    TestResponse wsResponse = ws.newRequest()
+      .setMediaType(MediaTypes.PROTOBUF)
+      .setParam(PARAM_QUALIFIER, Qualifiers.PROJECT)
+      .execute();
+    SearchProjectPermissionsWsResponse result = SearchProjectPermissionsWsResponse.parseFrom(wsResponse.getInputStream());
+
+    assertThat(result.getProjectsList())
+      .extracting("id")
+      .contains("project-uuid")
+      .doesNotContain("view-uuid")
+      .doesNotContain("developer-name");
+  }
+
   @Test
   public void fail_if_not_logged_in() {
     expectedException.expect(UnauthorizedException.class);
@@ -312,12 +334,4 @@ public class SearchProjectPermissionsActionTest {
   private void commit() {
     dbSession.commit();
   }
-
-  private static List<ResourceType> rootResourceTypes() {
-    ResourceType project = ResourceType.builder(Qualifiers.PROJECT).build();
-    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
-    ResourceType dev = ResourceType.builder("DEV").build();
-
-    return asList(project, view, dev);
-  }
 }
index 61a8dcd28c57d53b8f8d34bbd84162bb93a62b04..bb14ee02718c689d655d659f35fb9a0931101bd9 100644 (file)
@@ -166,6 +166,7 @@ public class PermissionsWsClient {
       newGetRequest(action("search_project_permissions"))
         .setParam(PARAM_PROJECT_ID, request.getProjectId())
         .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+        .setParam(PARAM_QUALIFIER, request.getQualifier())
         .setParam("p", request.getPage())
         .setParam("ps", request.getPageSize())
         .setParam("q", request.getQuery()),
index 2814bc1095093e3ae3242c389470a167f937df42..9bbed409ff7d60903f05b9defb60df80b3e3a6fe 100644 (file)
@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
 public class SearchProjectPermissionsWsRequest {
   private String projectId;
   private String projectKey;
+  private String qualifier;
   private Integer page;
   private Integer pageSize;
   private String query;
@@ -79,4 +80,14 @@ public class SearchProjectPermissionsWsRequest {
     this.query = query;
     return this;
   }
+
+  @CheckForNull
+  public String getQualifier() {
+    return qualifier;
+  }
+
+  public SearchProjectPermissionsWsRequest setQualifier(@Nullable String qualifier) {
+    this.qualifier = qualifier;
+    return this;
+  }
 }