diff options
Diffstat (limited to 'server/sonar-server')
10 files changed, 367 insertions, 221 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookCallerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookCallerImpl.java index f5d231fc98b..e9e70ca09c1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookCallerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookCallerImpl.java @@ -65,12 +65,14 @@ public class WebhookCallerImpl implements WebhookCaller { 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) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/ListAction.java index d90f1f0490c..cc8f70ab27c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/ListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/ListAction.java @@ -21,6 +21,7 @@ package org.sonar.server.webhook.ws; 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; @@ -30,13 +31,17 @@ import org.sonar.db.DbClient; 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; @@ -45,7 +50,6 @@ import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; 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 { @@ -92,55 +96,77 @@ 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); diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookDeliveriesAction.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookDeliveriesAction.java index ee5e469f57a..0ae3dd4a777 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookDeliveriesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookDeliveriesAction.java @@ -42,6 +42,7 @@ import static java.util.Objects.requireNonNull; 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; @@ -115,17 +116,17 @@ public class WebhookDeliveriesAction implements WebhooksWsAction { 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); diff --git a/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-deliveries.json b/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-deliveries.json index 129d9dbfc21..d95c99d3ba3 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-deliveries.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-deliveries.json @@ -1,4 +1,9 @@ { + "paging": { + "pageIndex": 1, + "pageSize": 10, + "total": 1 + }, "deliveries": [ { "id": "d1", @@ -12,4 +17,4 @@ "durationMs": 10 } ] -} +}
\ No newline at end of file diff --git a/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-delivery.json b/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-delivery.json index d95c99d3ba3..d4da8033df5 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-delivery.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-delivery.json @@ -1,20 +1,14 @@ { - "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\"}" + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookCallerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookCallerImplTest.java index 1e174e6ba54..60ac24ee262 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookCallerImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookCallerImplTest.java @@ -90,7 +90,7 @@ public class WebhookCallerImplTest { 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); @@ -105,7 +105,7 @@ public class WebhookCallerImplTest { 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); diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java index 158fdd73002..1fac932cbc9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java @@ -28,12 +28,13 @@ import org.sonar.core.util.UuidFactory; 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 { @@ -111,7 +112,7 @@ public class WebhookDeliveryStorageTest { } private static WebhookDeliveryDto newDto(String uuid, String componentUuid, long at) { - return newWebhookDeliveryDto() + return WebhookDbTesting.newDto() .setUuid(uuid) .setComponentUuid(componentUuid) .setCreatedAt(at); diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/ListActionTest.java index 995eb3b106b..0a6505d2f14 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/ListActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/ListActionTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.webhook.ws; +import java.util.List; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -31,6 +32,7 @@ import org.sonar.db.component.ComponentDto; 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; @@ -38,8 +40,8 @@ import org.sonar.server.exceptions.UnauthorizedException; 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; @@ -48,6 +50,8 @@ import static org.junit.rules.ExpectedException.none; 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; @@ -55,199 +59,252 @@ import static org.sonar.server.webhook.ws.WebhooksWsParameters.PROJECT_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); + + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveriesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveriesActionTest.java index 6d3d3327dff..4637386f5be 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveriesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveriesActionTest.java @@ -29,7 +29,7 @@ import org.sonar.api.web.UserRole; 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; @@ -40,7 +40,8 @@ import org.sonar.server.ws.WsActionTester; 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 { @@ -55,6 +56,8 @@ 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; @@ -63,7 +66,7 @@ public class WebhookDeliveriesActionTest { 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 @@ -116,7 +119,7 @@ public class WebhookDeliveriesActionTest { @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") @@ -140,9 +143,9 @@ public class WebhookDeliveriesActionTest { @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); @@ -158,9 +161,9 @@ public class WebhookDeliveriesActionTest { @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); @@ -168,15 +171,72 @@ public class WebhookDeliveriesActionTest { 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(); @@ -192,7 +252,7 @@ public class WebhookDeliveriesActionTest { @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(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveryActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveryActionTest.java index dbc6db0af65..1b54fc6ae2b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveryActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/WebhookDeliveryActionTest.java @@ -42,7 +42,7 @@ import org.sonarqube.ws.MediaTypes; 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 { @@ -100,7 +100,7 @@ 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") @@ -125,7 +125,7 @@ public class WebhookDeliveryActionTest { @Test public void return_delivery_that_failed_to_be_sent() { - WebhookDeliveryDto dto = newWebhookDeliveryDto() + WebhookDeliveryDto dto = newDto() .setComponentUuid(project.uuid()) .setSuccess(false) .setHttpStatus(null) @@ -147,7 +147,7 @@ public class WebhookDeliveryActionTest { @Test public void return_delivery_with_none_of_optional_fields() { - WebhookDeliveryDto dto = newWebhookDeliveryDto() + WebhookDeliveryDto dto = newDto() .setComponentUuid(project.uuid()) .setCeTaskUuid(null) .setHttpStatus(null) @@ -171,7 +171,7 @@ public class WebhookDeliveryActionTest { @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(); |