From 0a8a13500a85c8454b30390e236c7588351c88f4 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Fri, 27 Nov 2015 18:09:46 +0100 Subject: [PATCH] SONAR-6892 WS permissions/search_project_permissions filter by qualifier --- .../ws/PermissionRequestValidator.java | 18 +++- .../ws/PermissionsWsParametersBuilder.java | 101 +++++++++++++++--- .../ws/SearchProjectPermissionsAction.java | 13 ++- .../SearchProjectPermissionsDataLoader.java | 12 ++- .../ws/template/SetDefaultTemplateAction.java | 39 +------ .../SearchProjectPermissionsActionTest.java | 60 +++++++---- .../permission/PermissionsWsClient.java | 1 + .../SearchProjectPermissionsWsRequest.java | 11 ++ 8 files changed, 181 insertions(+), 74 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.java index daf061e8e54..4b2247a19bb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.java @@ -21,10 +21,12 @@ 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 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; diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsParametersBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsParametersBuilder.java index bb9fe7cf403..72d39c950d4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsParametersBuilder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsParametersBuilder.java @@ -20,12 +20,32 @@ 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 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("
    "); + String qualifierPattern = "
  • %s - %s
  • "; + for (String qualifier : getRootQualifiers(context.getResourceTypes())) { + description.append(format(qualifierPattern, qualifier, qualifierLabel(context, qualifier))); + } + description.append("
"); + + 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; + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsAction.java index 5d61994d0a2..41f5000ea2b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsAction.java @@ -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)); diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java index b1b96ff4a14..1d352f1a1d6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java @@ -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 rootComponents = searchRootComponents(dbSession, request, paging(request, countRootComponents)); List 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 qualifiers(@Nullable String requestQualifier) { + return requestQualifier == null + ? rootQualifiers + : singleton(requestQualifier); } private Table userCountByRootComponentIdAndPermission(DbSession dbSession, List rootComponentIds) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java index b1d9c7962a8..5d98cfb0b85 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java @@ -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 getRootQualifiers() { - return from(resourceTypes.getRoots()) - .transform(RESOURCE_TYPE_TO_QUALIFIER) - .toSortedSet(natural()); - } - - private String buildRootQualifiersDescription() { - StringBuilder description = new StringBuilder(); - description.append("
    "); - String qualifierPattern = "
  • %s - %s
  • "; - for (String qualifier : getRootQualifiers()) { - description.append(format(qualifierPattern, qualifier, i18n(qualifier))); - } - description.append("
"); - - 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 { diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchProjectPermissionsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchProjectPermissionsActionTest.java index 792392e14e2..8d3d2f6d4ca 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchProjectPermissionsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchProjectPermissionsActionTest.java @@ -20,15 +20,14 @@ 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 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); - } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsWsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsWsClient.java index 61a8dcd28c5..bb14ee02718 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsWsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsWsClient.java @@ -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()), diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/SearchProjectPermissionsWsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/SearchProjectPermissionsWsRequest.java index 2814bc10950..9bbed409ff7 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/SearchProjectPermissionsWsRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/SearchProjectPermissionsWsRequest.java @@ -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; + } } -- 2.39.5