diff options
9 files changed, 94 insertions, 40 deletions
diff --git a/it/it-tests/src/test/java/it/issue/IssueSearchTest.java b/it/it-tests/src/test/java/it/issue/IssueSearchTest.java index 2c9e187d271..59b509effe6 100644 --- a/it/it-tests/src/test/java/it/issue/IssueSearchTest.java +++ b/it/it-tests/src/test/java/it/issue/IssueSearchTest.java @@ -41,7 +41,6 @@ import org.sonar.wsclient.component.Component; import org.sonar.wsclient.issue.Issue; import org.sonar.wsclient.issue.IssueQuery; import org.sonar.wsclient.issue.Issues; -import org.sonar.wsclient.issue.NewIssue; import org.sonarqube.ws.Common; import org.sonarqube.ws.MediaTypes; import org.sonarqube.ws.client.GetRequest; @@ -191,7 +190,7 @@ public class IssueSearchTest extends AbstractIssueTest { search(IssueQuery.create().createdBefore(past).createdAfter(today)).list(); Fail.fail("Expecting 400 from issues search WS"); } catch (HttpException exception) { - assertThat(exception.getMessage()).contains("Start bound cannot be larger than end bound"); + assertThat(exception.getMessage()).contains("Start bound cannot be larger or equal to end bound"); } } 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 8ab38f7c912..2a40aa7308b 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 @@ -166,9 +166,10 @@ public class ActivityAction implements CeWsAction { // if a task searched by uuid is found all other parameters are ignored Optional<WsCe.Task> taskSearchedById = searchTaskByUuid(dbSession, request); if (taskSearchedById.isPresent()) { + userSession.checkComponentUuidPermission(UserRole.ADMIN, taskSearchedById.get().getComponentId()); return buildResponse( singletonList(taskSearchedById.get()), - Collections.<WsCe.Task>emptyList(), + Collections.emptyList(), request.getPageSize()); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 6f16aab83b5..24289e2b7b0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -370,8 +370,8 @@ public class IssueIndex extends BaseIndex { private void validateCreationDateBounds(Date createdBefore, Date createdAfter) { Preconditions.checkArgument(createdAfter == null || createdAfter.before(new Date(system.now())), "Start bound cannot be in the future"); - Preconditions.checkArgument(createdAfter == null || createdAfter.equals(createdBefore) || createdBefore == null || createdAfter.before(createdBefore), - "Start bound cannot be larger than end bound"); + Preconditions.checkArgument(createdAfter == null || createdBefore == null || createdAfter.before(createdBefore), + "Start bound cannot be larger or equal to end bound"); } private void configureStickyFacets(IssueQuery query, SearchOptions options, Map<String, QueryBuilder> filters, QueryBuilder esQuery, SearchRequestBuilder esSearch) { 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 da181306d87..246d6018109 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 @@ -65,8 +65,10 @@ import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.db.component.ComponentTesting.newDeveloper; import static org.sonar.db.component.ComponentTesting.newProjectDto; 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; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_STATUS; +import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_TYPE; public class ActivityActionTest { @@ -92,7 +94,7 @@ public class ActivityActionTest { @Test public void get_all_past_activity() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "PROJECT_2", CeActivityDto.Status.FAILED); @@ -115,7 +117,7 @@ public class ActivityActionTest { @Test public void filter_by_status() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "PROJECT_2", CeActivityDto.Status.FAILED); insertQueue("T3", "PROJECT_1", CeQueueDto.Status.IN_PROGRESS); @@ -130,7 +132,7 @@ public class ActivityActionTest { @Test public void filter_by_max_executed_at_exclude() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "PROJECT_2", CeActivityDto.Status.FAILED); insertQueue("T3", "PROJECT_1", CeQueueDto.Status.IN_PROGRESS); @@ -144,10 +146,9 @@ public class ActivityActionTest { @Test public void filter_by_max_executed_at_include_day_filled() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); String today = formatDate(new Date(EXECUTED_AT)); - System.out.println(EXECUTED_AT + " - " + today); ActivityResponse activityResponse = call(ws.newRequest() .setParam(CeWsParameters.PARAM_MAX_EXECUTED_AT, today)); @@ -157,7 +158,7 @@ public class ActivityActionTest { @Test public void filter_on_current_activities() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); // T2 is the current activity (the most recent one) insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "PROJECT_1", CeActivityDto.Status.FAILED); @@ -173,7 +174,7 @@ public class ActivityActionTest { @Test public void limit_results() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "PROJECT_2", CeActivityDto.Status.FAILED); insertQueue("T3", "PROJECT_1", CeQueueDto.Status.IN_PROGRESS); @@ -221,7 +222,7 @@ public class ActivityActionTest { componentDb.insertProjectAndSnapshot(eclipse); dbTester.commit(); componentDb.indexComponents(struts.getId(), zookeeper.getId(), eclipse.getId()); - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "P1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "P2", CeActivityDto.Status.SUCCESS); insertActivity("T3", "P3", CeActivityDto.Status.SUCCESS); @@ -238,7 +239,7 @@ public class ActivityActionTest { componentDb.insertDeveloperAndSnapshot(developer); componentDb.insertViewAndSnapshot(apacheView); componentDb.indexComponents(developer.getId(), apacheView.getId()); - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); insertActivity("T1", "D1", CeActivityDto.Status.SUCCESS); insertActivity("T2", "V1", CeActivityDto.Status.SUCCESS); @@ -249,6 +250,7 @@ public class ActivityActionTest { @Test public void search_task_id_in_queue_ignoring_other_parameters() throws IOException { + globalAdmin(); insertQueue("T1", "PROJECT_1", CeQueueDto.Status.IN_PROGRESS); ActivityResponse result = call( @@ -262,6 +264,7 @@ public class ActivityActionTest { @Test public void search_task_id_in_activity() { + globalAdmin(); insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); ActivityResponse result = call(ws.newRequest().setParam(Param.TEXT_QUERY, "T1")); @@ -271,6 +274,31 @@ public class ActivityActionTest { } @Test + public void search_task_id_as_project_admin() { + insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); + userSession.login().addProjectUuidPermissions(UserRole.ADMIN, "PROJECT_1"); + + ActivityResponse result = call(ws.newRequest().setParam(Param.TEXT_QUERY, "T1")); + + assertThat(result.getTasksCount()).isEqualTo(1); + assertThat(result.getTasks(0).getId()).isEqualTo("T1"); + } + + @Test + public void search_task_by_component_uuid() { + insertQueue("T1", "PROJECT_1", CeQueueDto.Status.IN_PROGRESS); + insertActivity("T1", "PROJECT_1", CeActivityDto.Status.SUCCESS); + globalAdmin(); + + ActivityResponse result = call(ws.newRequest() + .setParam(PARAM_COMPONENT_ID, "PROJECT_1") + .setParam(PARAM_TYPE, CeTaskTypes.REPORT) + .setParam(PARAM_STATUS, "SUCCESS,FAILED,CANCELED,IN_PROGRESS,PENDING")); + + assertThat(result.getTasksCount()).isEqualTo(2); + } + + @Test public void fail_if_both_filters_on_component_id_and_name() { expectedException.expect(BadRequestException.class); expectedException.expectMessage("componentId and componentQuery must not be set at the same time"); @@ -304,7 +332,7 @@ public class ActivityActionTest { @Test public void support_json_response() { - userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + globalAdmin(); TestResponse wsResponse = ws.newRequest() .setMediaType(MediaTypes.JSON) .execute(); @@ -312,6 +340,10 @@ public class ActivityActionTest { JsonAssert.assertJson(wsResponse.getInput()).isSimilarTo("{\"tasks\":[]}"); } + private void globalAdmin() { + userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + } + private CeQueueDto insertQueue(String taskUuid, String componentUuid, CeQueueDto.Status status) { CeQueueDto queueDto = new CeQueueDto(); queueDto.setTaskType(CeTaskTypes.REPORT); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java index a715a73e761..b26b0285722 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java @@ -33,6 +33,7 @@ import org.elasticsearch.test.ESTestCase; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.sonar.api.config.Settings; import org.sonar.api.issue.Issue; import org.sonar.api.resources.Scopes; @@ -71,6 +72,8 @@ public class IssueIndexTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); IssueIndex underTest; @@ -202,18 +205,21 @@ public class IssueIndexTest { IssueTesting.newDoc("ISSUE2", file)); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(file.uuid())).build(), new SearchOptions()).getDocs()) - .isEmpty(); + underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(file.uuid())).build(), new SearchOptions()) + .getDocs()) + .isEmpty(); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(module.uuid())).build(), new SearchOptions()).getDocs()) - .hasSize(1); + underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(module.uuid())).build(), new SearchOptions()) + .getDocs()) + .hasSize(1); assertThat( underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()) .getDocs()) .hasSize(2); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(project.uuid())).build(), new SearchOptions()).getDocs()) - .isEmpty(); + underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(project.uuid())).build(), new SearchOptions()) + .getDocs()) + .isEmpty(); assertThat( underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()) .isEmpty(); @@ -399,7 +405,8 @@ public class IssueIndexTest { IssueTesting.newDoc("ISSUE1", file).setStatus(Issue.STATUS_CLOSED), IssueTesting.newDoc("ISSUE2", file).setStatus(Issue.STATUS_OPEN)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CLOSED, Issue.STATUS_OPEN)).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CLOSED, Issue.STATUS_OPEN)).build(), new SearchOptions()).getDocs()) + .hasSize(2); assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CLOSED)).build(), new SearchOptions()).getDocs()).hasSize(1); assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CONFIRMED)).build(), new SearchOptions()).getDocs()).isEmpty(); } @@ -429,8 +436,9 @@ public class IssueIndexTest { IssueTesting.newDoc("ISSUE2", file).setResolution(Issue.RESOLUTION_FIXED)); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_FIXED)).build(), new SearchOptions()).getDocs()) - .hasSize(2); + underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_FIXED)).build(), new SearchOptions()) + .getDocs()) + .hasSize(2); assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE)).build(), new SearchOptions()).getDocs()).hasSize(1); assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_REMOVED)).build(), new SearchOptions()).getDocs()).isEmpty(); } @@ -668,10 +676,11 @@ public class IssueIndexTest { .createdAfter(parseDate("2014-09-19")).createdBefore(parseDate("2014-09-21")) .build(), new SearchOptions()).getDocs()).hasSize(1); - // 20 < createdAt < 20: nothing - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + // 20 < createdAt < 20: exception + expectedException.expect(IllegalArgumentException.class); + underTest.search(IssueQuery.builder(userSessionRule) .createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-20")) - .build(), new SearchOptions()).getDocs()).isEmpty(); + .build(), new SearchOptions()).getDocs(); } @Test @@ -699,11 +708,19 @@ public class IssueIndexTest { new SearchOptions()); Fail.failBecauseExceptionWasNotThrown(IllegalArgumentException.class); } catch (IllegalArgumentException exception) { - assertThat(exception.getMessage()).isEqualTo("Start bound cannot be larger than end bound"); + assertThat(exception.getMessage()).isEqualTo("Start bound cannot be larger or equal to end bound"); } } @Test + public void fail_if_created_before_equals_created_after() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Start bound cannot be larger or equal to end bound"); + + underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-20")).build(), new SearchOptions()); + } + + @Test public void filter_by_created_after_must_not_be_in_future() { try { underTest.search(IssueQuery.builder(userSessionRule).createdAfter(new Date(Long.MAX_VALUE)).build(), new SearchOptions()); @@ -804,8 +821,8 @@ public class IssueIndexTest { SearchOptions SearchOptions = fixtureForCreatedAtFacet(); Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) - .createdAfter(parseDateTime("2014-09-01T00:00:00-0100")) - .createdBefore(parseDateTime("2014-09-02T00:00:00-0100")).build(), + .createdAfter(parseDateTime("2014-09-01T00:00:00-0100")) + .createdBefore(parseDateTime("2014-09-02T00:00:00-0100")).build(), SearchOptions).getFacets().get("createdAt"); assertThat(createdAt).containsOnly( entry("2014-09-01T01:00:00+0000", 2L)); diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeTaskQuery.java b/sonar-db/src/main/java/org/sonar/db/ce/CeTaskQuery.java index 17862ce6996..69b67d76ec9 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeTaskQuery.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeTaskQuery.java @@ -19,12 +19,13 @@ */ package org.sonar.db.ce; +import java.util.ArrayList; import java.util.List; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.db.DatabaseUtils; -import static java.util.Collections.singletonList; +import static com.google.common.collect.Lists.newArrayList; /** * Db Query used for CE_QUEUE and CE_ACTIVITY tables @@ -34,8 +35,9 @@ public class CeTaskQuery { public static final int MAX_COMPONENT_UUIDS = DatabaseUtils.PARTITION_SIZE_FOR_ORACLE; private boolean onlyCurrents = false; - private List<String> componentUuids; - private List<String> statuses; + // SONAR-7681 a public implementation of List must be used in MyBatis - potential concurrency exceptions otherwise + private ArrayList<String> componentUuids; + private ArrayList<String> statuses; private String type; private Long minSubmittedAt; private Long maxExecutedAt; @@ -46,7 +48,7 @@ public class CeTaskQuery { } public CeTaskQuery setComponentUuids(@Nullable List<String> l) { - this.componentUuids = l; + this.componentUuids = l == null ? null : newArrayList(l); return this; } @@ -58,7 +60,7 @@ public class CeTaskQuery { if (s == null) { this.componentUuids = null; } else { - this.componentUuids = singletonList(s); + this.componentUuids = newArrayList(s); } return this; } @@ -78,7 +80,7 @@ public class CeTaskQuery { } public CeTaskQuery setStatuses(@Nullable List<String> statuses) { - this.statuses = statuses; + this.statuses = statuses == null ? null : newArrayList(statuses); return this; } diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentTreeQuery.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentTreeQuery.java index 9b556abf99b..d7f1dee8746 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ComponentTreeQuery.java +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentTreeQuery.java @@ -21,6 +21,7 @@ package org.sonar.db.component; import com.google.common.base.Function; import com.google.common.base.Joiner; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -31,6 +32,7 @@ import org.sonar.db.WildcardPosition; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.FluentIterable.from; +import static com.google.common.collect.Lists.newArrayList; import static java.util.Objects.requireNonNull; import static org.sonar.db.DatabaseUtils.buildLikeValue; import static org.sonar.db.WildcardPosition.AFTER; @@ -38,8 +40,9 @@ import static org.sonar.db.WildcardPosition.AFTER; public class ComponentTreeQuery { @CheckForNull private final String nameOrKeyQuery; + // SONAR-7681 a public implementation of List must be used in MyBatis - potential concurrency exceptions otherwise @CheckForNull - private final Collection<String> qualifiers; + private final ArrayList<String> qualifiers; @CheckForNull private final Integer page; @CheckForNull @@ -51,7 +54,7 @@ public class ComponentTreeQuery { private ComponentTreeQuery(Builder builder) { this.nameOrKeyQuery = builder.nameOrKeyQuery; - this.qualifiers = builder.qualifiers; + this.qualifiers = builder.qualifiers == null ? null : newArrayList(builder.qualifiers); this.page = builder.page; this.pageSize = builder.pageSize; this.baseSnapshot = builder.baseSnapshot; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java index 659f5c6e948..fc010d2271f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java @@ -19,7 +19,6 @@ */ package org.sonar.api; -import com.google.common.annotations.Beta; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -83,7 +82,6 @@ import static java.util.Objects.requireNonNull; * * @since 5.5 */ -@Beta public interface Plugin { class Context { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarPlugin.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarPlugin.java index a44838b745d..b49cf73a07b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarPlugin.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarPlugin.java @@ -28,7 +28,9 @@ import java.util.List; * This property is automatically set by sonar-packaging-maven-plugin when building plugin. * * @since 2.8 + * @deprecated replaced by {@link Plugin} in version 5.6. */ +@Deprecated public abstract class SonarPlugin implements Plugin { /** |