From: Teryk Bellahsene Date: Thu, 20 Jul 2017 13:26:03 +0000 (+0200) Subject: SONAR-9551 Web services handles APP qualifier X-Git-Tag: 6.6-RC1~795 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cab800cc17d507d7e64518556fed781bdbcaa549;p=sonarqube.git SONAR-9551 Web services handles APP qualifier --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java index 2e034f91dae..1a573ad89a5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java @@ -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 POSSIBLE_QUALIFIERS = ImmutableList.of(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV", Qualifiers.MODULE); + private static final List POSSIBLE_QUALIFIERS = ImmutableList.of(Qualifiers.PROJECT, Qualifiers.APP, Qualifiers.VIEW, "DEV", Qualifiers.MODULE); private final UserSession userSession; private final DbClient dbClient; diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java index eec80dc60e8..d7bf90d0e2e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java @@ -40,7 +40,7 @@ class ComponentDtoToWsComponent { /** * The concept of "visibility" will only be configured for these qualifiers. */ - private static final Set QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW); + private static final Set QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP); private ComponentDtoToWsComponent() { // prevent instantiation diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionCategory.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionCategory.java index a4fd5e5c9e9..8c177983acc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionCategory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionCategory.java @@ -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), diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java index 00df270a275..b770207aa55 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java @@ -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) diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java index 6c95b348096..b988c3d65c7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java @@ -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 viewOrSubViewUuids) { - List filteredViewUuids = new ArrayList<>(); - for (String viewUuid : viewOrSubViewUuids) { - if (userSession.hasComponentUuidPermission(UserRole.USER, viewUuid)) { - filteredViewUuids.add(viewUuid); - } - } + List filteredViewUuids = viewOrSubViewUuids.stream() + .filter(uuid -> userSession.hasComponentUuidPermission(UserRole.USER, uuid)) + .collect(Collectors.toList()); + if (filteredViewUuids.isEmpty()) { filteredViewUuids.add(UNKNOWN); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java index 6c216afb214..cba61152db2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java @@ -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 ALLOWED_QUALIFIERS = ImmutableSet.of(PROJECT, VIEW, SUBVIEW); + private static final Set ALLOWED_QUALIFIERS = ImmutableSet.of(PROJECT, APP, VIEW, SUBVIEW); private final UserSession userSession; private final DbClient dbClient; diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java b/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java index 3f7f5951896..e49d5a9b784 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexerDao.java @@ -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} " + diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java index f1159aeade5..a07dfe369f7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java @@ -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.
" + + "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.
" + - "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(); 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 357c1148185..49eca0a59ff 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 @@ -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); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchAction.java index 9db9df75b8b..2fa5a29ad94 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchAction.java @@ -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); diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java index 95fb26c20e3..709ae53305f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java @@ -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 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.
" + - "Requires 'Project administer' permission on the specified project or view") + .setDescription("Updates visibility of a project.
" + + "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(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java index 51076887c27..7766954c992 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java @@ -63,7 +63,7 @@ public class SettingValidations { }; } - private static final Set SUPPORTED_QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.MODULE, Qualifiers.SUBVIEW); + private static final Set SUPPORTED_QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP, Qualifiers.MODULE, Qualifiers.SUBVIEW); public Consumer qualifier() { return data -> { diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java index 2f216ef4e4b..e976aecd5e0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java @@ -82,7 +82,7 @@ public class ComponentAction implements NavigationWsAction { /** * The concept of "visibility" will only be configured for these qualifiers. */ - private static final Set QUALIFIERS_WITH_VISIBILITY = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW); + private static final Set 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()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/WsParameterBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/ws/WsParameterBuilder.java index 30650111064..d1cae3abacf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ws/WsParameterBuilder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ws/WsParameterBuilder.java @@ -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 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 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 getDefaultTemplateQualifiers(ResourceTypes resourceTypes) { + return resourceTypes.getRoots().stream() + .map(ResourceType::getQualifier) + .filter(q -> !Qualifiers.APP.equals(q)) + .collect(Collectors.toCollection(TreeSet::new)); } private static Set 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 { - 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; diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/components-example-suggestions.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/components-example-suggestions.json deleted file mode 100644 index 9bcb023e561..00000000000 --- a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/components-example-suggestions.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "results": [ - { - "q": "VW", - "items": [], - "more": 0 - }, - { - "q": "SVW", - "items": [], - "more": 0 - }, - { - "q": "TRK", - "items": [ - { - "key": "org.sonarsource:sonarqube", - "name": "SonarSource :: SonarQube", - "match": "SonarSource :: SonarQube", - "organization": "default-organization", - "project": "", - "isRecentlyBrowsed": true, - "isFavorite": false - }, - { - "key": "org.sonarsource:sonarlint", - "name": "SonarSource :: SonarLint", - "match": "SonarSource :: SonarLint", - "organization": "default-organization", - "project": "", - "isRecentlyBrowsed": false, - "isFavorite": false - } - ], - "more": 0 - }, - { - "q": "BRC", - "items": [], - "more": 0 - }, - { - "q": "FIL", - "items": [], - "more": 0 - }, - { - "q": "UTS", - "items": [], - "more": 0 - } - ], - "organizations": [ - { - "key": "default-organization", - "name": "Default Organization" - } - ], - "projects": [ - ] -} diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/suggestions-example.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/suggestions-example.json new file mode 100644 index 00000000000..3c7bbd44454 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/suggestions-example.json @@ -0,0 +1,66 @@ +{ + "results": [ + { + "q": "VW", + "items": [], + "more": 0 + }, + { + "q": "SVW", + "items": [], + "more": 0 + }, + { + "q": "APP", + "items": [], + "more": 0 + }, + { + "q": "TRK", + "items": [ + { + "key": "org.sonarsource:sonarqube", + "name": "SonarSource :: SonarQube", + "match": "SonarSource :: SonarQube", + "organization": "default-organization", + "project": "", + "isRecentlyBrowsed": true, + "isFavorite": false + }, + { + "key": "org.sonarsource:sonarlint", + "name": "SonarSource :: SonarLint", + "match": "SonarSource :: SonarLint", + "organization": "default-organization", + "project": "", + "isRecentlyBrowsed": false, + "isFavorite": false + } + ], + "more": 0 + }, + { + "q": "BRC", + "items": [], + "more": 0 + }, + { + "q": "FIL", + "items": [], + "more": 0 + }, + { + "q": "UTS", + "items": [], + "more": 0 + } + ], + "organizations": [ + { + "key": "default-organization", + "name": "Default Organization" + } + ], + "projects": [ + ] +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java index 37718679766..b15d1053439 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java @@ -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}, diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java index 07aa4ea77a5..4cca6f805ac 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java @@ -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(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java index 46e6fb57617..d5d95abdbfa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java @@ -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 diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java index c0c6518f4ce..b7caf99fd1a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java @@ -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); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java index 8b15aa45dc6..3e5302a2fdd 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java @@ -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 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")); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java index 117e38fe396..920e4f78d38 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java @@ -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> arg = (ArgumentCaptor>) ((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 diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java index 407ad0eb6c5..601f4740a47 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java @@ -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 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 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 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); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java index cbc6023290f..a4757a8719f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java @@ -79,7 +79,7 @@ public abstract class BasePermissionWsTest { } protected ResourceTypesRule newRootResourceTypes() { - return new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW); + return new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.APP); } protected PermissionUpdater newPermissionUpdater() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java index 18387a30750..b22c1c0449b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java @@ -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 { 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();