package org.sonar.db.webhook;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import org.apache.ibatis.session.RowBounds;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+
public class WebhookDeliveryDao implements Dao {
public Optional<WebhookDeliveryDto> selectByUuid(DbSession dbSession, String uuid) {
mapper(dbSession).deleteComponentBeforeDate(componentUuid, beforeDate);
}
+ public Map<String, WebhookDeliveryLiteDto> selectLatestDeliveries(DbSession dbSession, List<WebhookDto> webhooks) {
+ return webhooks.stream()
+ .flatMap(webhook -> selectByWebhookUuid(dbSession, webhook.getUuid(),0,1).stream())
+ .collect(toMap(WebhookDeliveryLiteDto::getWebhookUuid, identity()));
+ }
+
private static WebhookDeliveryMapper mapper(DbSession dbSession) {
return dbSession.getMapper(WebhookDeliveryMapper.class);
}
import org.sonar.db.user.RootFlagAssertions;
import org.sonar.db.user.UserDbTester;
import org.sonar.db.webhook.WebhookDbTester;
+import org.sonar.db.webhook.WebhookDeliveryDbTester;
import static com.google.common.base.Preconditions.checkState;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
private final FileSourceTester fileSourceTester;
private final PluginDbTester pluginDbTester;
private final WebhookDbTester webhookDbTester;
+ private final WebhookDeliveryDbTester webhookDeliveryDbTester;
public DbTester(System2 system2, @Nullable String schemaPath) {
super(TestDb.create(schemaPath));
this.fileSourceTester = new FileSourceTester(this);
this.pluginDbTester = new PluginDbTester(this);
this.webhookDbTester = new WebhookDbTester(this);
+ this.webhookDeliveryDbTester = new WebhookDeliveryDbTester(this);
}
public static DbTester create() {
return webhookDbTester;
}
+ public WebhookDeliveryDbTester webhookDelivery() {
+ return webhookDeliveryDbTester;
+ }
+
@Override
protected void after() {
if (session != null) {
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newProjectCopy;
-import static org.sonar.db.webhook.WebhookDbTesting.newWebhookDeliveryDto;
+import static org.sonar.db.webhook.WebhookDbTesting.newDto;
import static org.sonar.db.webhook.WebhookDbTesting.selectAllDeliveryUuids;
public class PurgeDaoTest {
@Test
public void deleteProject_deletes_webhook_deliveries() {
ComponentDto project = dbTester.components().insertPublicProject();
- dbClient.webhookDeliveryDao().insert(dbSession, newWebhookDeliveryDto().setComponentUuid(project.uuid()).setUuid("D1"));
- dbClient.webhookDeliveryDao().insert(dbSession, newWebhookDeliveryDto().setComponentUuid("P2").setUuid("D2"));
+ dbClient.webhookDeliveryDao().insert(dbSession, newDto().setComponentUuid(project.uuid()).setUuid("D1"));
+ dbClient.webhookDeliveryDao().insert(dbSession, newDto().setComponentUuid("P2").setUuid("D2"));
underTest.deleteProject(dbSession, project.uuid());
// only statics
}
- public static WebhookDeliveryDto newWebhookDeliveryDto() {
+ /**
+ * Build a {@link WebhookDeliveryDto} with all mandatory fields.
+ * Optional fields are kept null.
+ */
+ public static WebhookDeliveryDto newDto(String uuid, String webhookUuid, String componentUuid, String ceTaskUuid) {
+ return newDto()
+ .setUuid(uuid)
+ .setWebhookUuid(webhookUuid)
+ .setComponentUuid(componentUuid)
+ .setCeTaskUuid(ceTaskUuid);
+ }
+
+ public static WebhookDeliveryDto newDto() {
return new WebhookDeliveryDto()
.setUuid(randomAlphanumeric(40))
.setComponentUuid(randomAlphanumeric(40))
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import static com.google.common.collect.ImmutableList.of;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.webhook.WebhookDbTesting.newWebhookDeliveryDto;
+import static org.sonar.db.webhook.WebhookTesting.newProjectWebhook;
public class WebhookDeliveryDaoTest {
@Test
public void selectOrderedByComponentUuid_returns_empty_if_no_records() {
- underTest.insert(dbSession, newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1"));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1"));
List<WebhookDeliveryLiteDto> deliveries = underTest.selectOrderedByComponentUuid(dbSession, "ANOTHER_COMPONENT", 0, 10);
@Test
public void selectOrderedByComponentUuid_returns_records_ordered_by_date() {
- WebhookDeliveryDto dto1 = newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
- WebhookDeliveryDto dto2 = newDto("D2", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(NOW);
- WebhookDeliveryDto dto3 = newDto("D3", "WEBHOOK_UUID_1", "COMPONENT_2", "TASK_1").setCreatedAt(NOW);
+ WebhookDeliveryDto dto1 = WebhookDbTesting.newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
+ WebhookDeliveryDto dto2 = WebhookDbTesting.newDto("D2", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(NOW);
+ WebhookDeliveryDto dto3 = WebhookDbTesting.newDto("D3", "WEBHOOK_UUID_1", "COMPONENT_2", "TASK_1").setCreatedAt(NOW);
underTest.insert(dbSession, dto3);
underTest.insert(dbSession, dto2);
underTest.insert(dbSession, dto1);
@Test
public void selectOrderedByCeTaskUuid_returns_empty_if_no_records() {
- underTest.insert(dbSession, newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1"));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1"));
List<WebhookDeliveryLiteDto> deliveries = underTest.selectOrderedByCeTaskUuid(dbSession, "ANOTHER_TASK", 0, 10);
@Test
public void selectOrderedByCeTaskUuid_returns_records_ordered_by_date() {
- WebhookDeliveryDto dto1 = newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
- WebhookDeliveryDto dto2 = newDto("D2", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(NOW);
- WebhookDeliveryDto dto3 = newDto("D3", "WEBHOOK_UUID_1", "COMPONENT_2", "TASK_2").setCreatedAt(NOW);
+ WebhookDeliveryDto dto1 = WebhookDbTesting.newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
+ WebhookDeliveryDto dto2 = WebhookDbTesting.newDto("D2", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(NOW);
+ WebhookDeliveryDto dto3 = WebhookDbTesting.newDto("D3", "WEBHOOK_UUID_1", "COMPONENT_2", "TASK_2").setCreatedAt(NOW);
underTest.insert(dbSession, dto3);
underTest.insert(dbSession, dto2);
underTest.insert(dbSession, dto1);
@Test
public void selectByWebhookUuid_returns_empty_if_no_records() {
- underTest.insert(dbSession, newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1"));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1"));
List<WebhookDeliveryLiteDto> deliveries = underTest.selectByWebhookUuid(dbSession, "a-webhook-uuid", 0, 10);
@Test
public void selectByWebhookUuid_returns_records_ordered_by_date() {
WebhookDto webhookDto = dbWebhooks.insert(WebhookTesting.newProjectWebhook("COMPONENT_1"));
- WebhookDeliveryDto dto1 = newDto("D1", webhookDto.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
- WebhookDeliveryDto dto2 = newDto("D2", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW);
- WebhookDeliveryDto dto3 = newDto("D3", "fake-webhook-uuid", "COMPONENT_2", "TASK_1").setCreatedAt(NOW);
+ WebhookDeliveryDto dto1 = WebhookDbTesting.newDto("D1", webhookDto.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
+ WebhookDeliveryDto dto2 = WebhookDbTesting.newDto("D2", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW);
+ WebhookDeliveryDto dto3 = WebhookDbTesting.newDto("D3", "fake-webhook-uuid", "COMPONENT_2", "TASK_1").setCreatedAt(NOW);
underTest.insert(dbSession, dto3);
underTest.insert(dbSession, dto2);
underTest.insert(dbSession, dto1);
@Test
public void selectByWebhookUuid_returns_records_according_to_pagination() {
WebhookDto webhookDto = dbWebhooks.insert(WebhookTesting.newProjectWebhook("COMPONENT_1"));
- WebhookDeliveryDto dto1 = newDto("D1", webhookDto.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE);
- underTest.insert(dbSession, dto1);
- WebhookDeliveryDto dto2 = newDto("D2", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW);
- underTest.insert(dbSession, dto2);
- underTest.insert(dbSession, newDto("D3", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
- underTest.insert(dbSession, newDto("D4", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
- underTest.insert(dbSession, newDto("D5", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
- underTest.insert(dbSession, newDto("D6", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D1", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW - 5_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D2", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW - 4_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D3", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW - 3_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D4", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW - 2_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D5", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW - 1_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("D6", webhookDto.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
- List<WebhookDeliveryLiteDto> deliveries = underTest.selectByWebhookUuid(dbSession, webhookDto.getUuid(), 1, 3);
+ List<WebhookDeliveryLiteDto> deliveries = underTest.selectByWebhookUuid(dbSession, webhookDto.getUuid(), 2, 2);
- assertThat(deliveries).extracting(WebhookDeliveryLiteDto::getUuid).containsExactlyInAnyOrder("D3", "D4", "D5");
+ assertThat(deliveries).extracting(WebhookDeliveryLiteDto::getUuid).containsExactly("D4", "D3");
}
+ @Test
+ public void selectLatestDelivery_of_a_webhook() {
+ WebhookDto webhook1 = dbWebhooks.insert(newProjectWebhook("COMPONENT_1"));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("WH1-DELIVERY-1-UUID", webhook1.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("WH1-DELIVERY-2-UUID", webhook1.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
+
+ WebhookDto webhook2 = dbWebhooks.insert(newProjectWebhook("COMPONENT_1"));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("WH2-DELIVERY-1-UUID", webhook2.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("WH2-DELIVERY-2-UUID", webhook2.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
+
+ Map<String, WebhookDeliveryLiteDto> map = underTest.selectLatestDeliveries(dbSession, of(webhook1, webhook2));
+ assertThat(map).containsKeys(webhook1.getUuid());
+ assertThat(map.get(webhook1.getUuid())).extracting(WebhookDeliveryLiteDto::getUuid).contains("WH1-DELIVERY-2-UUID");
+
+ assertThat(map).containsKeys(webhook2.getUuid());
+ assertThat(map.get(webhook2.getUuid())).extracting(WebhookDeliveryLiteDto::getUuid).contains("WH2-DELIVERY-2-UUID");
+ }
@Test
public void insert_row_with_only_mandatory_columns() {
- WebhookDeliveryDto dto = newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1")
+ WebhookDeliveryDto dto = WebhookDbTesting.newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1")
.setHttpStatus(null)
.setDurationMs(null)
.setErrorStacktrace(null);
@Test
public void insert_row_with_all_columns() {
- WebhookDeliveryDto dto = newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1");
+ WebhookDeliveryDto dto = WebhookDbTesting.newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1");
underTest.insert(dbSession, dto);
@Test
public void deleteComponentBeforeDate_deletes_rows_before_date() {
- underTest.insert(dbSession, newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(1_000_000L));
- underTest.insert(dbSession, newDto("DELIVERY_2", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_2").setCreatedAt(2_000_000L));
- underTest.insert(dbSession, newDto("DELIVERY_3", "WEBHOOK_UUID_1", "COMPONENT_2", "TASK_3").setCreatedAt(1_000_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(1_000_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("DELIVERY_2", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_2").setCreatedAt(2_000_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("DELIVERY_3", "WEBHOOK_UUID_1", "COMPONENT_2", "TASK_3").setCreatedAt(1_000_000L));
// should delete the old delivery on COMPONENT_1 and keep the one of COMPONENT_2
underTest.deleteComponentBeforeDate(dbSession, "COMPONENT_1", 1_500_000L);
@Test
public void deleteComponentBeforeDate_does_nothing_on_invalid_uuid() {
- underTest.insert(dbSession, newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(1_000_000L));
+ underTest.insert(dbSession, WebhookDbTesting.newDto("DELIVERY_1", "WEBHOOK_UUID_1", "COMPONENT_1", "TASK_1").setCreatedAt(1_000_000L));
underTest.deleteComponentBeforeDate(dbSession, "COMPONENT_2", 1_500_000L);
assertThat(actual.getCreatedAt()).isEqualTo(expected.getCreatedAt());
}
- /**
- * Build a {@link WebhookDeliveryDto} with all mandatory fields.
- * Optional fields are kept null.
- */
- private static WebhookDeliveryDto newDto(String uuid, String webhookUuid, String componentUuid, String ceTaskUuid) {
- return newWebhookDeliveryDto()
- .setUuid(uuid)
- .setWebhookUuid(webhookUuid)
- .setComponentUuid(componentUuid)
- .setCeTaskUuid(ceTaskUuid);
- }
-
private WebhookDeliveryDto selectByUuid(String uuid) {
Optional<WebhookDeliveryDto> dto = underTest.selectByUuid(dbSession, uuid);
assertThat(dto).isPresent();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.webhook;
+
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+
+public class WebhookDeliveryDbTester {
+
+ private final DbTester dbTester;
+
+ public WebhookDeliveryDbTester(DbTester dbTester) {
+ this.dbTester = dbTester;
+ }
+
+ public WebhookDeliveryLiteDto insert(WebhookDeliveryDto dto) {
+ DbSession dbSession = dbTester.getSession();
+ dbTester.getDbClient().webhookDeliveryDao().insert(dbSession, dto);
+ dbSession.commit();
+ return dto;
+ }
+
+}
*/
package org.sonar.db.webhook;
-import java.util.Calendar;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
+import java.util.Calendar;
+
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
public class WebhookTesting {
.setOrganizationUuid(organizationDto.getUuid());
}
+ public static WebhookDto newOrganizationWebhook(String name, String organizationUuid) {
+ return getWebhookDto()
+ .setName(name)
+ .setOrganizationUuid(organizationUuid);
+ }
+
private static WebhookDto getWebhookDto() {
return new WebhookDto()
.setUuid(randomAlphanumeric(40))
import java.util.List;
import java.util.Map;
import java.util.function.Function;
+import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.server.platform.db.migration.step.DataChange;
import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProvider;
+import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
for (String value : values) {
PropertyRow name = properties.get("sonar.webhooks.project." + value + ".name");
PropertyRow url = properties.get("sonar.webhooks.project." + value + ".url");
- webhooks.add(new Webhook(name, url, null, projectUuidOf(context, name)));
+ String projectUuid = checkNotNull(projectUuidOf(context, name), "Project was not found for property : sonar.webhooks.project.%s", value);
+ webhooks.add(new Webhook(name, url, null, projectUuid));
}
return webhooks;
}
+ @CheckForNull
private static String projectUuidOf(Context context, PropertyRow row) throws SQLException {
return context
.prepareSelect("select uuid from projects where id = ?")
Request request = buildHttpRequest(webhook, payload);
try (Response response = execute(request)) {
builder.setHttpStatus(response.code());
- builder.setDurationInMs((int) (system.now() - startedAt));
}
} catch (Exception e) {
builder.setError(e);
}
- return builder.build();
+
+ return builder
+ .setDurationInMs((int) (system.now() - startedAt))
+ .build();
}
private static Request buildHttpRequest(Webhook webhook, WebhookPayload payload) {
import com.google.common.io.Resources;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.server.ws.Request;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.webhook.WebhookDeliveryLiteDto;
import org.sonar.db.webhook.WebhookDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.Webhooks.ListWsResponse.Builder;
+import org.sonarqube.ws.Webhooks;
+import org.sonarqube.ws.Webhooks.ListResponse;
+import org.sonarqube.ws.Webhooks.ListResponseElement;
import static java.util.Optional.ofNullable;
import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.LIST_ACTION;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.ORGANIZATION_KEY_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.PROJECT_KEY_PARAM;
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonar.server.ws.WsUtils.checkStateWithOptional;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
-import static org.sonarqube.ws.Webhooks.ListWsResponse.newBuilder;
public class ListAction implements WebhooksWsAction {
userSession.checkLoggedIn();
- writeResponse(request, response, doHandle(organizationKey, projectKey));
-
+ try (DbSession dbSession = dbClient.openSession(true)) {
+ List<WebhookDto> webhookDtos = doHandle(dbSession, organizationKey, projectKey);
+ Map<String, WebhookDeliveryLiteDto> lastDeliveries = loadLastDeliveriesOf(dbSession, webhookDtos);
+ writeResponse(request, response, webhookDtos, lastDeliveries);
+ }
}
- private List<WebhookDto> doHandle(@Nullable String organizationKey, @Nullable String projectKey) {
-
- try (DbSession dbSession = dbClient.openSession(true)) {
+ private Map<String, WebhookDeliveryLiteDto> loadLastDeliveriesOf(DbSession dbSession, List<WebhookDto> webhookDtos) {
+ return dbClient.webhookDeliveryDao().selectLatestDeliveries(dbSession, webhookDtos);
+ }
- OrganizationDto organizationDto;
- if (isNotBlank(organizationKey)) {
- Optional<OrganizationDto> dtoOptional = dbClient.organizationDao().selectByKey(dbSession, organizationKey);
- organizationDto = checkFoundWithOptional(dtoOptional, "No organization with key '%s'", organizationKey);
- } else {
- organizationDto = defaultOrganizationDto(dbSession);
- }
+ private List<WebhookDto> doHandle(DbSession dbSession, @Nullable String organizationKey, @Nullable String projectKey) {
- if (isNotBlank(projectKey)) {
+ OrganizationDto organizationDto;
+ if (isNotBlank(organizationKey)) {
+ Optional<OrganizationDto> dtoOptional = dbClient.organizationDao().selectByKey(dbSession, organizationKey);
+ organizationDto = checkFoundWithOptional(dtoOptional, "No organization with key '%s'", organizationKey);
+ } else {
+ organizationDto = defaultOrganizationDto(dbSession);
+ }
- Optional<ComponentDto> optional = ofNullable(dbClient.componentDao().selectByKey(dbSession, projectKey).orNull());
- ComponentDto componentDto = checkFoundWithOptional(optional, "project %s does not exist", projectKey);
- webhookSupport.checkPermission(componentDto);
- webhookSupport.checkThatProjectBelongsToOrganization(componentDto, organizationDto, "Project '%s' does not belong to organisation '%s'", projectKey, organizationKey);
- webhookSupport.checkPermission(componentDto);
- return dbClient.webhookDao().selectByProject(dbSession, componentDto);
+ if (isNotBlank(projectKey)) {
- } else {
+ Optional<ComponentDto> optional = ofNullable(dbClient.componentDao().selectByKey(dbSession, projectKey).orNull());
+ ComponentDto componentDto = checkFoundWithOptional(optional, "project %s does not exist", projectKey);
+ webhookSupport.checkPermission(componentDto);
+ webhookSupport.checkThatProjectBelongsToOrganization(componentDto, organizationDto, "Project '%s' does not belong to organisation '%s'", projectKey, organizationKey);
+ webhookSupport.checkPermission(componentDto);
+ return dbClient.webhookDao().selectByProject(dbSession, componentDto);
- webhookSupport.checkPermission(organizationDto);
- return dbClient.webhookDao().selectByOrganization(dbSession, organizationDto);
+ } else {
- }
+ webhookSupport.checkPermission(organizationDto);
+ return dbClient.webhookDao().selectByOrganization(dbSession, organizationDto);
}
- }
-
- private static void writeResponse(Request request, Response response, List<WebhookDto> webhookDtos) {
- Builder responseBuilder = newBuilder();
+ }
+ private static void writeResponse(Request request, Response response, List<WebhookDto> webhookDtos, Map<String, WebhookDeliveryLiteDto> lastDeliveries) {
+ ListResponse.Builder responseBuilder = ListResponse.newBuilder();
webhookDtos
.stream()
- .forEach(webhook -> responseBuilder.addWebhooksBuilder()
- .setKey(webhook.getUuid())
- .setName(webhook.getName())
- .setUrl(webhook.getUrl()));
-
+ .forEach(webhook -> {
+ ListResponseElement.Builder responseElementBuilder = responseBuilder.addWebhooksBuilder();
+ responseElementBuilder
+ .setKey(webhook.getUuid())
+ .setName(webhook.getName())
+ .setUrl(webhook.getUrl());
+ addLastDelivery(responseElementBuilder, webhook, lastDeliveries);
+ });
writeProtobuf(responseBuilder.build(), request, response);
}
+ private static void addLastDelivery(ListResponseElement.Builder responseElementBuilder, WebhookDto webhook, Map<String, WebhookDeliveryLiteDto> lastDeliveries) {
+ if (lastDeliveries.containsKey(webhook.getUuid())) {
+ WebhookDeliveryLiteDto delivery = lastDeliveries.get(webhook.getUuid());
+ Webhooks.LatestDelivery.Builder builder = responseElementBuilder.getLatestDeliveryBuilder()
+ .setId(delivery.getUuid())
+ .setAt(formatDateTime(delivery.getCreatedAt()))
+ .setSuccess(delivery.isSuccess());
+ if (delivery.getHttpStatus() != null) {
+ builder.setHttpStatus(delivery.getHttpStatus());
+ }
+ if (delivery.getDurationMs() != null) {
+ builder.setDurationMs(delivery.getDurationMs());
+ }
+ builder.build();
+ }
+ }
+
private OrganizationDto defaultOrganizationDto(DbSession dbSession) {
String uuid = defaultOrganizationProvider.get().getUuid();
Optional<OrganizationDto> organizationDto = dbClient.organizationDao().selectByUuid(dbSession, uuid);
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.sonar.api.server.ws.WebService.Param.PAGE;
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
+import static org.sonar.api.utils.Paging.offset;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
import static org.sonar.server.webhook.ws.WebhookWsSupport.copyDtoToProtobuf;
int totalElements;
try (DbSession dbSession = dbClient.openSession(false)) {
if (isNotBlank(webhookUuid)) {
- deliveries = dbClient.webhookDeliveryDao().selectByWebhookUuid(dbSession, webhookUuid, page - 1, pageSize);
- component = getComponentDto(dbSession, deliveries);
totalElements = dbClient.webhookDeliveryDao().countDeliveriesByWebhookUuid(dbSession, webhookUuid);
+ deliveries = dbClient.webhookDeliveryDao().selectByWebhookUuid(dbSession, webhookUuid, offset(page, pageSize), pageSize);
+ component = getComponentDto(dbSession, deliveries);
} else if (componentKey != null) {
component = componentFinder.getByKey(dbSession, componentKey);
- deliveries = dbClient.webhookDeliveryDao().selectOrderedByComponentUuid(dbSession, component.uuid(), page - 1, pageSize);
totalElements = dbClient.webhookDeliveryDao().countDeliveriesByComponentUuid(dbSession, component.uuid());
+ deliveries = dbClient.webhookDeliveryDao().selectOrderedByComponentUuid(dbSession, component.uuid(), offset(page, pageSize), pageSize);
} else {
- deliveries = dbClient.webhookDeliveryDao().selectOrderedByCeTaskUuid(dbSession, ceTaskId, page - 1, pageSize);
- component = getComponentDto(dbSession, deliveries);
totalElements = dbClient.webhookDeliveryDao().countDeliveriesByCeTaskUuid(dbSession, ceTaskId);
+ deliveries = dbClient.webhookDeliveryDao().selectOrderedByCeTaskUuid(dbSession, ceTaskId, offset(page, pageSize), pageSize);
+ component = getComponentDto(dbSession, deliveries);
}
}
return new Data(component, deliveries).withPagingInfo(page, pageSize, totalElements);
{
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 10,
+ "total": 1
+ },
"deliveries": [
{
"id": "d1",
"durationMs": 10
}
]
-}
+}
\ No newline at end of file
{
- "paging": {
- "pageIndex": 1,
- "pageSize": 10,
- "total": 1
- },
- "deliveries": [
- {
- "id": "d1",
- "componentKey": "my-project",
- "ceTaskId": "task-1",
- "name": "Jenkins",
- "url": "http://jenkins",
- "at": "2017-07-14T04:40:00+0200",
- "success": true,
- "httpStatus": 200,
- "durationMs": 10
- }
- ]
-}
\ No newline at end of file
+ "delivery": {
+ "id": "d1",
+ "componentKey": "my-project",
+ "ceTaskId": "task-1",
+ "name": "Jenkins",
+ "url": "http://jenkins",
+ "at": "2017-07-14T04:40:00+0200",
+ "success": true,
+ "httpStatus": 200,
+ "durationMs": 10,
+ "payload": "{\"status\"=\"SUCCESS\"}"
+ }
+}
WebhookDelivery delivery = newSender().call(webhook, PAYLOAD);
assertThat(delivery.getHttpStatus()).isEmpty();
- assertThat(delivery.getDurationInMs()).isEmpty();
+ assertThat(delivery.getDurationInMs().get()).isGreaterThanOrEqualTo(0);
// message can be "Connection refused" or "connect timed out"
assertThat(delivery.getErrorMessage().get()).matches("(.*Connection refused.*)|(.*connect timed out.*)");
assertThat(delivery.getAt()).isEqualTo(NOW);
WebhookDelivery delivery = newSender().call(webhook, PAYLOAD);
assertThat(delivery.getHttpStatus()).isEmpty();
- assertThat(delivery.getDurationInMs()).isEmpty();
+ assertThat(delivery.getDurationInMs().get()).isGreaterThanOrEqualTo(0);
assertThat(delivery.getError().get()).isInstanceOf(IllegalArgumentException.class);
assertThat(delivery.getErrorMessage().get()).isEqualTo("Webhook URL is not valid: this_is_not_an_url");
assertThat(delivery.getAt()).isEqualTo(NOW);
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.webhook.WebhookDbTesting;
import org.sonar.db.webhook.WebhookDeliveryDto;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import static org.sonar.db.webhook.WebhookDbTesting.newWebhookDeliveryDto;
+import static org.sonar.db.webhook.WebhookDbTesting.newDto;
import static org.sonar.db.webhook.WebhookDbTesting.selectAllDeliveryUuids;
public class WebhookDeliveryStorageTest {
}
private static WebhookDeliveryDto newDto(String uuid, String componentUuid, long at) {
- return newWebhookDeliveryDto()
+ return WebhookDbTesting.newDto()
.setUuid(uuid)
.setComponentUuid(componentUuid)
.setCreatedAt(at);
*/
package org.sonar.server.webhook.ws;
+import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.db.organization.OrganizationDbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.webhook.WebhookDbTester;
+import org.sonar.db.webhook.WebhookDeliveryDbTester;
import org.sonar.db.webhook.WebhookDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
-import org.sonarqube.ws.Webhooks.ListWsResponse;
-import org.sonarqube.ws.Webhooks.ListWsResponse.List;
+import org.sonarqube.ws.Webhooks;
+import org.sonarqube.ws.Webhooks.ListResponse;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.db.DbTester.create;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
+import static org.sonar.db.webhook.WebhookDbTesting.newDto;
+import static org.sonar.db.webhook.WebhookTesting.newOrganizationWebhook;
import static org.sonar.server.organization.TestDefaultOrganizationProvider.from;
import static org.sonar.server.tester.UserSessionRule.standalone;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.ORGANIZATION_KEY_PARAM;
public class ListActionTest {
- @Rule
- public ExpectedException expectedException = none();
+ private static final long NOW = 1_500_000_000L;
+ private static final long BEFORE = NOW - 1_000L;
- @Rule
- public UserSessionRule userSession = standalone();
+ @Rule
+ public ExpectedException expectedException = none();
- @Rule
- public DbTester db = create();
+ @Rule
+ public UserSessionRule userSession = standalone();
- private DbClient dbClient = db.getDbClient();
- private DefaultOrganizationProvider defaultOrganizationProvider = from(db);
- private WebhookSupport webhookSupport = new WebhookSupport(userSession);
- private ListAction underTest = new ListAction(dbClient, userSession, defaultOrganizationProvider, webhookSupport);
+ @Rule
+ public DbTester db = create();
- private ComponentDbTester componentDbTester = db.components();
- private WebhookDbTester webhookDbTester = db.webhooks();
- private OrganizationDbTester organizationDbTester = db.organizations();
- private WsActionTester wsActionTester = new WsActionTester(underTest);
+ private DbClient dbClient = db.getDbClient();
+ private DefaultOrganizationProvider defaultOrganizationProvider = from(db);
+ private WebhookSupport webhookSupport = new WebhookSupport(userSession);
+ private ListAction underTest = new ListAction(dbClient, userSession, defaultOrganizationProvider, webhookSupport);
- @Test
- public void definition() {
+ private ComponentDbTester componentDbTester = db.components();
+ private WebhookDbTester webhookDbTester = db.webhooks();
+ private WebhookDeliveryDbTester webhookDeliveryDbTester = db.webhookDelivery();
+ private OrganizationDbTester organizationDbTester = db.organizations();
+ private WsActionTester wsActionTester = new WsActionTester(underTest);
- WebService.Action action = wsActionTester.getDef();
+ @Test
+ public void definition() {
- assertThat(action).isNotNull();
- assertThat(action.isInternal()).isFalse();
- assertThat(action.isPost()).isFalse();
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params())
- .extracting(Param::key, Param::isRequired)
- .containsExactlyInAnyOrder(
- tuple("organization", false),
- tuple("project", false));
+ WebService.Action action = wsActionTester.getDef();
- }
+ assertThat(action).isNotNull();
+ assertThat(action.isInternal()).isFalse();
+ assertThat(action.isPost()).isFalse();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.params())
+ .extracting(Param::key, Param::isRequired)
+ .containsExactlyInAnyOrder(
+ tuple("organization", false),
+ tuple("project", false));
- @Test
- public void List_global_webhooks() {
+ }
- WebhookDto dto1 = webhookDbTester.insertWebhook(db.getDefaultOrganization());
- WebhookDto dto2 = webhookDbTester.insertWebhook(db.getDefaultOrganization());
- userSession.logIn().addPermission(ADMINISTER, db.getDefaultOrganization().getUuid());
+ @Test
+ public void list_webhooks_and_their_latest_delivery() {
+ WebhookDto webhook1 = webhookDbTester.insert(newOrganizationWebhook("aaa", defaultOrganizationProvider.get().getUuid()));
+ webhookDeliveryDbTester.insert(newDto("WH1-DELIVERY-1-UUID", webhook1.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE));
+ webhookDeliveryDbTester.insert(newDto("WH1-DELIVERY-2-UUID", webhook1.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
- ListWsResponse response = wsActionTester.newRequest()
- .executeProtobuf(ListWsResponse.class);
+ WebhookDto webhook2 = webhookDbTester.insert(newOrganizationWebhook("bbb", defaultOrganizationProvider.get().getUuid()));
+ webhookDeliveryDbTester.insert(newDto("WH2-DELIVERY-1-UUID", webhook2.getUuid(), "COMPONENT_1", "TASK_1").setCreatedAt(BEFORE));
+ webhookDeliveryDbTester.insert(newDto("WH2-DELIVERY-2-UUID", webhook2.getUuid(), "COMPONENT_1", "TASK_2").setCreatedAt(NOW));
- assertThat(response.getWebhooksList())
- .extracting(List::getName, List::getUrl)
- .contains(tuple(dto1.getName(), dto1.getUrl()),
- tuple(dto2.getName(), dto2.getUrl()));
+ userSession.logIn().addPermission(ADMINISTER, db.getDefaultOrganization().getUuid());
- }
+ ListResponse response = wsActionTester.newRequest().executeProtobuf(ListResponse.class);
- @Test
- public void List_project_webhooks_when_no_organization_is_provided() {
+ List<Webhooks.ListResponseElement> elements = response.getWebhooksList();
+ assertThat(elements.size()).isEqualTo(2);
- ComponentDto project1 = componentDbTester.insertPrivateProject();
- userSession.logIn().addProjectPermission(ADMIN, project1);
+ assertThat(elements.get(0)).extracting(Webhooks.ListResponseElement::getKey).containsExactly(webhook1.getUuid());
+ assertThat(elements.get(0)).extracting(Webhooks.ListResponseElement::getName).containsExactly("aaa");
+ assertThat(elements.get(0).getLatestDelivery()).isNotNull();
+ assertThat(elements.get(0).getLatestDelivery()).extracting(Webhooks.LatestDelivery::getId).containsExactly("WH1-DELIVERY-2-UUID");
- WebhookDto dto1 = webhookDbTester.insertWebhook(project1);
- WebhookDto dto2 = webhookDbTester.insertWebhook(project1);
+ assertThat(elements.get(1)).extracting(Webhooks.ListResponseElement::getKey).containsExactly(webhook2.getUuid());
+ assertThat(elements.get(1)).extracting(Webhooks.ListResponseElement::getName).containsExactly("bbb");
+ assertThat(elements.get(1).getLatestDelivery()).isNotNull();
+ assertThat(elements.get(1).getLatestDelivery()).extracting(Webhooks.LatestDelivery::getId).containsExactly("WH2-DELIVERY-2-UUID");
+ }
- ListWsResponse response = wsActionTester.newRequest()
- .setParam(PROJECT_KEY_PARAM, project1.getKey())
- .executeProtobuf(ListWsResponse.class);
+ @Test
+ public void list_webhooks_when_no_delivery() {
+ WebhookDto webhook1 = webhookDbTester.insert(newOrganizationWebhook("aaa", defaultOrganizationProvider.get().getUuid()));
+ WebhookDto webhook2 = webhookDbTester.insert(newOrganizationWebhook("bbb", defaultOrganizationProvider.get().getUuid()));
- assertThat(response.getWebhooksList())
- .extracting(List::getName, List::getUrl)
- .contains(tuple(dto1.getName(), dto1.getUrl()),
- tuple(dto2.getName(), dto2.getUrl()));
+ userSession.logIn().addPermission(ADMINISTER, db.getDefaultOrganization().getUuid());
- }
+ ListResponse response = wsActionTester.newRequest().executeProtobuf(ListResponse.class);
- @Test
- public void List_organization_webhooks() {
+ List<Webhooks.ListResponseElement> elements = response.getWebhooksList();
+ assertThat(elements.size()).isEqualTo(2);
- OrganizationDto organizationDto = organizationDbTester.insert();
- WebhookDto dto1 = webhookDbTester.insertWebhook(organizationDto);
- WebhookDto dto2 = webhookDbTester.insertWebhook(organizationDto);
- userSession.logIn().addPermission(ADMINISTER, organizationDto.getUuid());
+ assertThat(elements.get(0)).extracting(Webhooks.ListResponseElement::getKey).containsExactly(webhook1.getUuid());
+ assertThat(elements.get(0)).extracting(Webhooks.ListResponseElement::getName).containsExactly("aaa");
+ assertThat(elements.get(0).hasLatestDelivery()).isFalse();
- ListWsResponse response = wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, organizationDto.getKey())
- .executeProtobuf(ListWsResponse.class);
+ assertThat(elements.get(1)).extracting(Webhooks.ListResponseElement::getKey).containsExactly(webhook2.getUuid());
+ assertThat(elements.get(1)).extracting(Webhooks.ListResponseElement::getName).containsExactly("bbb");
+ assertThat(elements.get(1).hasLatestDelivery()).isFalse();
+ }
- assertThat(response.getWebhooksList())
- .extracting(List::getName, List::getUrl)
- .contains(tuple(dto1.getName(), dto1.getUrl()),
- tuple(dto2.getName(), dto2.getUrl()));
+ @Test
+ public void list_global_webhooks() {
- }
+ WebhookDto dto1 = webhookDbTester.insertWebhook(db.getDefaultOrganization());
+ WebhookDto dto2 = webhookDbTester.insertWebhook(db.getDefaultOrganization());
+ userSession.logIn().addPermission(ADMINISTER, db.getDefaultOrganization().getUuid());
- @Test
- public void List_project_webhooks_when_organization_is_provided() {
+ ListResponse response = wsActionTester.newRequest()
+ .executeProtobuf(ListResponse.class);
- OrganizationDto organization = organizationDbTester.insert();
- ComponentDto project = componentDbTester.insertPrivateProject(organization);
- userSession.logIn().addProjectPermission(ADMIN, project);
+ assertThat(response.getWebhooksList())
+ .extracting(Webhooks.ListResponseElement::getName, Webhooks.ListResponseElement::getUrl)
+ .contains(tuple(dto1.getName(), dto1.getUrl()),
+ tuple(dto2.getName(), dto2.getUrl()));
- WebhookDto dto1 = webhookDbTester.insertWebhook(project);
- WebhookDto dto2 = webhookDbTester.insertWebhook(project);
+ }
- ListWsResponse response = wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
- .setParam(PROJECT_KEY_PARAM, project.getKey())
- .executeProtobuf(ListWsResponse.class);
+ @Test
+ public void list_project_webhooks_when_no_organization_is_provided() {
- assertThat(response.getWebhooksList())
- .extracting(List::getName, List::getUrl)
- .contains(tuple(dto1.getName(), dto1.getUrl()),
- tuple(dto2.getName(), dto2.getUrl()));
+ ComponentDto project1 = componentDbTester.insertPrivateProject();
+ userSession.logIn().addProjectPermission(ADMIN, project1);
- }
+ WebhookDto dto1 = webhookDbTester.insertWebhook(project1);
+ WebhookDto dto2 = webhookDbTester.insertWebhook(project1);
- @Test
- public void return_NotFoundException_if_requested_project_is_not_found() throws Exception {
+ ListResponse response = wsActionTester.newRequest()
+ .setParam(PROJECT_KEY_PARAM, project1.getKey())
+ .executeProtobuf(ListResponse.class);
- userSession.logIn().setSystemAdministrator();
- expectedException.expect(NotFoundException.class);
+ assertThat(response.getWebhooksList())
+ .extracting(Webhooks.ListResponseElement::getName, Webhooks.ListResponseElement::getUrl)
+ .contains(tuple(dto1.getName(), dto1.getUrl()),
+ tuple(dto2.getName(), dto2.getUrl()));
- wsActionTester.newRequest()
- .setParam(PROJECT_KEY_PARAM, "pipo")
- .executeProtobuf(ListWsResponse.class);
+ }
- }
+ @Test
+ public void list_organization_webhooks() {
- @Test
- public void return_NotFoundException_if_requested_organization_is_not_found() throws Exception {
+ OrganizationDto organizationDto = organizationDbTester.insert();
+ WebhookDto dto1 = webhookDbTester.insertWebhook(organizationDto);
+ WebhookDto dto2 = webhookDbTester.insertWebhook(organizationDto);
+ userSession.logIn().addPermission(ADMINISTER, organizationDto.getUuid());
- userSession.logIn().setSystemAdministrator();
- expectedException.expect(NotFoundException.class);
+ ListResponse response = wsActionTester.newRequest()
+ .setParam(ORGANIZATION_KEY_PARAM, organizationDto.getKey())
+ .executeProtobuf(ListResponse.class);
- wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, "pipo")
- .executeProtobuf(ListWsResponse.class);
+ assertThat(response.getWebhooksList())
+ .extracting(Webhooks.ListResponseElement::getName, Webhooks.ListResponseElement::getUrl)
+ .contains(tuple(dto1.getName(), dto1.getUrl()),
+ tuple(dto2.getName(), dto2.getUrl()));
- }
+ }
- @Test
- public void fail_if_project_exists_but_does_not_belong_to_requested_organization() {
+ @Test
+ public void list_project_webhooks_when_organization_is_provided() {
- OrganizationDto organization = organizationDbTester.insert();
- ComponentDto project = componentDbTester.insertPrivateProject();
+ OrganizationDto organization = organizationDbTester.insert();
+ ComponentDto project = componentDbTester.insertPrivateProject(organization);
+ userSession.logIn().addProjectPermission(ADMIN, project);
- expectedException.expect(NotFoundException.class);
- expectedException.expectMessage(format("Project '%s' does not belong to organisation '%s'", project.getKey(), organization.getKey()));
+ WebhookDto dto1 = webhookDbTester.insertWebhook(project);
+ WebhookDto dto2 = webhookDbTester.insertWebhook(project);
- userSession.logIn().addProjectPermission(ADMIN, project);
+ ListResponse response = wsActionTester.newRequest()
+ .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
+ .setParam(PROJECT_KEY_PARAM, project.getKey())
+ .executeProtobuf(ListResponse.class);
- wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
- .setParam(PROJECT_KEY_PARAM, project.getKey())
- .execute();
+ assertThat(response.getWebhooksList())
+ .extracting(Webhooks.ListResponseElement::getName, Webhooks.ListResponseElement::getUrl)
+ .contains(tuple(dto1.getName(), dto1.getUrl()),
+ tuple(dto2.getName(), dto2.getUrl()));
- }
+ }
- @Test
- public void return_UnauthorizedException_if_not_logged_in() throws Exception {
+ @Test
+ public void return_NotFoundException_if_requested_project_is_not_found() throws Exception {
- userSession.anonymous();
- expectedException.expect(UnauthorizedException.class);
+ userSession.logIn().setSystemAdministrator();
+ expectedException.expect(NotFoundException.class);
- wsActionTester.newRequest()
- .executeProtobuf(ListWsResponse.class);
+ wsActionTester.newRequest()
+ .setParam(PROJECT_KEY_PARAM, "pipo")
+ .executeProtobuf(ListResponse.class);
- }
+ }
- @Test
- public void throw_ForbiddenException_if_not_organization_administrator() {
+ @Test
+ public void return_NotFoundException_if_requested_organization_is_not_found() throws Exception {
- userSession.logIn();
+ userSession.logIn().setSystemAdministrator();
+ expectedException.expect(NotFoundException.class);
- expectedException.expect(ForbiddenException.class);
- expectedException.expectMessage("Insufficient privileges");
+ wsActionTester.newRequest()
+ .setParam(ORGANIZATION_KEY_PARAM, "pipo")
+ .executeProtobuf(ListResponse.class);
- wsActionTester.newRequest()
- .executeProtobuf(ListWsResponse.class);
- }
+ }
- @Test
- public void throw_ForbiddenException_if_not_project_administrator() {
+ @Test
+ public void fail_if_project_exists_but_does_not_belong_to_requested_organization() {
- ComponentDto project = componentDbTester.insertPrivateProject();
+ OrganizationDto organization = organizationDbTester.insert();
+ ComponentDto project = componentDbTester.insertPrivateProject();
- userSession.logIn();
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage(format("Project '%s' does not belong to organisation '%s'", project.getKey(), organization.getKey()));
- expectedException.expect(ForbiddenException.class);
- expectedException.expectMessage("Insufficient privileges");
+ userSession.logIn().addProjectPermission(ADMIN, project);
- wsActionTester.newRequest()
- .setParam(PROJECT_KEY_PARAM, project.getKey())
- .executeProtobuf(ListWsResponse.class);
+ wsActionTester.newRequest()
+ .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
+ .setParam(PROJECT_KEY_PARAM, project.getKey())
+ .execute();
- }
+ }
+
+ @Test
+ public void return_UnauthorizedException_if_not_logged_in() throws Exception {
+
+ userSession.anonymous();
+ expectedException.expect(UnauthorizedException.class);
+
+ wsActionTester.newRequest()
+ .executeProtobuf(ListResponse.class);
+
+ }
+
+ @Test
+ public void throw_ForbiddenException_if_not_organization_administrator() {
+
+ userSession.logIn();
+
+ expectedException.expect(ForbiddenException.class);
+ expectedException.expectMessage("Insufficient privileges");
+
+ wsActionTester.newRequest()
+ .executeProtobuf(ListResponse.class);
+ }
+
+ @Test
+ public void throw_ForbiddenException_if_not_project_administrator() {
+
+ ComponentDto project = componentDbTester.insertPrivateProject();
+
+ userSession.logIn();
+
+ expectedException.expect(ForbiddenException.class);
+ expectedException.expectMessage("Insufficient privileges");
+
+ wsActionTester.newRequest()
+ .setParam(PROJECT_KEY_PARAM, project.getKey())
+ .executeProtobuf(ListResponse.class);
+
+ }
}
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.webhook.WebhookDeliveryDbTester;
import org.sonar.db.webhook.WebhookDeliveryDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.TestComponentFinder;
import org.sonarqube.ws.Webhooks;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.webhook.WebhookDbTesting.newWebhookDeliveryDto;
+import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
+import static org.sonar.db.webhook.WebhookDbTesting.newDto;
import static org.sonar.test.JsonAssert.assertJson;
public class WebhookDeliveriesActionTest {
public DbTester db = DbTester.create(System2.INSTANCE);
private DbClient dbClient = db.getDbClient();
+ private WebhookDeliveryDbTester webhookDeliveryDbTester = db.webhookDelivery();
+
private WsActionTester ws;
private ComponentDto project;
ComponentFinder componentFinder = TestComponentFinder.from(db);
WebhookDeliveriesAction underTest = new WebhookDeliveriesAction(dbClient, userSession, componentFinder);
ws = new WsActionTester(underTest);
- project = db.components().insertComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("my-project"));
+ project = db.components().insertComponent(newPrivateProjectDto(db.organizations().insert()).setDbKey("my-project"));
}
@Test
@Test
public void search_by_component_and_return_records_of_example() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setUuid("d1")
.setComponentUuid(project.uuid())
.setCeTaskUuid("task-1")
@Test
public void search_by_task_and_return_records() {
- WebhookDeliveryDto dto1 = newWebhookDeliveryDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1");
- WebhookDeliveryDto dto2 = newWebhookDeliveryDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1");
- WebhookDeliveryDto dto3 = newWebhookDeliveryDto().setComponentUuid(project.uuid()).setCeTaskUuid("t2");
+ WebhookDeliveryDto dto1 = newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1");
+ WebhookDeliveryDto dto2 = newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1");
+ WebhookDeliveryDto dto3 = newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t2");
dbClient.webhookDeliveryDao().insert(db.getSession(), dto1);
dbClient.webhookDeliveryDao().insert(db.getSession(), dto2);
dbClient.webhookDeliveryDao().insert(db.getSession(), dto3);
@Test
public void search_by_webhook_and_return_records() {
- WebhookDeliveryDto dto1 = newWebhookDeliveryDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid");
- WebhookDeliveryDto dto2 = newWebhookDeliveryDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid");
- WebhookDeliveryDto dto3 = newWebhookDeliveryDto().setComponentUuid(project.uuid()).setCeTaskUuid("t2").setWebhookUuid("wh-2-uuid");
+ WebhookDeliveryDto dto1 = newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid");
+ WebhookDeliveryDto dto2 = newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid");
+ WebhookDeliveryDto dto3 = newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t2").setWebhookUuid("wh-2-uuid");
dbClient.webhookDeliveryDao().insert(db.getSession(), dto1);
dbClient.webhookDeliveryDao().insert(db.getSession(), dto2);
dbClient.webhookDeliveryDao().insert(db.getSession(), dto3);
userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
Webhooks.DeliveriesWsResponse response = ws.newRequest()
- .setParam("ceTaskId", "t1")
+ .setParam("webhook", "wh-1-uuid")
.executeProtobuf(Webhooks.DeliveriesWsResponse.class);
assertThat(response.getDeliveriesCount()).isEqualTo(2);
assertThat(response.getDeliveriesList()).extracting(Webhooks.Delivery::getId).containsOnly(dto1.getUuid(), dto2.getUuid());
}
+ @Test
+ public void validate_default_pagination() {
+
+ for (int i = 0; i < 15; i++) {
+ webhookDeliveryDbTester.insert(newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid"));
+ }
+
+ userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+
+ Webhooks.DeliveriesWsResponse response = ws.newRequest()
+ .setParam("webhook", "wh-1-uuid")
+ .executeProtobuf(Webhooks.DeliveriesWsResponse.class);
+
+ assertThat(response.getDeliveriesCount()).isEqualTo(10);
+
+ }
+
+ @Test
+ public void validate_pagination_first_page() {
+
+ for (int i = 0; i < 12; i++) {
+ webhookDeliveryDbTester.insert(newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid"));
+ }
+
+ userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+
+ Webhooks.DeliveriesWsResponse response = ws.newRequest()
+ .setParam("webhook", "wh-1-uuid")
+ .setParam("p", "1")
+ .setParam("ps", "10")
+ .executeProtobuf(Webhooks.DeliveriesWsResponse.class);
+
+ assertThat(response.getDeliveriesCount()).isEqualTo(10);
+ assertThat(response.getPaging().getTotal()).isEqualTo(12);
+ assertThat(response.getPaging().getPageIndex()).isEqualTo(1);
+ }
+
+ @Test
+ public void validate_pagination_last_page() {
+
+ for (int i = 0; i < 12; i++) {
+ webhookDeliveryDbTester.insert(newDto().setComponentUuid(project.uuid()).setCeTaskUuid("t1").setWebhookUuid("wh-1-uuid"));
+ }
+
+ userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+
+ Webhooks.DeliveriesWsResponse response = ws.newRequest()
+ .setParam("webhook", "wh-1-uuid")
+ .setParam("p", "2")
+ .setParam("ps", "10")
+ .executeProtobuf(Webhooks.DeliveriesWsResponse.class);
+
+ assertThat(response.getDeliveriesCount()).isEqualTo(2);
+ assertThat(response.getPaging().getTotal()).isEqualTo(12);
+ assertThat(response.getPaging().getPageIndex()).isEqualTo(2);
+ }
+
@Test
public void search_by_component_and_throw_ForbiddenException_if_not_admin_of_project() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setComponentUuid(project.uuid());
dbClient.webhookDeliveryDao().insert(db.getSession(), dto);
db.commit();
@Test
public void search_by_task_and_throw_ForbiddenException_if_not_admin_of_project() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setComponentUuid(project.uuid());
dbClient.webhookDeliveryDao().insert(db.getSession(), dto);
db.commit();
import org.sonarqube.ws.Webhooks;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.webhook.WebhookDbTesting.newWebhookDeliveryDto;
+import static org.sonar.db.webhook.WebhookDbTesting.newDto;
import static org.sonar.test.JsonAssert.assertJson;
public class WebhookDeliveryActionTest {
@Test
public void load_the_delivery_of_example() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setUuid("d1")
.setComponentUuid(project.uuid())
.setCeTaskUuid("task-1")
@Test
public void return_delivery_that_failed_to_be_sent() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setComponentUuid(project.uuid())
.setSuccess(false)
.setHttpStatus(null)
@Test
public void return_delivery_with_none_of_optional_fields() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setComponentUuid(project.uuid())
.setCeTaskUuid(null)
.setHttpStatus(null)
@Test
public void throw_ForbiddenException_if_not_admin_of_project() {
- WebhookDeliveryDto dto = newWebhookDeliveryDto()
+ WebhookDeliveryDto dto = newDto()
.setComponentUuid(project.uuid());
dbClient.webhookDeliveryDao().insert(db.getSession(), dto);
db.commit();
webhooks.delivery.payload=Payload:
webhooks.delivery.response_x=Response: {0}
webhooks.documentation_link=Webhooks documentation
-webhooks.last_execution=Last execution
+webhooks.last_execution=Last delivery
webhooks.last_execution.none=Never
webhooks.maximum_reached=You reached your maximum number of {0} webhooks. You can still update or delete an existing one.
webhooks.name=Name
class NewAction {
private final String key;
+ private static final String PAGE_PARAM_DESCRIPTION = "1-based page number";
private String deprecatedKey;
private String description;
private String since;
*/
public NewAction addPagingParams(int defaultPageSize) {
createParam(Param.PAGE)
- .setDescription("1-based page number")
+ .setDescription(PAGE_PARAM_DESCRIPTION)
.setExampleValue("42")
.setDeprecatedKey("pageIndex", "5.2")
.setDefaultValue("1");
public NewParam createPageParam() {
return createParam(Param.PAGE)
- .setDescription("1-based page number")
+ .setDescription(PAGE_PARAM_DESCRIPTION)
.setExampleValue("42")
.setDeprecatedKey("pageIndex", "5.2")
.setDefaultValue("1");
/**
* Add predefined parameters related to pagination of results with a maximum page size.
- * Note the maximum is a documentation only feature. It does not check anything.
+ * @since 7.1
*/
public NewAction addPagingParamsSince(int defaultPageSize, int maxPageSize, String version) {
createParam(Param.PAGE)
- .setDescription("1-based page number")
+ .setDescription(PAGE_PARAM_DESCRIPTION)
.setExampleValue("42")
.setDefaultValue("1")
.setSince(version);
*/
package org.sonarqube.ws.client.webhooks;
-import java.util.List;
import javax.annotation.Generated;
/**
private String ceTaskId;
private String componentKey;
+ private String p;
+ private String ps;
+ private String webhook;
/**
* Example value: "AU-Tpxb--iU5OvuD2FLy"
public String getComponentKey() {
return componentKey;
}
+
+ /**
+ * Example value: "42"
+ */
+ public DeliveriesRequest setP(String p) {
+ this.p = p;
+ return this;
+ }
+
+ public String getP() {
+ return p;
+ }
+
+ /**
+ * Example value: "20"
+ */
+ public DeliveriesRequest setPs(String ps) {
+ this.ps = ps;
+ return this;
+ }
+
+ public String getPs() {
+ return ps;
+ }
+
+ /**
+ * Example value: "AU-TpxcA-iU5OvuD2FLz"
+ */
+ public DeliveriesRequest setWebhook(String webhook) {
+ this.webhook = webhook;
+ return this;
+ }
+
+ public String getWebhook() {
+ return webhook;
+ }
}
*/
package org.sonarqube.ws.client.webhooks;
-import java.util.stream.Collectors;
import javax.annotation.Generated;
import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.Webhooks.CreateWsResponse;
+import org.sonarqube.ws.Webhooks.DeliveriesWsResponse;
+import org.sonarqube.ws.Webhooks.DeliveryWsResponse;
+import org.sonarqube.ws.Webhooks.ListResponse;
import org.sonarqube.ws.client.BaseService;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsConnector;
-import org.sonarqube.ws.Webhooks.CreateWsResponse;
-import org.sonarqube.ws.Webhooks.DeliveriesWsResponse;
-import org.sonarqube.ws.Webhooks.DeliveryWsResponse;
-import org.sonarqube.ws.Webhooks.ListWsResponse;
/**
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/webhooks">Further information about this web service online</a>
return call(
new GetRequest(path("deliveries"))
.setParam("ceTaskId", request.getCeTaskId())
- .setParam("componentKey", request.getComponentKey()),
+ .setParam("componentKey", request.getComponentKey())
+ .setParam("p", request.getP())
+ .setParam("ps", request.getPs())
+ .setParam("webhook", request.getWebhook()),
DeliveriesWsResponse.parser());
}
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/webhooks/list">Further information about this action online (including a response example)</a>
* @since 7.1
*/
- public ListWsResponse list(ListRequest request) {
+ public ListResponse list(ListRequest request) {
return call(
new GetRequest(path("list"))
.setParam("organization", request.getOrganization())
.setParam("project", request.getProject()),
- ListWsResponse.parser());
+ ListResponse.parser());
}
/**
option java_outer_classname = "Webhooks";
option optimize_for = SPEED;
-// GET api/webhooks/list
-message ListWsResponse {
- repeated List webhooks = 1;
+message LatestDelivery {
+ optional string id = 1;
+ optional string at = 2;
+ optional bool success = 3;
+ optional int32 httpStatus = 4;
+ optional int32 durationMs = 5;
+}
- message List {
- optional string key = 1;
- optional string name = 2;
- optional string url = 3;
- optional LatestDelivery latestDelivery = 4;
+message ListResponseElement {
+ optional string key = 1;
+ optional string name = 2;
+ optional string url = 3;
+ optional LatestDelivery latestDelivery = 4;
+}
- message LatestDelivery {
- optional string id = 1;
- optional string at = 2;
- optional string success = 3;
- optional string httpStatus = 4;
- optional string durationMs = 5;
- }
- }
+// GET api/webhooks/list
+message ListResponse {
+ repeated ListResponseElement webhooks = 1;
}
// POST api/webhooks/create
assertThat(detail.getSuccess()).isFalse();
assertThat(detail.hasHttpStatus()).isFalse();
- assertThat(detail.hasDurationMs()).isFalse();
+ assertThat(detail.hasDurationMs()).isTrue();
assertThat(detail.getPayload()).isNotEmpty();
assertThat(detail.getErrorStacktrace())
.contains("java.net.UnknownHostException")