aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorGuillaume Jambet <guillaume.jambet@sonarsource.com>2018-01-31 18:47:59 +0100
committerGuillaume Jambet <guillaume.jambet@gmail.com>2018-03-01 15:21:05 +0100
commit21b4be2173e36fef157e46582060e265edb1bf45 (patch)
tree8e94b30ef647a93fb1c24750fec518458615c2aa /server
parent3c5c062c8bf27f5ed93c72871d9d9ddcf4c0c548 (diff)
downloadsonarqube-21b4be2173e36fef157e46582060e265edb1bf45.tar.gz
sonarqube-21b4be2173e36fef157e46582060e265edb1bf45.zip
SONAR-10344 api/webhooks/search returns webhooks for global and project
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/setting/ws/ValuesAction.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooksImpl.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/webhook/ws/SearchAction.java90
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookSearchDTO.java26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhooksWsParameters.java25
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-webhooks-search.json18
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/webhook/ws/SearchActionTest.java176
-rw-r--r--server/sonar-web/src/main/js/api/webhooks.ts16
-rw-r--r--server/sonar-web/src/main/js/app/types.ts15
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/App.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx15
12 files changed, 293 insertions, 104 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ValuesAction.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
index 4a947af76ae..57fefaeb3a0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
@@ -145,8 +145,8 @@ public class ValuesAction implements SettingsWsAction {
private Set<String> loadKeys(ValuesRequest valuesRequest) {
List<String> keys = valuesRequest.getKeys();
- return keys == null || keys.isEmpty() ? concat(propertyDefinitions.getAll().stream().map(PropertyDefinition::key), SERVER_SETTING_KEYS.stream()).collect(Collectors.toSet())
- : ImmutableSet.copyOf(keys);
+ return keys == null || keys.isEmpty() ? concat(propertyDefinitions.getAll().stream().map(PropertyDefinition::key),
+ SERVER_SETTING_KEYS.stream()).collect(Collectors.toSet()) : ImmutableSet.copyOf(keys);
}
private Optional<ComponentDto> loadComponent(DbSession dbSession, ValuesRequest valuesRequest) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooksImpl.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooksImpl.java
index fdcef061f7e..cae1aa5eaf0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooksImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooksImpl.java
@@ -57,7 +57,7 @@ public class WebHooksImpl implements WebHooks {
.isPresent();
}
- private static Stream<NameUrl> readWebHooksFrom(Configuration config) {
+ public static Stream<NameUrl> readWebHooksFrom(Configuration config) {
return Stream.concat(
getWebhookProperties(config, WebhookProperties.GLOBAL_KEY).stream(),
getWebhookProperties(config, WebhookProperties.PROJECT_KEY).stream())
@@ -110,7 +110,7 @@ public class WebHooksImpl implements WebHooks {
}
}
- private static final class NameUrl {
+ public static final class NameUrl {
private final String name;
private final String url;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/SearchAction.java
index c31b49b92e3..93e0c23e0f4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/SearchAction.java
@@ -1,36 +1,70 @@
+/*
+ * 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.server.webhook.ws;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
import com.google.common.io.Resources;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nullable;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.setting.ws.Setting;
+import org.sonar.server.setting.ws.SettingsFinder;
import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.Webhooks;
+import org.sonarqube.ws.Webhooks.SearchWsResponse.Builder;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.web.UserRole.ADMIN;
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.webhook.ws.WebhooksWsParameters.SEARCH_ACTION;
import static org.sonar.server.ws.KeyExamples.KEY_ORG_EXAMPLE_001;
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.writeProtobuf;
+import static org.sonarqube.ws.Webhooks.SearchWsResponse.newBuilder;
public class SearchAction implements WebhooksWsAction {
private final DbClient dbClient;
private final UserSession userSession;
+ private final SettingsFinder settingsFinder;
- public SearchAction(DbClient dbClient, UserSession userSession) {
+ public SearchAction(DbClient dbClient, UserSession userSession, SettingsFinder settingsFinder) {
this.dbClient = dbClient;
this.userSession = userSession;
+ this.settingsFinder = settingsFinder;
}
@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction(SEARCH_ACTION)
- .setDescription("Search for webhooks associated to an organization or a project.<br/>")
+ .setDescription("Search for global or project webhooks")
.setSince("7.1")
.setResponseExample(Resources.getResource(this.getClass(), "example-webhooks-search.json"))
.setHandler(this);
@@ -51,25 +85,45 @@ public class SearchAction implements WebhooksWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
- Webhooks.SearchWsResponse.Builder searchResponse = Webhooks.SearchWsResponse.newBuilder();
+ String projectKey = request.param(PROJECT_KEY_PARAM);
- // FIXME : hard coded to test plumbing
- ArrayList<WebhookSearchDTO> webhookSearchDTOS = new ArrayList<>();
- webhookSearchDTOS.add(new WebhookSearchDTO("UUID-1", "my first webhook", "http://www.my-webhook-listener.com/sonarqube"));
- webhookSearchDTOS.add(new WebhookSearchDTO("UUID-2", "my 2nd webhook", "https://www.my-other-webhook-listener.com/fancy-listner"));
+ userSession.checkLoggedIn();
- for (WebhookSearchDTO dto : webhookSearchDTOS) {
- searchResponse.addWebhooksBuilder()
- .setKey(dto.getKey())
- .setName(dto.getName())
- .setUrl(dto.getUrl());
+ writeResponse(request, response, doHandle(projectKey));
+
+ }
+
+ private List<Setting> doHandle(@Nullable String projectKey) {
+
+ try (DbSession dbSession = dbClient.openSession(true)) {
+
+ if (isNotBlank(projectKey)) {
+ Optional<ComponentDto> component = dbClient.componentDao().selectByKey(dbSession, projectKey);
+ checkFoundWithOptional(component, "project %s does not exist", projectKey);
+ userSession.checkComponentPermission(ADMIN, component.get());
+ return new ArrayList<>(settingsFinder.loadComponentSettings(dbSession,
+ ImmutableSet.of("sonar.webhooks.project"), component.get()).get(component.get().uuid()));
+ } else {
+ userSession.checkIsSystemAdministrator();
+ return settingsFinder.loadGlobalSettings(dbSession, ImmutableSet.of("sonar.webhooks.global"));
+ }
}
+ }
+
+ private static void writeResponse(Request request, Response response, List<Setting> settings) {
+
+ Builder responseBuilder = newBuilder();
- writeProtobuf(searchResponse.build(), request, response);
+ settings
+ .stream()
+ .map(Setting::getPropertySets)
+ .flatMap(Collection::stream)
+ .forEach(map -> responseBuilder.addWebhooksBuilder()
+ .setKey("")
+ .setName(map.get("name"))
+ .setUrl(map.get("url")));
+
+ writeProtobuf(responseBuilder.build(), request, response);
}
}
-
-// {"key":"UUID-1","name":,"url":,"latestDelivery":{"id":"d1","at":"2017-07-14T04:40:00+0200","success":true,"httpStatus":200,"durationMs":10}},
-// {"key":"UUID-2","name":"my 2nd
-// webhook","url":"https://www.my-other-webhook-listener.com/fancy-listner","latestDelivery":{"id":"d2","at":"2017-07-14T04:40:00+0200","success":true,"httpStatus":200,"durationMs":10}}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookSearchDTO.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookSearchDTO.java
deleted file mode 100644
index 617ef66fec0..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhookSearchDTO.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.sonar.server.webhook.ws;
-
-public class WebhookSearchDTO {
-
- private final String key;
- private final String name;
- private final String url;
-
- public WebhookSearchDTO(String key, String name, String url) {
- this.key = key;
- this.name = name;
- this.url = url;
- }
-
- public String getKey() {
- return key;
- }
-
- public String getName() {
- return name;
- }
-
- public String getUrl() {
- return url;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhooksWsParameters.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhooksWsParameters.java
index 3a8d18acf66..7430e3f2f1d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhooksWsParameters.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/ws/WebhooksWsParameters.java
@@ -1,14 +1,35 @@
+/*
+ * 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.server.webhook.ws;
class WebhooksWsParameters {
static final String WEBHOOKS_CONTROLLER = "api/webhooks";
-
static final String SEARCH_ACTION = "search";
-
static final String ORGANIZATION_KEY_PARAM = "organization";
static final String PROJECT_KEY_PARAM = "project";
+ private WebhooksWsParameters() {
+ // hiding constructor
+ }
+
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-webhooks-search.json b/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-webhooks-search.json
index 0f5d3befe28..ba3ba250df4 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-webhooks-search.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/webhook/ws/example-webhooks-search.json
@@ -3,26 +3,12 @@
{
"key": "UUID-1",
"name": "my first webhook",
- "url": "http://www.my-webhook-listener.com/sonarqube",
- "latestDelivery": {
- "id": "d1",
- "at": "2017-07-14T04:40:00+0200",
- "success": true,
- "httpStatus": 200,
- "durationMs": 10
- }
+ "url": "http://www.my-webhook-listener.com/sonarqube"
},
{
"key": "UUID-2",
"name": "my 2nd webhook",
- "url": "https://www.my-other-webhook-listener.com/fancy-listner",
- "latestDelivery": {
- "id": "d2",
- "at": "2017-07-14T04:40:00+0200",
- "success": true,
- "httpStatus": 200,
- "durationMs": 10
- }
+ "url": "https://www.my-other-webhook-listener.com/fancy-listner"
}
]
} \ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/SearchActionTest.java
index 68264390abd..d2c7606e39d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/ws/SearchActionTest.java
@@ -1,35 +1,79 @@
+/*
+ * 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.server.webhook.ws;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.config.PropertyDefinition;
+import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.Param;
import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.property.PropertyDbTester;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.setting.ws.SettingsFinder;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.Webhooks.SearchWsResponse;
+import org.sonarqube.ws.Webhooks.SearchWsResponse.Search;
+import static com.google.common.collect.ImmutableMap.of;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.tuple;
+import static org.junit.rules.ExpectedException.none;
+import static org.sonar.api.PropertyType.PROPERTY_SET;
+import static org.sonar.api.config.PropertyFieldDefinition.build;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.db.DbTester.create;
+import static org.sonar.server.tester.UserSessionRule.standalone;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.PROJECT_KEY_PARAM;
public class SearchActionTest {
@Rule
- public ExpectedException expectedException = ExpectedException.none();
+ public ExpectedException expectedException = none();
@Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
+ public UserSessionRule userSession = standalone();
@Rule
- public DbTester db = DbTester.create();
+ public DbTester db = create();
private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
-
- private org.sonar.server.webhook.ws.SearchAction underTest = new SearchAction(dbClient, userSession);
+ private PropertyDefinitions definitions = new PropertyDefinitions();
+ private SettingsFinder settingsFinder = new SettingsFinder(dbClient, definitions);
+ private SearchAction underTest = new SearchAction(dbClient, userSession, settingsFinder);
private WsActionTester wsActionTester = new WsActionTester(underTest);
+ private ComponentDbTester componentDbTester = new ComponentDbTester(db);
+
+ private PropertyDbTester propertyDb = new PropertyDbTester(db);
+
@Test
public void definition() {
@@ -40,10 +84,124 @@ public class SearchActionTest {
assertThat(action.isPost()).isFalse();
assertThat(action.responseExampleAsString()).isNotEmpty();
assertThat(action.params())
- .extracting(WebService.Param::key, WebService.Param::isRequired)
+ .extracting(Param::key, Param::isRequired)
.containsExactlyInAnyOrder(
tuple("organization", false),
tuple("project", false));
}
-} \ No newline at end of file
+ @Test
+ public void search_global_webhooks() {
+
+ definitions.addComponent(PropertyDefinition
+ .builder("sonar.webhooks.global")
+ .type(PROPERTY_SET)
+ .fields(asList(
+ build("name").name("name").build(),
+ build("url").name("url").build()))
+ .build());
+ propertyDb.insertPropertySet("sonar.webhooks.global", null,
+ of("name", "my first global webhook", "url", "http://127.0.0.1/first-global"),
+ of("name", "my second global webhook", "url", "http://127.0.0.1/second-global"));
+
+ userSession.logIn().setSystemAdministrator();
+
+ SearchWsResponse response = wsActionTester.newRequest()
+ .executeProtobuf(SearchWsResponse.class);
+
+ assertThat(response.getWebhooksList())
+ .extracting(Search::getName, Search::getUrl)
+ .containsExactly(tuple("my first global webhook", "http://127.0.0.1/first-global"),
+ tuple("my second global webhook", "http://127.0.0.1/second-global"));
+ }
+
+ @Test
+ public void search_project_webhooks_when_no_organization_is_provided() {
+ OrganizationDto defaultOrganization = db.getDefaultOrganization();
+ ComponentDto project = db.components().insertPublicProject(defaultOrganization);
+
+ definitions.addComponent(PropertyDefinition
+ .builder("sonar.webhooks.global")
+ .type(PROPERTY_SET)
+ .fields(asList(
+ build("name").name("name").build(),
+ build("url").name("url").build()))
+ .build());
+ propertyDb.insertPropertySet("sonar.webhooks.global", null,
+ of("name", "my first global webhook", "url", "http://127.0.0.1/first-global"),
+ of("name", "my second global webhook", "url", "http://127.0.0.1/second-global"));
+
+ definitions.addComponent(PropertyDefinition
+ .builder("sonar.webhooks.project")
+ .type(PROPERTY_SET)
+ .fields(asList(
+ build("name").name("name").build(),
+ build("url").name("url").build()))
+ .build());
+ propertyDb.insertPropertySet("sonar.webhooks.project", project,
+ of("name", "my first project webhook", "url", "http://127.0.0.1/first-project"),
+ of("name", "my second project webhook", "url", "http://127.0.0.1/second-project"));
+
+ userSession.logIn().addProjectPermission(ADMIN, project);
+
+ SearchWsResponse response = wsActionTester.newRequest()
+ .setParam(PROJECT_KEY_PARAM, project.getKey())
+ .executeProtobuf(SearchWsResponse.class);
+
+ assertThat(response.getWebhooksList())
+ .extracting(Search::getName, Search::getUrl)
+ .containsExactly(tuple("my first project webhook", "http://127.0.0.1/first-project"),
+ tuple("my second project webhook", "http://127.0.0.1/second-project"));
+
+ }
+
+ @Test
+ public void return_UnauthorizedException_if_not_logged_in() throws Exception {
+
+ userSession.anonymous();
+ expectedException.expect(UnauthorizedException.class);
+
+ wsActionTester.newRequest()
+ .executeProtobuf(SearchWsResponse.class);
+ }
+
+ @Test
+ public void return_NotFoundException_if_not_project_is_not_found() throws Exception {
+
+ userSession.logIn().setSystemAdministrator();
+ expectedException.expect(NotFoundException.class);
+
+ wsActionTester.newRequest()
+ .setParam(PROJECT_KEY_PARAM, "pipo")
+ .executeProtobuf(SearchWsResponse.class);
+ }
+
+ @Test
+ public void throw_ForbiddenException_if_not_organization_administrator() {
+
+ userSession.logIn();
+
+ expectedException.expect(ForbiddenException.class);
+ expectedException.expectMessage("Insufficient privileges");
+
+ wsActionTester.newRequest()
+ .executeProtobuf(SearchWsResponse.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(SearchWsResponse.class);
+
+ }
+
+}
diff --git a/server/sonar-web/src/main/js/api/webhooks.ts b/server/sonar-web/src/main/js/api/webhooks.ts
index fa526855e02..547702464b1 100644
--- a/server/sonar-web/src/main/js/api/webhooks.ts
+++ b/server/sonar-web/src/main/js/api/webhooks.ts
@@ -19,21 +19,7 @@
*/
import { getJSON } from '../helpers/request';
import throwGlobalError from '../app/utils/throwGlobalError';
-
-export interface Delivery {
- id: string;
- at: string;
- success: boolean;
- httpStatus: number;
- durationMs: number;
-}
-
-export interface Webhook {
- key: string;
- name: string;
- url: string;
- latestDelivery?: Delivery;
-}
+import { Webhook } from '../app/types';
export function searchWebhooks(data: {
organization: string | undefined;
diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts
index 13b8bac9f66..43f2c58bad5 100644
--- a/server/sonar-web/src/main/js/app/types.ts
+++ b/server/sonar-web/src/main/js/app/types.ts
@@ -383,3 +383,18 @@ export enum Visibility {
Public = 'public',
Private = 'private'
}
+
+export interface Webhook {
+ key: string;
+ latestDelivery?: WebhookDelivery;
+ name: string;
+ url: string;
+}
+
+export interface WebhookDelivery {
+ at: string;
+ durationMs: number;
+ httpStatus: number;
+ id: string;
+ success: boolean;
+}
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx
index 36f26f55913..e1d559ef307 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx
@@ -21,13 +21,13 @@ import * as React from 'react';
import { Helmet } from 'react-helmet';
import PageHeader from './PageHeader';
import WebhooksList from './WebhooksList';
-import { searchWebhooks, Webhook } from '../../../api/webhooks';
-import { LightComponent, Organization } from '../../../app/types';
+import { searchWebhooks } from '../../../api/webhooks';
+import { LightComponent, Organization, Webhook } from '../../../app/types';
import { translate } from '../../../helpers/l10n';
interface Props {
- organization: Organization | undefined;
component?: LightComponent;
+ organization: Organization | undefined;
}
interface State {
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx
index 1be6a9da181..f156900d581 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { Webhook } from '../../../api/webhooks';
+import { Webhook } from '../../../app/types';
interface Props {
webhook: Webhook;
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx
index 61689e75561..600fad4e8d3 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx
@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import WebhookItem from './WebhookItem';
-import { Webhook } from '../../../api/webhooks';
+import { Webhook } from '../../../app/types';
import { translate } from '../../../helpers/l10n';
interface Props {
@@ -36,21 +36,16 @@ export default class WebhooksList extends React.PureComponent<Props> {
</thead>
);
- renderNoWebhooks = () => (
- <tr>
- <td>{translate('webhooks.no_result')}</td>
- </tr>
- );
-
render() {
const { webhooks } = this.props;
+ if (webhooks.length < 1) {
+ return <p>{translate('webhooks.no_result')}</p>;
+ }
return (
<table className="data zebra">
{this.renderHeader()}
<tbody>
- {webhooks.length > 0
- ? webhooks.map(webhook => <WebhookItem key={webhook.key} webhook={webhook} />)
- : this.renderNoWebhooks()}
+ {webhooks.map(webhook => <WebhookItem key={webhook.key} webhook={webhook} />)}
</tbody>
</table>
);