Browse Source

SONAR-9551 Web services handles APP qualifier

tags/6.6-RC1
Teryk Bellahsene 7 years ago
parent
commit
cab800cc17
26 changed files with 213 additions and 183 deletions
  1. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java
  2. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
  3. 1
    0
      server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionCategory.java
  4. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java
  5. 7
    6
      server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java
  6. 2
    1
      server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java
  7. 12
    4
      server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java
  8. 27
    27
      server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java
  9. 2
    2
      server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java
  10. 2
    1
      server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchAction.java
  11. 5
    15
      server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java
  12. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java
  13. 2
    2
      server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
  14. 25
    24
      server/sonar-server/src/main/java/org/sonar/server/ws/WsParameterBuilder.java
  15. 5
    0
      server/sonar-server/src/main/resources/org/sonar/server/component/ws/suggestions-example.json
  16. 1
    0
      server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java
  17. 16
    1
      server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java
  18. 20
    2
      server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java
  19. 9
    5
      server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java
  20. 22
    3
      server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java
  21. 4
    3
      server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java
  22. 25
    11
      server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java
  23. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java
  24. 15
    0
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java
  25. 2
    2
      server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchActionTest.java
  26. 4
    69
      server/sonar-server/src/test/java/org/sonar/server/project/ws/UpdateVisibilityActionTest.java

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java View File

@@ -69,7 +69,7 @@ import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_TYPE;

public class ActivityAction implements CeWsAction {
private static final int MAX_PAGE_SIZE = 1000;
private static final List<String> POSSIBLE_QUALIFIERS = ImmutableList.of(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV", Qualifiers.MODULE);
private static final List<String> POSSIBLE_QUALIFIERS = ImmutableList.of(Qualifiers.PROJECT, Qualifiers.APP, Qualifiers.VIEW, "DEV", Qualifiers.MODULE);

private final UserSession userSession;
private final DbClient dbClient;

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java View File

@@ -40,7 +40,7 @@ class ComponentDtoToWsComponent {
/**
* The concept of "visibility" will only be configured for these qualifiers.
*/
private static final Set<String> QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW);
private static final Set<String> QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP);

private ComponentDtoToWsComponent() {
// prevent instantiation

+ 1
- 0
server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionCategory.java View File

@@ -27,6 +27,7 @@ import static java.util.Arrays.stream;
public enum SuggestionCategory {
VIEW(Qualifiers.VIEW),
SUBVIEW(Qualifiers.SUBVIEW),
APP(Qualifiers.APP),
PROJECT(Qualifiers.PROJECT),
MODULE(Qualifiers.MODULE),
FILE(Qualifiers.FILE),

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java View File

@@ -117,7 +117,7 @@ public class SuggestionsAction implements ComponentsWsAction {
.setSince("4.2")
.setInternal(true)
.setHandler(this)
.setResponseExample(Resources.getResource(this.getClass(), "components-example-suggestions.json"))
.setResponseExample(Resources.getResource(this.getClass(), "suggestions-example.json"))
.setChangelog(new Change("6.4", "Parameter 's' is optional"));

action.createParam(PARAM_QUERY)

+ 7
- 6
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java View File

@@ -25,6 +25,7 @@ import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -35,6 +36,7 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.BooleanUtils;
@@ -292,6 +294,7 @@ public class IssueQueryFactory {
switch (qualifier) {
case Qualifiers.VIEW:
case Qualifiers.SUBVIEW:
case Qualifiers.APP:
addViewsOrSubViews(builder, componentUuids);
break;
case Qualifiers.PROJECT:
@@ -313,12 +316,10 @@ public class IssueQueryFactory {
}

private void addViewsOrSubViews(IssueQuery.Builder builder, Collection<String> viewOrSubViewUuids) {
List<String> filteredViewUuids = new ArrayList<>();
for (String viewUuid : viewOrSubViewUuids) {
if (userSession.hasComponentUuidPermission(UserRole.USER, viewUuid)) {
filteredViewUuids.add(viewUuid);
}
}
List<String> filteredViewUuids = viewOrSubViewUuids.stream()
.filter(uuid -> userSession.hasComponentUuidPermission(UserRole.USER, uuid))
.collect(Collectors.toList());

if (filteredViewUuids.isEmpty()) {
filteredViewUuids.add(UNKNOWN);
}

+ 2
- 1
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java View File

@@ -45,6 +45,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Comparator.comparing;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.api.resources.Qualifiers.SUBVIEW;
import static org.sonar.api.resources.Qualifiers.VIEW;
@@ -60,7 +61,7 @@ import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_PROJECT

public class SearchAction implements MeasuresWsAction {

private static final Set<String> ALLOWED_QUALIFIERS = ImmutableSet.of(PROJECT, VIEW, SUBVIEW);
private static final Set<String> ALLOWED_QUALIFIERS = ImmutableSet.of(PROJECT, APP, VIEW, SUBVIEW);

private final UserSession userSession;
private final DbClient dbClient;

+ 12
- 4
server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java View File

@@ -110,7 +110,9 @@ public class PermissionIndexerDao {
" FROM projects " +
" INNER JOIN user_roles ON user_roles.resource_id = projects.id AND user_roles.role = 'user' " +
" WHERE " +
" (projects.qualifier = 'TRK' or projects.qualifier = 'VW') " +
" (projects.qualifier = 'TRK' " +
" or projects.qualifier = 'VW' " +
" or projects.qualifier = 'APP') " +
" AND projects.copy_component_uuid is NULL " +
" {projectsCondition} " +
" UNION " +
@@ -126,7 +128,9 @@ public class PermissionIndexerDao {
" INNER JOIN group_roles ON group_roles.resource_id = projects.id AND group_roles.role = 'user' " +
" INNER JOIN groups ON groups.id = group_roles.group_id " +
" WHERE " +
" (projects.qualifier = 'TRK' or projects.qualifier = 'VW') " +
" (projects.qualifier = 'TRK' " +
" or projects.qualifier = 'VW' " +
" or projects.qualifier = 'APP') " +
" AND projects.copy_component_uuid is NULL " +
" {projectsCondition} " +
" AND group_id IS NOT NULL " +
@@ -141,7 +145,9 @@ public class PermissionIndexerDao {
" NULL AS group_id " +
" FROM projects " +
" WHERE " +
" (projects.qualifier = 'TRK' or projects.qualifier = 'VW') " +
" (projects.qualifier = 'TRK' " +
" or projects.qualifier = 'VW' " +
" or projects.qualifier = 'APP') " +
" AND projects.copy_component_uuid is NULL " +
" AND projects.private = ? " +
" {projectsCondition} " +
@@ -155,7 +161,9 @@ public class PermissionIndexerDao {
" NULL AS group_id " +
" FROM projects " +
" WHERE " +
" (projects.qualifier = 'TRK' or projects.qualifier = 'VW') " +
" (projects.qualifier = 'TRK' " +
" or projects.qualifier = 'VW' " +
" or projects.qualifier = 'APP') " +
" AND projects.copy_component_uuid is NULL " +
" AND projects.private = ? " +
" {projectsCondition} " +

+ 27
- 27
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java View File

@@ -66,6 +66,33 @@ public class SearchTemplatesAction implements PermissionsWsAction {
this.dataLoader = dataLoader;
}

@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("search_templates")
.setDescription("List permission templates.<br />" +
"Requires the following permission: 'Administer System'.")
.setResponseExample(getClass().getResource("search_templates-example.json"))
.setSince("5.2")
.addSearchQuery("defau", "permission template names")
.setHandler(this);

createOrganizationParameter(action).setSince("6.2");
}

@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
try (DbSession dbSession = dbClient.openSession(false)) {
OrganizationDto org = support.findOrganization(dbSession, wsRequest.param(PARAM_ORGANIZATION));
SearchTemplatesWsRequest request = new SearchTemplatesWsRequest()
.setOrganizationUuid(org.getUuid())
.setQuery(wsRequest.param(Param.TEXT_QUERY));
checkGlobalAdmin(userSession, request.getOrganizationUuid());

SearchTemplatesWsResponse searchTemplatesWsResponse = buildResponse(dataLoader.load(dbSession, request));
writeProtobuf(searchTemplatesWsResponse, wsRequest, wsResponse);
}
}

private static void buildDefaultTemplatesResponse(SearchTemplatesWsResponse.Builder response, SearchTemplatesData data) {
TemplateIdQualifier.Builder templateUuidQualifierBuilder = TemplateIdQualifier.newBuilder();

@@ -108,33 +135,6 @@ public class SearchTemplatesAction implements PermissionsWsAction {
}
}

@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("search_templates")
.setDescription("List permission templates.<br />" +
"Requires the following permission: 'Administer System'.")
.setResponseExample(getClass().getResource("search_templates-example.json"))
.setSince("5.2")
.addSearchQuery("defau", "permission template names")
.setHandler(this);

createOrganizationParameter(action).setSince("6.2");
}

@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
try (DbSession dbSession = dbClient.openSession(false)) {
OrganizationDto org = support.findOrganization(dbSession, wsRequest.param(PARAM_ORGANIZATION));
SearchTemplatesWsRequest request = new SearchTemplatesWsRequest()
.setOrganizationUuid(org.getUuid())
.setQuery(wsRequest.param(Param.TEXT_QUERY));
checkGlobalAdmin(userSession, request.getOrganizationUuid());

SearchTemplatesWsResponse searchTemplatesWsResponse = buildResponse(dataLoader.load(dbSession, request));
writeProtobuf(searchTemplatesWsResponse, wsRequest, wsResponse);
}
}

private WsPermissions.SearchTemplatesWsResponse buildResponse(SearchTemplatesData data) {
SearchTemplatesWsResponse.Builder response = SearchTemplatesWsResponse.newBuilder();


+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java View File

@@ -39,8 +39,8 @@ import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobal
import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createTemplateParameters;
import static org.sonar.server.permission.ws.template.WsTemplateRef.newTemplateRef;
import static org.sonar.server.ws.WsParameterBuilder.createRootQualifierParameter;
import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
import static org.sonar.server.ws.WsParameterBuilder.createDefaultTemplateQualifierParameter;
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
@@ -81,7 +81,7 @@ public class SetDefaultTemplateAction implements PermissionsWsAction {
.setHandler(this);

createTemplateParameters(action);
createRootQualifierParameter(action, newQualifierParameterContext(i18n, resourceTypes))
createDefaultTemplateQualifierParameter(action, newQualifierParameterContext(i18n, resourceTypes))
.setDefaultValue(Qualifiers.PROJECT);
}


+ 2
- 1
server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchAction.java View File

@@ -40,6 +40,7 @@ import org.sonarqube.ws.client.project.SearchWsRequest;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Optional.ofNullable;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.api.resources.Qualifiers.VIEW;
import static org.sonar.core.util.Protobuf.setNullable;
@@ -84,7 +85,7 @@ public class SearchAction implements ProjectsWsAction {

action.createParam(PARAM_QUALIFIERS)
.setDescription("Comma-separated list of component qualifiers. Filter the results with the specified qualifiers")
.setPossibleValues(PROJECT, VIEW)
.setPossibleValues(PROJECT, VIEW, APP)
.setDefaultValue(PROJECT);
support.addOrganizationParam(action);


+ 5
- 15
server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java View File

@@ -19,10 +19,7 @@
*/
package org.sonar.server.project.ws;

import com.google.common.collect.ImmutableSet;
import java.util.Set;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
@@ -49,8 +46,6 @@ import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT
import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_VISIBILITY;

public class UpdateVisibilityAction implements ProjectsWsAction {
private static final Set<String> ALLOWED_QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW);

private final DbClient dbClient;
private final ComponentFinder componentFinder;
private final UserSession userSession;
@@ -68,19 +63,19 @@ public class UpdateVisibilityAction implements ProjectsWsAction {

public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction(ProjectsWsParameters.ACTION_UPDATE_VISIBILITY)
.setDescription("Updates visibility of a project or a view.<br/>" +
"Requires 'Project administer' permission on the specified project or view")
.setDescription("Updates visibility of a project.<br>" +
"Requires 'Project administer' permission on the specified project")
.setSince("6.4")
.setPost(true)
.setHandler(this);

action.createParam(PARAM_PROJECT)
.setDescription("Project or view key")
.setDescription("Project key")
.setExampleValue(KEY_PROJECT_EXAMPLE_001)
.setRequired(true);

action.createParam(PARAM_VISIBILITY)
.setDescription("new visibility of the project or view")
.setDescription("New visibility")
.setPossibleValues(Visibility.getLabels())
.setRequired(true);
}
@@ -94,8 +89,7 @@ public class UpdateVisibilityAction implements ProjectsWsAction {

try (DbSession dbSession = dbClient.openSession(false)) {
ComponentDto component = componentFinder.getByKey(dbSession, projectKey);
checkRequest(isRoot(component), "Component must either be a project or a view");
checkRequest(!changeToPrivate || !Qualifiers.VIEW.equals(component.qualifier()), "Views can't be made private");
checkRequest(component.isRootProject() && Qualifiers.PROJECT.equals(component.qualifier()), "Component must be a project");
userSession.checkComponentPermission(UserRole.ADMIN, component);
checkRequest(noPendingTask(dbSession, component), "Component visibility can't be changed as long as it has background task(s) pending or in progress");

@@ -114,10 +108,6 @@ public class UpdateVisibilityAction implements ProjectsWsAction {
}
}

private static boolean isRoot(ComponentDto component) {
return Scopes.PROJECT.equals(component.scope()) && ALLOWED_QUALIFIERS.contains(component.qualifier());
}

private boolean noPendingTask(DbSession dbSession, ComponentDto rootComponent) {
return dbClient.ceQueueDao().selectByComponentUuid(dbSession, rootComponent.uuid()).isEmpty();
}

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java View File

@@ -63,7 +63,7 @@ public class SettingValidations {
};
}

private static final Set<String> SUPPORTED_QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.MODULE, Qualifiers.SUBVIEW);
private static final Set<String> SUPPORTED_QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP, Qualifiers.MODULE, Qualifiers.SUBVIEW);

public Consumer<SettingData> qualifier() {
return data -> {

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java View File

@@ -82,7 +82,7 @@ public class ComponentAction implements NavigationWsAction {
/**
* The concept of "visibility" will only be configured for these qualifiers.
*/
private static final Set<String> QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW);
private static final Set<String> QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP);

private final DbClient dbClient;
private final PageRepository pageRepository;
@@ -248,7 +248,7 @@ public class ComponentAction implements NavigationWsAction {
private void writeConfigPageAccess(JsonWriter json, boolean isProjectAdmin, ComponentDto component, OrganizationDto organization) {
boolean isProject = Qualifiers.PROJECT.equals(component.qualifier());
boolean showManualMeasures = isProjectAdmin && !Qualifiers.DIRECTORY.equals(component.qualifier());
boolean showBackgroundTasks = isProjectAdmin && (isProject || Qualifiers.VIEW.equals(component.qualifier()));
boolean showBackgroundTasks = isProjectAdmin && (isProject || Qualifiers.VIEW.equals(component.qualifier()) || Qualifiers.APP.equals(component.qualifier()));
boolean isQualityProfileAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, component.getOrganizationUuid());
boolean isQualityGateAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, component.getOrganizationUuid());
boolean isOrganizationAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER, component.getOrganizationUuid());

+ 25
- 24
server/sonar-server/src/main/java/org/sonar/server/ws/WsParameterBuilder.java View File

@@ -19,26 +19,21 @@
*/
package org.sonar.server.ws;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import java.util.Locale;
import java.util.Set;
import javax.annotation.Nullable;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.sonar.api.i18n.I18n;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.ResourceType;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.server.ws.WebService;

import static com.google.common.base.Predicates.not;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Ordering.natural;
import static java.lang.String.format;

public class WsParameterBuilder {
private static final String PARAM_QUALIFIER = "qualifier";
private static final String PARAM_QUALIFIERS = "qualifiers";
private static final Set<String> DEPRECATED_QUALIFIERS = ImmutableSet.of(Qualifiers.LIBRARY);

private WsParameterBuilder() {
// static methods only
@@ -50,6 +45,12 @@ public class WsParameterBuilder {
.setPossibleValues(getRootQualifiers(context.getResourceTypes()));
}

public static WebService.NewParam createDefaultTemplateQualifierParameter(WebService.NewAction action, QualifierParameterContext context) {
return action.createParam(PARAM_QUALIFIER)
.setDescription("Project qualifier. Filter the results with the specified qualifier. Possible values are:" + buildDefaultTemplateQualifiersDescription(context))
.setPossibleValues(getDefaultTemplateQualifiers(context.getResourceTypes()));
}

public static WebService.NewParam createQualifiersParameter(WebService.NewAction action, QualifierParameterContext context) {
return action.createParam(PARAM_QUALIFIERS)
.setDescription(
@@ -58,17 +59,26 @@ public class WsParameterBuilder {
}

private static Set<String> getRootQualifiers(ResourceTypes resourceTypes) {
return from(resourceTypes.getRoots())
.transform(ResourceType::getQualifier)
.filter(not(IsDeprecatedQualifier.INSTANCE))
.toSortedSet(natural());
return resourceTypes.getRoots().stream()
.map(ResourceType::getQualifier)
.collect(Collectors.toCollection(TreeSet::new));
}

private static Set<String> getDefaultTemplateQualifiers(ResourceTypes resourceTypes) {
return resourceTypes.getRoots().stream()
.map(ResourceType::getQualifier)
.filter(q -> !Qualifiers.APP.equals(q))
.collect(Collectors.toCollection(TreeSet::new));
}

private static Set<String> getAllQualifiers(ResourceTypes resourceTypes) {
return from(resourceTypes.getAll())
.transform(ResourceType::getQualifier)
.filter(not(IsDeprecatedQualifier.INSTANCE))
.toSortedSet(natural());
return resourceTypes.getAll().stream()
.map(ResourceType::getQualifier)
.collect(Collectors.toCollection(TreeSet::new));
}

private static String buildDefaultTemplateQualifiersDescription(QualifierParameterContext context) {
return buildQualifiersDescription(context, getDefaultTemplateQualifiers(context.getResourceTypes()));
}

private static String buildRootQualifiersDescription(QualifierParameterContext context) {
@@ -96,15 +106,6 @@ public class WsParameterBuilder {
return context.getI18n().message(Locale.ENGLISH, qualifiersPropertyPrefix + qualifier, "no description available");
}

private enum IsDeprecatedQualifier implements Predicate<String> {
INSTANCE;

@Override
public boolean apply(@Nullable String input) {
return DEPRECATED_QUALIFIERS.contains(input);
}
}

public static class QualifierParameterContext {
private final I18n i18n;
private final ResourceTypes resourceTypes;

server/sonar-server/src/main/resources/org/sonar/server/component/ws/components-example-suggestions.json → server/sonar-server/src/main/resources/org/sonar/server/component/ws/suggestions-example.json View File

@@ -10,6 +10,11 @@
"items": [],
"more": 0
},
{
"q": "APP",
"items": [],
"more": 0
},
{
"q": "TRK",
"items": [

+ 1
- 0
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java View File

@@ -94,6 +94,7 @@ public class ProjectDataLoaderTest {
String[][] allScopesAndQualifierButProjectAndModule = {
{Scopes.PROJECT, Qualifiers.VIEW},
{Scopes.PROJECT, Qualifiers.SUBVIEW},
{Scopes.PROJECT, Qualifiers.APP},
{Scopes.FILE, Qualifiers.PROJECT},
{Scopes.DIRECTORY, Qualifiers.DIRECTORY},
{Scopes.FILE, Qualifiers.UNIT_TEST_FILE},

+ 16
- 1
server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java View File

@@ -47,12 +47,14 @@ import org.sonar.test.JsonAssert;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.WsCe;
import org.sonarqube.ws.WsCe.ActivityResponse;
import org.sonarqube.ws.WsCe.Task;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.sonar.api.utils.DateUtils.formatDate;
import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.db.component.ComponentTesting.newApplication;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_QUERY;
@@ -91,7 +93,7 @@ public class ActivityActionTest {

assertThat(activityResponse.getTasksCount()).isEqualTo(2);
// chronological order, from newest to oldest
WsCe.Task task = activityResponse.getTasks(0);
Task task = activityResponse.getTasks(0);
assertThat(task.getOrganization()).isEqualTo(org2.getKey());
assertThat(task.getId()).isEqualTo("T2");
assertThat(task.getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
@@ -267,6 +269,19 @@ public class ActivityActionTest {
assertThat(activityResponse.getTasksList()).extracting("id").containsOnly("T2");
}

@Test
public void search_activity_returns_application() {
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto apacheApp = newApplication(organizationDto).setName("Apache App");
dbTester.components().insertViewAndSnapshot(apacheApp);
logInAsSystemAdministrator();
insertActivity("T2", apacheApp.uuid(), CeActivityDto.Status.SUCCESS);

ActivityResponse activityResponse = call(ws.newRequest().setParam(PARAM_COMPONENT_QUERY, "apac"));

assertThat(activityResponse.getTasksList()).extracting(Task::getId).containsOnly("T2");
}

@Test
public void search_task_id_in_queue_ignoring_other_parameters() throws IOException {
logInAsSystemAdministrator();

+ 20
- 2
server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java View File

@@ -153,7 +153,25 @@ public class ComponentUpdaterTest {
assertThat(loaded.getKey()).isEqualTo("view-key");
assertThat(loaded.name()).isEqualTo("view-name");
assertThat(loaded.qualifier()).isEqualTo("VW");
verify(projectIndexers).hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION);
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue();
}

@Test
public void persist_and_index_when_creating_application() {
NewComponent view = NewComponent.newComponentBuilder()
.setKey("app-key")
.setName("app-name")
.setQualifier(APP)
.setOrganizationUuid(db.getDefaultOrganization().getUuid())
.build();

ComponentDto returned = underTest.create(db.getSession(), view, null);

ComponentDto loaded = db.getDbClient().componentDao().selectOrFailByUuid(db.getSession(), returned.uuid());
assertThat(loaded.getKey()).isEqualTo("app-key");
assertThat(loaded.name()).isEqualTo("app-name");
assertThat(loaded.qualifier()).isEqualTo("APP");
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue();
}

@Test
@@ -171,7 +189,7 @@ public class ComponentUpdaterTest {
assertThat(loaded.getKey()).isEqualTo("app-key");
assertThat(loaded.name()).isEqualTo("app-name");
assertThat(loaded.qualifier()).isEqualTo("APP");
verify(projectIndexers).hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION);
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue();
}

@Test

+ 9
- 5
server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java View File

@@ -49,7 +49,6 @@ import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
import org.sonar.test.JsonAssert;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.WsComponents.SuggestionsWsResponse;
import org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Category;
@@ -68,6 +67,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.FILE;
import static org.sonar.api.resources.Qualifiers.MODULE;
import static org.sonar.api.resources.Qualifiers.PROJECT;
@@ -81,6 +81,7 @@ import static org.sonar.server.component.ws.SuggestionsAction.PARAM_MORE;
import static org.sonar.server.component.ws.SuggestionsAction.PARAM_QUERY;
import static org.sonar.server.component.ws.SuggestionsAction.PARAM_RECENTLY_BROWSED;
import static org.sonar.server.component.ws.SuggestionsAction.SHORT_INPUT_WARNING;
import static org.sonar.test.JsonAssert.assertJson;

public class SuggestionsActionTest {
private static final String[] SUGGESTION_QUALIFIERS = Stream.of(SuggestionCategory.values())
@@ -152,7 +153,7 @@ public class SuggestionsActionTest {
.setMediaType(MediaTypes.JSON)
.execute();

JsonAssert.assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(wsResponse.getInput());
assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(wsResponse.getInput());
}

@Test
@@ -348,7 +349,7 @@ public class SuggestionsActionTest {

assertThat(response.getResultsList())
.extracting(Category::getQ, Category::getItemsCount)
.containsExactlyInAnyOrder(tuple("VW", 0), tuple("SVW", 0), tuple("TRK", 1), tuple("BRC", 0), tuple("FIL", 0), tuple("UTS", 0));
.containsExactlyInAnyOrder(tuple("VW", 0), tuple("APP", 0), tuple("SVW", 0), tuple("TRK", 1), tuple("BRC", 0), tuple("FIL", 0), tuple("UTS", 0));
}

@Test
@@ -564,13 +565,14 @@ public class SuggestionsActionTest {

assertThat(response.getResultsList())
.extracting(Category::getQ, Category::getItemsCount)
.containsExactlyInAnyOrder(tuple("VW", 0), tuple("SVW", 0), tuple("TRK", 1), tuple("BRC", 0), tuple("FIL", 0), tuple("UTS", 0));
.containsExactlyInAnyOrder(tuple("VW", 0), tuple("SVW", 0), tuple("APP", 0), tuple("TRK", 1), tuple("BRC", 0), tuple("FIL", 0), tuple("UTS", 0));
}

@Test
public void should_only_provide_project_for_certain_qualifiers() throws Exception {
String query = randomAlphabetic(10);

ComponentDto app = db.components().insertApplication(organization, v -> v.setName(query));
ComponentDto view = db.components().insertView(organization, v -> v.setName(query));
ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubView(view).setName(query));
ComponentDto project = db.components().insertPrivateProject(organization, p -> p.setName(query));
@@ -580,6 +582,7 @@ public class SuggestionsActionTest {
componentIndexer.indexOnStartup(null);
authorizationIndexerTester.allowOnlyAnyone(project);
authorizationIndexerTester.allowOnlyAnyone(view);
authorizationIndexerTester.allowOnlyAnyone(app);

SuggestionsWsResponse response = ws.newRequest()
.setMethod("POST")
@@ -589,6 +592,7 @@ public class SuggestionsActionTest {
assertThat(response.getResultsList())
.extracting(Category::getQ, c -> c.getItemsList().stream().map(Suggestion::hasProject).findFirst().orElse(null))
.containsExactlyInAnyOrder(
tuple(SuggestionCategory.APP.getName(), false),
tuple(SuggestionCategory.VIEW.getName(), false),
tuple(SuggestionCategory.SUBVIEW.getName(), false),
tuple(SuggestionCategory.PROJECT.getName(), false),
@@ -689,7 +693,7 @@ public class SuggestionsActionTest {

@Test
public void show_more_results_filter_out_if_non_allowed_qualifiers() {
resourceTypes.setAllQualifiers(VIEW, SUBVIEW);
resourceTypes.setAllQualifiers(APP, VIEW, SUBVIEW);

check_proposal_to_show_more_results(10, 0, 0L, SuggestionCategory.PROJECT, true);
}

+ 22
- 3
server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java View File

@@ -58,6 +58,7 @@ import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.api.utils.DateUtils.parseDateTime;
import static org.sonar.db.component.ComponentTesting.newApplication;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
@@ -192,6 +193,24 @@ public class SearchActionTest {
assertThat(measure.getValue()).isEqualTo("15.5");
}


@Test
public void return_measures_on_application() throws Exception {
ComponentDto application = newApplication(db.getDefaultOrganization());
SnapshotDto viewSnapshot = db.components().insertProjectAndSnapshot(application);
MetricDto coverage = insertCoverageMetric();
dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, application, viewSnapshot).setValue(15.5d));
db.commit();

SearchWsResponse result = call(singletonList(application.key()), singletonList("coverage"));

List<Measure> measures = result.getMeasuresList();
assertThat(measures).hasSize(1);
Measure measure = measures.get(0);
assertThat(measure.getMetric()).isEqualTo("coverage");
assertThat(measure.getValue()).isEqualTo("15.5");
}

@Test
public void return_measures_on_sub_view() throws Exception {
ComponentDto view = newView(db.getDefaultOrganization());
@@ -332,7 +351,7 @@ public class SearchActionTest {
insertComplexityMetric();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only component of qualifiers [TRK, VW, SVW] are allowed");
expectedException.expectMessage("Only component of qualifiers [TRK, APP, VW, SVW] are allowed");

call(singletonList(module.key()), singletonList("complexity"));
}
@@ -345,7 +364,7 @@ public class SearchActionTest {
insertComplexityMetric();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only component of qualifiers [TRK, VW, SVW] are allowed");
expectedException.expectMessage("Only component of qualifiers [TRK, APP, VW, SVW] are allowed");

call(singletonList(dir.key()), singletonList("complexity"));
}
@@ -358,7 +377,7 @@ public class SearchActionTest {
insertComplexityMetric();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only component of qualifiers [TRK, VW, SVW] are allowed");
expectedException.expectMessage("Only component of qualifiers [TRK, APP, VW, SVW] are allowed");

call(singletonList(file.key()), singletonList("complexity"));
}

+ 4
- 3
server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java View File

@@ -229,11 +229,12 @@ public class DeleteActionTest {
ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project));
ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(module, "a/b"));
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(module, directory));
ComponentDto view = db.components().insertView(organization, (dto) -> {
});
ComponentDto view = db.components().insertView(organization);
ComponentDto subview1 = db.components().insertComponent(ComponentTesting.newSubView(view, "v1", "ksv1"));
ComponentDto subview2 = db.components().insertComponent(ComponentTesting.newSubView(subview1, "v2", "ksv2"));
ComponentDto application = db.components().insertApplication(organization);
ComponentDto projectCopy = db.components().insertComponent(ComponentTesting.newProjectCopy("pc1", project, subview1));
ComponentDto projectCopyForApplication = db.components().insertComponent(ComponentTesting.newProjectCopy("pc2", project, application));
logInAsAdministrator(organization);

sendRequest(organization);
@@ -241,7 +242,7 @@ public class DeleteActionTest {
verifyOrganizationDoesNotExist(organization);
ArgumentCaptor<List<ComponentDto>> arg = (ArgumentCaptor<List<ComponentDto>>) ((ArgumentCaptor) ArgumentCaptor.forClass(List.class));
verify(componentCleanerService).delete(any(DbSession.class), arg.capture());
assertThat(arg.getValue()).containsOnly(project, view);
assertThat(arg.getValue()).containsOnly(project, view, application);
}

@Test

+ 25
- 11
server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java View File

@@ -35,6 +35,7 @@ import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.GroupPermissionDto;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDbTester;
@@ -43,6 +44,7 @@ import org.sonar.db.user.UserDto;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.api.resources.Qualifiers.VIEW;
import static org.sonar.api.web.UserRole.ADMIN;
@@ -59,11 +61,13 @@ public class PermissionIndexerDaoTest {
private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
private UserDbTester userDbTester = new UserDbTester(dbTester);

private OrganizationDto organization;
private ComponentDto publicProject;
private ComponentDto privateProject1;
private ComponentDto privateProject2;
private ComponentDto view1;
private ComponentDto view2;
private ComponentDto application;
private UserDto user1;
private UserDto user2;
private GroupDto group;
@@ -71,15 +75,17 @@ public class PermissionIndexerDaoTest {
private PermissionIndexerDao underTest = new PermissionIndexerDao();

@Before
public void setUp() throws Exception {
publicProject = componentDbTester.insertPublicProject();
privateProject1 = componentDbTester.insertPrivateProject();
privateProject2 = componentDbTester.insertPrivateProject();
view1 = componentDbTester.insertView();
view2 = componentDbTester.insertView();
public void setUp() {
organization = dbTester.organizations().insert();
publicProject = componentDbTester.insertPublicProject(organization);
privateProject1 = componentDbTester.insertPrivateProject(organization);
privateProject2 = componentDbTester.insertPrivateProject(organization);
view1 = componentDbTester.insertView(organization);
view2 = componentDbTester.insertView(organization);
application = componentDbTester.insertApplication(organization);
user1 = userDbTester.insertUser();
user2 = userDbTester.insertUser();
group = userDbTester.insertGroup();
group = userDbTester.insertGroup(organization);
}

@Test
@@ -87,7 +93,7 @@ public class PermissionIndexerDaoTest {
insertTestDataForProjectsAndViews();

Collection<PermissionIndexerDao.Dto> dtos = underTest.selectAll(dbClient, dbSession);
assertThat(dtos).hasSize(5);
assertThat(dtos).hasSize(6);

PermissionIndexerDao.Dto publicProjectAuthorization = getByProjectUuid(publicProject.uuid(), dtos);
isPublic(publicProjectAuthorization, PROJECT);
@@ -95,6 +101,9 @@ public class PermissionIndexerDaoTest {
PermissionIndexerDao.Dto view1Authorization = getByProjectUuid(view1.uuid(), dtos);
isPublic(view1Authorization, VIEW);

PermissionIndexerDao.Dto applicationAuthorization = getByProjectUuid(application.uuid(), dtos);
isPublic(applicationAuthorization, APP);

PermissionIndexerDao.Dto privateProject1Authorization = getByProjectUuid(privateProject1.uuid(), dtos);
assertThat(privateProject1Authorization.getGroupIds()).containsOnly(group.getId());
assertThat(privateProject1Authorization.isAllowAnyone()).isFalse();
@@ -116,10 +125,10 @@ public class PermissionIndexerDaoTest {
insertTestDataForProjectsAndViews();

Map<String, PermissionIndexerDao.Dto> dtos = underTest
.selectByUuids(dbClient, dbSession, asList(publicProject.uuid(), privateProject1.uuid(), privateProject2.uuid(), view1.uuid(), view2.uuid()))
.selectByUuids(dbClient, dbSession, asList(publicProject.uuid(), privateProject1.uuid(), privateProject2.uuid(), view1.uuid(), view2.uuid(), application.uuid()))
.stream()
.collect(MoreCollectors.uniqueIndex(PermissionIndexerDao.Dto::getProjectUuid, Function.identity()));
assertThat(dtos).hasSize(5);
assertThat(dtos).hasSize(6);

PermissionIndexerDao.Dto publicProjectAuthorization = dtos.get(publicProject.uuid());
isPublic(publicProjectAuthorization, PROJECT);
@@ -127,6 +136,9 @@ public class PermissionIndexerDaoTest {
PermissionIndexerDao.Dto view1Authorization = dtos.get(view1.uuid());
isPublic(view1Authorization, VIEW);

PermissionIndexerDao.Dto applicationAuthorization = dtos.get(application.uuid());
isPublic(applicationAuthorization, APP);

PermissionIndexerDao.Dto privateProject1Authorization = dtos.get(privateProject1.uuid());
assertThat(privateProject1Authorization.getGroupIds()).containsOnly(group.getId());
assertThat(privateProject1Authorization.isAllowAnyone()).isFalse();
@@ -155,7 +167,7 @@ public class PermissionIndexerDaoTest {
public void select_by_projects_with_high_number_of_projects() throws Exception {
List<String> projectUuids = new ArrayList<>();
for (int i = 0; i < 350; i++) {
ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization(), Integer.toString(i));
ComponentDto project = ComponentTesting.newPrivateProjectDto(organization, Integer.toString(i));
dbClient.componentDao().insert(dbSession, project);
projectUuids.add(project.uuid());
GroupPermissionDto dto = new GroupPermissionDto()
@@ -246,6 +258,7 @@ public class PermissionIndexerDaoTest {
userDbTester.insertProjectPermissionOnUser(user1, USER, privateProject1);
userDbTester.insertProjectPermissionOnUser(user1, USER, privateProject2);
userDbTester.insertProjectPermissionOnUser(user1, ADMIN, view1);
userDbTester.insertProjectPermissionOnUser(user1, ADMIN, application);

// user2 has USER access on privateProject1 only
userDbTester.insertProjectPermissionOnUser(user2, USER, privateProject1);
@@ -255,5 +268,6 @@ public class PermissionIndexerDaoTest {
userDbTester.insertProjectPermissionOnGroup(group, USER, privateProject1);
userDbTester.insertProjectPermissionOnGroup(group, ADMIN, privateProject1);
userDbTester.insertProjectPermissionOnGroup(group, ADMIN, view1);
userDbTester.insertProjectPermissionOnGroup(group, ADMIN, application);
}
}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java View File

@@ -79,7 +79,7 @@ public abstract class BasePermissionWsTest<A extends PermissionsWsAction> {
}

protected ResourceTypesRule newRootResourceTypes() {
return new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW);
return new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP);
}

protected PermissionUpdater newPermissionUpdater() {

+ 15
- 0
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java View File

@@ -37,6 +37,7 @@ import org.sonar.server.permission.ws.BasePermissionWsTest;
import org.sonar.server.ws.TestRequest;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.api.resources.Qualifiers.VIEW;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ORGANIZATION;
@@ -111,6 +112,20 @@ public class SetDefaultTemplateActionTest extends BasePermissionWsTest<SetDefaul
assertDefaultTemplates(organization, projectDefaultTemplate.getUuid(), template.getUuid());
}

@Test
public void fail_if_update_default_template_with_app_qualifier() throws Exception {
OrganizationDto organization = db.organizations().insert();
PermissionTemplateDto projectDefaultTemplate = db.permissionTemplates().insertTemplate(organization);
db.organizations().setDefaultTemplates(projectDefaultTemplate, null);
PermissionTemplateDto template = insertTemplate(organization);
loginAsAdmin(organization);

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Value of parameter 'qualifier' (APP) must be one of: [TRK, VW]");

newRequest(template.getUuid(), APP);
}

@Test
public void fail_if_anonymous() throws Exception {
OrganizationDto organization = db.organizations().insert();

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchActionTest.java View File

@@ -237,7 +237,7 @@ public class SearchActionTest {
public void fail_on_invalid_qualifier() throws Exception {
userSession.addPermission(ADMINISTER_QUALITY_PROFILES, db.getDefaultOrganization());
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Value of parameter 'qualifiers' (BRC) must be one of: [TRK, VW]");
expectedException.expectMessage("Value of parameter 'qualifiers' (BRC) must be one of: [TRK, VW, APP]");

call(SearchWsRequest.builder().setQualifiers(singletonList("BRC")).build());
}
@@ -267,7 +267,7 @@ public class SearchActionTest {
WebService.Param qualifierParam = action.param("qualifiers");
assertThat(qualifierParam.isRequired()).isFalse();
assertThat(qualifierParam.description()).isEqualTo("Comma-separated list of component qualifiers. Filter the results with the specified qualifiers");
assertThat(qualifierParam.possibleValues()).containsOnly("TRK", "VW");
assertThat(qualifierParam.possibleValues()).containsOnly("TRK", "VW", "APP");
assertThat(qualifierParam.defaultValue()).isEqualTo("TRK");

WebService.Param pParam = action.param("p");

+ 4
- 69
server/sonar-server/src/test/java/org/sonar/server/project/ws/UpdateVisibilityActionTest.java View File

@@ -66,6 +66,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.sonar.db.component.ComponentTesting.newProjectCopy;
import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;

public class UpdateVisibilityActionTest {
@@ -184,10 +185,10 @@ public class UpdateVisibilityActionTest {
dbTester.components().insertComponents(module, dir, file);
ComponentDto view = dbTester.components().insertView(organization);
ComponentDto subView = ComponentTesting.newSubView(view);
ComponentDto projectCopy = ComponentTesting.newProjectCopy("foo", project, subView);
ComponentDto projectCopy = newProjectCopy("foo", project, subView);
dbTester.components().insertComponents(subView, projectCopy);

Stream.of(module, dir, file, subView, projectCopy)
Stream.of(module, dir, file, view, subView, projectCopy)
.forEach(nonRootComponent -> {
request.setParam(PARAM_PROJECT, nonRootComponent.key())
.setParam(PARAM_VISIBILITY, randomVisibility);
@@ -196,7 +197,7 @@ public class UpdateVisibilityActionTest {
request.execute();
fail("a BadRequestException should have been raised");
} catch (BadRequestException e) {
assertThat(e.getMessage()).isEqualTo("Component must either be a project or a view");
assertThat(e.getMessage()).isEqualTo("Component must be a project");
}
});
}
@@ -295,43 +296,6 @@ public class UpdateVisibilityActionTest {
assertThat(isPrivateInDb(file)).isEqualTo(!initiallyPrivate);
}

@Test
public void execute_has_no_effect_when_changing_a_view_to_public() {
OrganizationDto organization = dbTester.organizations().insert();
ComponentDto project = randomPublicOrPrivateProject();
ComponentDto view = dbTester.components().insertView(organization);
ComponentDto subView = ComponentTesting.newSubView(view);
ComponentDto projectCopy = ComponentTesting.newProjectCopy("foo", project, subView);
dbTester.components().insertComponents(subView, projectCopy);
userSessionRule.addProjectPermission(UserRole.ADMIN, view);

request.setParam(PARAM_PROJECT, view.key())
.setParam(PARAM_VISIBILITY, PUBLIC)
.execute();

assertThat(isPrivateInDb(view)).isEqualTo(false);
assertThat(isPrivateInDb(subView)).isEqualTo(false);
assertThat(isPrivateInDb(projectCopy)).isEqualTo(false);
}

@Test
public void execute_fails_with_BadRequestException_when_changing_a_view_to_private() {
OrganizationDto organization = dbTester.organizations().insert();
ComponentDto project = randomPublicOrPrivateProject();
ComponentDto view = dbTester.components().insertView(organization);
ComponentDto subView = ComponentTesting.newSubView(view);
ComponentDto projectCopy = ComponentTesting.newProjectCopy("foo", project, subView);
dbTester.components().insertComponents(subView, projectCopy);
userSessionRule.addProjectPermission(UserRole.ADMIN, view);
TestRequest request = this.request.setParam(PARAM_PROJECT, view.key())
.setParam(PARAM_VISIBILITY, PRIVATE);

expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Views can't be made private");

request.execute();
}

@Test
public void execute_has_no_effect_if_specified_project_already_has_specified_visibility() {
ComponentDto project = randomPublicOrPrivateProject();
@@ -420,22 +384,6 @@ public class UpdateVisibilityActionTest {
verifyStillHasAllPermissions(project, user, group);
}

@Test
public void execute_does_not_delete_permissions_USER_and_BROWSE_of_specified_view_when_making_it_public() {
OrganizationDto organization = dbTester.organizations().insert();
ComponentDto view = dbTester.components().insertView(organization);
UserDto user = dbTester.users().insertUser();
GroupDto group = dbTester.users().insertGroup(organization);
unsafeGiveAllPermissionsToRootComponent(view, user, group, organization);
userSessionRule.addProjectPermission(UserRole.ADMIN, view);

request.setParam(PARAM_PROJECT, view.key())
.setParam(PARAM_VISIBILITY, PUBLIC)
.execute();

verifyStillHasAllPermissions(view, user, group);
}

@Test
public void execute_updates_permission_of_specified_project_in_indexes_when_changing_visibility() {
ComponentDto project = randomPublicOrPrivateProject();
@@ -462,19 +410,6 @@ public class UpdateVisibilityActionTest {
assertThat(projectIndexers.hasBeenCalled(project.uuid())).isFalse();
}

@Test
public void execute_does_not_update_permission_of_specified_view_in_indexes_when_making_it_public() {
OrganizationDto organization = dbTester.organizations().insert();
ComponentDto view = dbTester.components().insertView(organization);
userSessionRule.addProjectPermission(UserRole.ADMIN, view);

request.setParam(PARAM_PROJECT, view.key())
.setParam(PARAM_VISIBILITY, PUBLIC)
.execute();

assertThat(projectIndexers.hasBeenCalled(view.uuid())).isFalse();
}

@Test
public void execute_grants_USER_and_CODEVIEWER_permissions_to_any_user_with_at_least_one_permission_when_making_project_private() {
OrganizationDto organization = dbTester.organizations().insert();

Loading…
Cancel
Save