import org.sonar.db.webhook.WebhookDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.Webhooks;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
-import static java.util.Optional.ofNullable;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.ACTION_CREATE;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.NAME_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.ORGANIZATION_KEY_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.ORGANIZATION_KEY_PARAM_MAXIMUM_LENGTH;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.PROJECT_KEY_PARAM;
-import static org.sonar.server.webhook.ws.WebhooksWsParameters.PROJECT_KEY_PARAM_MAXIMUN_LENGTH;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.PROJECT_KEY_PARAM_MAXIMUM_LENGTH;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.SECRET_PARAM;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.SECRET_PARAM_MAXIMUM_LENGTH;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.URL_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.URL_PARAM_MAXIMUM_LENGTH;
import static org.sonar.server.ws.KeyExamples.KEY_ORG_EXAMPLE_001;
private final WebhookSupport webhookSupport;
public CreateAction(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider,
- UuidFactory uuidFactory, WebhookSupport webhookSupport) {
+ UuidFactory uuidFactory, WebhookSupport webhookSupport) {
this.dbClient = dbClient;
this.userSession = userSession;
this.defaultOrganizationProvider = defaultOrganizationProvider;
@Override
public void define(WebService.NewController controller) {
-
WebService.NewAction action = controller.createAction(ACTION_CREATE)
.setPost(true)
.setDescription("Create a Webhook.<br>" +
action.createParam(PROJECT_KEY_PARAM)
.setRequired(false)
- .setMaximumLength(PROJECT_KEY_PARAM_MAXIMUN_LENGTH)
+ .setMaximumLength(PROJECT_KEY_PARAM_MAXIMUM_LENGTH)
.setDescription("The key of the project that will own the webhook")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
.setDescription("The key of the organization that will own the webhook")
.setExampleValue(KEY_ORG_EXAMPLE_001);
+ action.createParam(SECRET_PARAM)
+ .setRequired(false)
+ .setMinimumLength(1)
+ .setMaximumLength(SECRET_PARAM_MAXIMUM_LENGTH)
+ .setDescription("If provided, secret will be used as the key to generate the HMAC hex (lowercase) digest value in the 'X-Sonar-Webhook-HMAC-SHA256' header")
+ .setExampleValue("your_secret")
+ .setSince("7.8");
}
@Override
public void handle(Request request, Response response) throws Exception {
-
userSession.checkLoggedIn();
String name = request.mandatoryParam(NAME_PARAM);
String url = request.mandatoryParam(URL_PARAM);
String projectKey = request.param(PROJECT_KEY_PARAM);
String organizationKey = request.param(ORGANIZATION_KEY_PARAM);
+ String secret = request.param(SECRET_PARAM);
try (DbSession dbSession = dbClient.openSession(false)) {
-
OrganizationDto organizationDto;
if (isNotBlank(organizationKey)) {
Optional<OrganizationDto> dtoOptional = dbClient.organizationDao().selectByKey(dbSession, organizationKey);
ComponentDto projectDto = null;
if (isNotBlank(projectKey)) {
- Optional<ComponentDto> dtoOptional = ofNullable(dbClient.componentDao().selectByKey(dbSession, projectKey).orElse(null));
+ Optional<ComponentDto> dtoOptional = dbClient.componentDao().selectByKey(dbSession, projectKey);
ComponentDto componentDto = checkFoundWithOptional(dtoOptional, "No project with key '%s'", projectKey);
webhookSupport.checkThatProjectBelongsToOrganization(componentDto, organizationDto, "Project '%s' does not belong to organisation '%s'", projectKey, organizationKey);
webhookSupport.checkPermission(componentDto);
webhookSupport.checkUrlPattern(url, "Url parameter with value '%s' is not a valid url", url);
- WebhookDto webhookDto = doHandle(dbSession, organizationDto, projectDto, name, url);
-
- dbClient.webhookDao().insert(dbSession, webhookDto);
+ WebhookDto dto = doHandle(dbSession, organizationDto, projectDto, name, url, secret);
+ dbClient.webhookDao().insert(dbSession, dto);
dbSession.commit();
- writeResponse(request, response, webhookDto);
+ writeResponse(request, response, dto);
}
}
- private WebhookDto doHandle(DbSession dbSession, @Nullable OrganizationDto organization, @Nullable ComponentDto project, String name, String url) {
+ private WebhookDto doHandle(DbSession dbSession, @Nullable OrganizationDto organization,
+ @Nullable ComponentDto project, String name, String url, @Nullable String secret) {
checkState(organization != null || project != null,
"A webhook can not be created if not linked to an organization or a project.");
WebhookDto dto = new WebhookDto()
.setUuid(uuidFactory.create())
.setName(name)
- .setUrl(url);
+ .setUrl(url)
+ .setSecret(secret);
if (project != null) {
checkNumberOfWebhook(numberOfWebhookOf(dbSession, project), "Maximum number of webhook reached for project '%s'", project.getKey());
return dto;
}
- private static void writeResponse(Request request, Response response, WebhookDto element) {
- Webhooks.CreateWsResponse.Builder responseBuilder = newBuilder();
- responseBuilder.setWebhook(Webhook.newBuilder()
- .setKey(element.getUuid())
- .setName(element.getName())
- .setUrl(element.getUrl()));
-
- writeProtobuf(responseBuilder.build(), request, response);
+ private static void writeResponse(Request request, Response response, WebhookDto dto) {
+ Webhook.Builder webhookBuilder = Webhook.newBuilder();
+ webhookBuilder
+ .setKey(dto.getUuid())
+ .setName(dto.getName())
+ .setUrl(dto.getUrl());
+ if (dto.getSecret() != null) {
+ webhookBuilder.setSecret(dto.getSecret());
+ }
+ writeProtobuf(newBuilder().setWebhook(webhookBuilder).build(), request, response);
}
private static void checkNumberOfWebhook(int nbOfWebhooks, String message, Object... messageArguments) {
- if (nbOfWebhooks >= MAX_NUMBER_OF_WEBHOOKS){
+ if (nbOfWebhooks >= MAX_NUMBER_OF_WEBHOOKS) {
throw new IllegalArgumentException(format(message, messageArguments));
}
}
import static java.util.Optional.ofNullable;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.DELETE_ACTION;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM;
-import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM_MAXIMUN_LENGTH;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM_MAXIMUM_LENGTH;
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;
action.createParam(KEY_PARAM)
.setRequired(true)
- .setMaximumLength(KEY_PARAM_MAXIMUN_LENGTH)
+ .setMaximumLength(KEY_PARAM_MAXIMUM_LENGTH)
.setDescription("The key of the webhook to be deleted, "+
"auto-generated value can be obtained through api/webhooks/create or api/webhooks/list")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
package org.sonar.server.webhook.ws;
import java.util.Optional;
+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 static java.util.Optional.ofNullable;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM;
-import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM_MAXIMUN_LENGTH;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM_MAXIMUM_LENGTH;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.NAME_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.NAME_PARAM_MAXIMUM_LENGTH;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.SECRET_PARAM;
+import static org.sonar.server.webhook.ws.WebhooksWsParameters.SECRET_PARAM_MAXIMUM_LENGTH;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.UPDATE_ACTION;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.URL_PARAM;
import static org.sonar.server.webhook.ws.WebhooksWsParameters.URL_PARAM_MAXIMUM_LENGTH;
@Override
public void define(WebService.NewController controller) {
-
WebService.NewAction action = controller.createAction(UPDATE_ACTION)
.setPost(true)
.setDescription("Update a Webhook.<br>" +
action.createParam(KEY_PARAM)
.setRequired(true)
- .setMaximumLength(KEY_PARAM_MAXIMUN_LENGTH)
- .setDescription("The key of the webhook to be updated, "+
+ .setMaximumLength(KEY_PARAM_MAXIMUM_LENGTH)
+ .setDescription("The key of the webhook to be updated, " +
"auto-generated value can be obtained through api/webhooks/create or api/webhooks/list")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
.setDescription("new url to be called by the webhook")
.setExampleValue(URL_WEBHOOK_EXAMPLE_001);
+ action.createParam(SECRET_PARAM)
+ .setRequired(false)
+ .setMinimumLength(1)
+ .setMaximumLength(SECRET_PARAM_MAXIMUM_LENGTH)
+ .setDescription("If provided, secret will be used as the key to generate the HMAC hex (lowercase) digest value in the 'X-Sonar-Webhook-HMAC-SHA256' header")
+ .setExampleValue("your_secret")
+ .setSince("7.8");
}
@Override
String webhookKey = request.param(KEY_PARAM);
String name = request.mandatoryParam(NAME_PARAM);
String url = request.mandatoryParam(URL_PARAM);
+ String secret = request.param(SECRET_PARAM);
webhookSupport.checkUrlPattern(url, "Url parameter with value '%s' is not a valid url", url);
Optional<OrganizationDto> optionalDto = dbClient.organizationDao().selectByUuid(dbSession, organizationUuid);
OrganizationDto organizationDto = checkStateWithOptional(optionalDto, "the requested organization '%s' was not found", organizationUuid);
webhookSupport.checkPermission(organizationDto);
- updateWebhook(dbSession, webhookDto, name, url);
+ updateWebhook(dbSession, webhookDto, name, url, secret);
}
String projectUuid = webhookDto.getProjectUuid();
Optional<ComponentDto> optionalDto = ofNullable(dbClient.componentDao().selectByUuid(dbSession, projectUuid).orElse(null));
ComponentDto componentDto = checkStateWithOptional(optionalDto, "the requested project '%s' was not found", projectUuid);
webhookSupport.checkPermission(componentDto);
- updateWebhook(dbSession, webhookDto, name, url);
+ updateWebhook(dbSession, webhookDto, name, url, secret);
}
dbSession.commit();
response.noContent();
}
- private void updateWebhook(DbSession dbSession, WebhookDto webhookDto, String name, String url) {
- dbClient.webhookDao().update(dbSession, webhookDto.setName(name).setUrl(url));
+ private void updateWebhook(DbSession dbSession, WebhookDto dto, String name, String url, @Nullable String secret) {
+ dto
+ .setName(name)
+ .setUrl(url)
+ .setSecret(secret);
+ dbClient.webhookDao().update(dbSession, dto);
}
}
static final String ORGANIZATION_KEY_PARAM = "organization";
static final int ORGANIZATION_KEY_PARAM_MAXIMUM_LENGTH = 255;
static final String PROJECT_KEY_PARAM = "project";
- static final int PROJECT_KEY_PARAM_MAXIMUN_LENGTH = 100;
+ static final int PROJECT_KEY_PARAM_MAXIMUM_LENGTH = 100;
static final String NAME_PARAM = "name";
static final int NAME_PARAM_MAXIMUM_LENGTH = 100;
static final String URL_PARAM = "url";
static final int URL_PARAM_MAXIMUM_LENGTH = 512;
static final String KEY_PARAM = "webhook";
- static final int KEY_PARAM_MAXIMUN_LENGTH = 40;
+ static final int KEY_PARAM_MAXIMUM_LENGTH = 40;
+ static final String SECRET_PARAM = "secret";
+ static final int SECRET_PARAM_MAXIMUM_LENGTH = 200;
private WebhooksWsParameters() {
// prevent instantiation
"webhook": {
"key": "uuid",
"name": "My webhook",
- "url": "https://www.my-webhook-listener.com/sonar"
+ "url": "https://www.my-webhook-listener.com/sonar",
+ "secret": "your_secret"
}
-}
\ No newline at end of file
+}
@Test
public void test_ws_definition() {
-
WebService.Action action = wsActionTester.getDef();
assertThat(action).isNotNull();
assertThat(action.isInternal()).isFalse();
tuple("organization", false),
tuple("project", false),
tuple("name", true),
- tuple("url", true));
+ tuple("url", true),
+ tuple("secret", false));
}
@Test
- public void create_a_webhook_on_default_organization() {
-
+ public void create_a_webhook_with_secret() {
userSession.logIn().addPermission(ADMINISTER, defaultOrganizationProvider.get().getUuid());
CreateWsResponse response = wsActionTester.newRequest()
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
+ .setParam("secret", "a_secret")
.executeProtobuf(CreateWsResponse.class);
assertThat(response.getWebhook()).isNotNull();
assertThat(response.getWebhook().getKey()).isNotNull();
assertThat(response.getWebhook().getName()).isEqualTo(NAME_WEBHOOK_EXAMPLE_001);
assertThat(response.getWebhook().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
+ assertThat(response.getWebhook().getSecret()).isEqualTo("a_secret");
+ }
+ @Test
+ public void create_a_webhook_on_default_organization() {
+ userSession.logIn().addPermission(ADMINISTER, defaultOrganizationProvider.get().getUuid());
+
+ CreateWsResponse response = wsActionTester.newRequest()
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
+ .executeProtobuf(CreateWsResponse.class);
+
+ assertThat(response.getWebhook()).isNotNull();
+ assertThat(response.getWebhook().getKey()).isNotNull();
+ assertThat(response.getWebhook().getName()).isEqualTo(NAME_WEBHOOK_EXAMPLE_001);
+ assertThat(response.getWebhook().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
+ assertThat(response.getWebhook().hasSecret()).isFalse();
}
@Test
public void create_a_webhook_on_specific_organization() {
-
OrganizationDto organization = organizationDbTester.insert();
-
userSession.logIn().addPermission(ADMINISTER, organization.getUuid());
CreateWsResponse response = wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("organization", organization.getKey())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.executeProtobuf(CreateWsResponse.class);
assertThat(response.getWebhook()).isNotNull();
assertThat(response.getWebhook().getKey()).isNotNull();
assertThat(response.getWebhook().getName()).isEqualTo(NAME_WEBHOOK_EXAMPLE_001);
assertThat(response.getWebhook().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
-
+ assertThat(response.getWebhook().hasSecret()).isFalse();
}
@Test
public void create_a_webhook_on_project() {
-
ComponentDto project = componentDbTester.insertPrivateProject();
userSession.logIn().addProjectPermission(ADMIN, project);
CreateWsResponse response = wsActionTester.newRequest()
- .setParam(PROJECT_KEY_PARAM, project.getKey())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("project", project.getKey())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.executeProtobuf(CreateWsResponse.class);
assertThat(response.getWebhook()).isNotNull();
assertThat(response.getWebhook().getKey()).isNotNull();
assertThat(response.getWebhook().getName()).isEqualTo(NAME_WEBHOOK_EXAMPLE_001);
assertThat(response.getWebhook().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
-
+ assertThat(response.getWebhook().hasSecret()).isFalse();
}
@Test
public void create_a_webhook_on_a_project_belonging_to_an_organization() {
-
OrganizationDto organization = organizationDbTester.insert();
ComponentDto project = componentDbTester.insertPrivateProject(organization);
userSession.logIn().addProjectPermission(ADMIN, project);
CreateWsResponse response = wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
- .setParam(PROJECT_KEY_PARAM, project.getKey())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("organization", organization.getKey())
+ .setParam("project", project.getKey())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.executeProtobuf(CreateWsResponse.class);
assertThat(response.getWebhook()).isNotNull();
assertThat(response.getWebhook().getKey()).isNotNull();
assertThat(response.getWebhook().getName()).isEqualTo(NAME_WEBHOOK_EXAMPLE_001);
assertThat(response.getWebhook().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
-
+ assertThat(response.getWebhook().hasSecret()).isFalse();
}
@Test
public void fail_if_project_does_not_belong_to_requested_organization() {
-
OrganizationDto organization = organizationDbTester.insert();
ComponentDto project = componentDbTester.insertPrivateProject();
userSession.logIn().addProjectPermission(ADMIN, project);
wsActionTester.newRequest()
- .setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
- .setParam(PROJECT_KEY_PARAM, project.getKey())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("organization", organization.getKey())
+ .setParam("project", project.getKey())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
- public void fail_if_project_does_not_exists() {
-
+ public void fail_if_project_does_not_exist() {
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("No project with key 'inexistent-project-uuid'");
.setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
.setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
public void fail_if_crossing_maximum_quantity_of_webhooks_on_this_project() {
-
ComponentDto project = componentDbTester.insertPrivateProject();
expectedException.expect(IllegalArgumentException.class);
.setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
.setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
public void fail_if_crossing_maximum_quantity_of_webhooks_on_this_organization() {
-
OrganizationDto organization = organizationDbTester.insert();
expectedException.expect(IllegalArgumentException.class);
}
@Test
- public void fail_if_organization_does_not_exists() {
-
+ public void fail_if_organization_does_not_exist() {
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("No organization with key 'inexistent-organization-uuid'");
.setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
.setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
- public void fail_if_url_is_not_valid() throws Exception {
-
+ public void fail_if_url_is_not_valid() {
userSession.logIn().addPermission(ADMINISTER, defaultOrganizationProvider.get().getUuid());
expectedException.expect(IllegalArgumentException.class);
.setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
.setParam(URL_PARAM, "htp://www.wrong-protocol.com/")
.execute();
-
}
@Test
- public void fail_if_credential_in_url_is_have_a_wrong_format() throws Exception {
-
+ public void fail_if_credential_in_url_is_have_a_wrong_format() {
userSession.logIn().addPermission(ADMINISTER, defaultOrganizationProvider.get().getUuid());
expectedException.expect(IllegalArgumentException.class);
.setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
.setParam(URL_PARAM, "http://:www.wrong-protocol.com/")
.execute();
-
}
@Test
- public void return_UnauthorizedException_if_not_logged_in() throws Exception {
-
+ public void return_UnauthorizedException_if_not_logged_in() {
userSession.anonymous();
expectedException.expect(UnauthorizedException.class);
.setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
.setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
public void throw_ForbiddenException_if_no_organization_provided_and_user_is_not_system_administrator() {
-
userSession.logIn();
expectedException.expect(ForbiddenException.class);
@Test
public void throw_ForbiddenException_if_organization_provided_but_user_is_not_organization_administrator() {
-
OrganizationDto organization = organizationDbTester.insert();
userSession.logIn();
.setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
.setParam(ORGANIZATION_KEY_PARAM, organization.getKey())
.execute();
-
}
@Test
public void throw_ForbiddenException_if_not_project_administrator() {
-
ComponentDto project = componentDbTester.insertPrivateProject();
-
userSession.logIn();
expectedException.expect(ForbiddenException.class);
.setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
.setParam(PROJECT_KEY_PARAM, project.getKey())
.execute();
-
}
}
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.server.organization.TestDefaultOrganizationProvider.from;
import static org.sonar.server.tester.UserSessionRule.standalone;
-import static org.sonar.server.webhook.ws.WebhooksWsParameters.KEY_PARAM;
-import static org.sonar.server.webhook.ws.WebhooksWsParameters.NAME_PARAM;
-import static org.sonar.server.webhook.ws.WebhooksWsParameters.URL_PARAM;
import static org.sonar.server.ws.KeyExamples.NAME_WEBHOOK_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.URL_WEBHOOK_EXAMPLE_001;
@Test
public void test_ws_definition() {
-
WebService.Action action = wsActionTester.getDef();
assertThat(action).isNotNull();
assertThat(action.isInternal()).isFalse();
.containsExactlyInAnyOrder(
tuple("webhook", true),
tuple("name", true),
- tuple("url", true));
-
+ tuple("url", true),
+ tuple("secret", false));
}
@Test
- public void update_a_project_webhook() {
-
+ public void update_a_project_webhook_with_required_fields() {
ComponentDto project = componentDbTester.insertPrivateProject();
WebhookDto dto = webhookDbTester.insertWebhook(project);
userSession.logIn().addProjectPermission(ADMIN, project);
TestResponse response = wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.execute();
assertThat(response.getStatus()).isEqualTo(HTTP_NO_CONTENT);
assertThat(reloaded.get().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
assertThat(reloaded.get().getOrganizationUuid()).isNull();
assertThat(reloaded.get().getProjectUuid()).isEqualTo(dto.getProjectUuid());
+ assertThat(reloaded.get().getSecret()).isNull();
+ }
+
+ @Test
+ public void update_a_project_webhook_with_all_fields() {
+ ComponentDto project = componentDbTester.insertPrivateProject();
+ WebhookDto dto = webhookDbTester.insertWebhook(project);
+ userSession.logIn().addProjectPermission(ADMIN, project);
+
+ TestResponse response = wsActionTester.newRequest()
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
+ .setParam("secret", "a_new_secret")
+ .execute();
+ assertThat(response.getStatus()).isEqualTo(HTTP_NO_CONTENT);
+ Optional<WebhookDto> reloaded = webhookDbTester.selectWebhook(dto.getUuid());
+ assertThat(reloaded.get()).isNotNull();
+ assertThat(reloaded.get().getName()).isEqualTo(NAME_WEBHOOK_EXAMPLE_001);
+ assertThat(reloaded.get().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
+ assertThat(reloaded.get().getOrganizationUuid()).isNull();
+ assertThat(reloaded.get().getProjectUuid()).isEqualTo(dto.getProjectUuid());
+ assertThat(reloaded.get().getSecret()).isEqualTo("a_new_secret");
}
@Test
public void update_an_organization_webhook() {
-
OrganizationDto organization = organizationDbTester.insert();
WebhookDto dto = webhookDbTester.insertWebhook(organization);
userSession.logIn().addPermission(ADMINISTER, organization.getUuid());
TestResponse response = wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
+ .setParam("secret", "a_new_secret")
.execute();
assertThat(response.getStatus()).isEqualTo(HTTP_NO_CONTENT);
assertThat(reloaded.get().getUrl()).isEqualTo(URL_WEBHOOK_EXAMPLE_001);
assertThat(reloaded.get().getOrganizationUuid()).isEqualTo(dto.getOrganizationUuid());
assertThat(reloaded.get().getProjectUuid()).isNull();
-
+ assertThat(reloaded.get().getSecret()).isEqualTo("a_new_secret");
}
@Test
public void fail_if_webhook_does_not_exist() {
-
userSession.logIn().addPermission(ADMINISTER, defaultOrganizationProvider.get().getUuid());
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("No webhook with key 'inexistent-webhook-uuid'");
wsActionTester.newRequest()
- .setParam(KEY_PARAM, "inexistent-webhook-uuid")
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("webhook", "inexistent-webhook-uuid")
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.execute();
}
@Test
- public void fail_if_not_logged_in() throws Exception {
-
+ public void fail_if_not_logged_in() {
OrganizationDto organization = organizationDbTester.insert();
WebhookDto dto = webhookDbTester.insertWebhook(organization);
userSession.anonymous();
expectedException.expect(UnauthorizedException.class);
wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
public void fail_if_no_permission_on_webhook_scope_project() {
-
ComponentDto project = componentDbTester.insertPrivateProject();
WebhookDto dto = webhookDbTester.insertWebhook(project);
expectedException.expectMessage("Insufficient privileges");
wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
public void fail_if_no_permission_on_webhook_scope_organization() {
-
OrganizationDto organization = organizationDbTester.insert();
WebhookDto dto = webhookDbTester.insertWebhook(organization);
expectedException.expectMessage("Insufficient privileges");
wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, URL_WEBHOOK_EXAMPLE_001)
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", URL_WEBHOOK_EXAMPLE_001)
.execute();
-
}
@Test
- public void fail_if_url_is_not_valid() throws Exception {
-
+ public void fail_if_url_is_not_valid() {
ComponentDto project = componentDbTester.insertPrivateProject();
WebhookDto dto = webhookDbTester.insertWebhook(project);
userSession.logIn().addProjectPermission(ADMIN, project);
expectedException.expect(IllegalArgumentException.class);
wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, "htp://www.wrong-protocol.com/")
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", "htp://www.wrong-protocol.com/")
.execute();
-
}
@Test
- public void fail_if_credential_in_url_is_have_a_wrong_format() throws Exception {
-
+ public void fail_if_credential_in_url_is_have_a_wrong_format() {
ComponentDto project = componentDbTester.insertPrivateProject();
WebhookDto dto = webhookDbTester.insertWebhook(project);
userSession.logIn().addProjectPermission(ADMIN, project);
expectedException.expect(IllegalArgumentException.class);
wsActionTester.newRequest()
- .setParam(KEY_PARAM, dto.getUuid())
- .setParam(NAME_PARAM, NAME_WEBHOOK_EXAMPLE_001)
- .setParam(URL_PARAM, "http://:www.wrong-protocol.com/")
+ .setParam("webhook", dto.getUuid())
+ .setParam("name", NAME_WEBHOOK_EXAMPLE_001)
+ .setParam("url", "http://:www.wrong-protocol.com/")
.execute();
-
}
}
*/
package org.sonarqube.ws.client.webhooks;
-import java.util.List;
import javax.annotation.Generated;
/**
private String name;
private String organization;
private String project;
+ private String secret;
private String url;
/**
return project;
}
+ /**
+ * Example value: "your_secret"
+ */
+ public CreateRequest setSecret(String secret) {
+ this.secret = secret;
+ return this;
+ }
+
+ public String getSecret() {
+ return secret;
+ }
+
/**
* This is a mandatory parameter.
* Example value: "https://www.my-webhook-listener.com/sonar"
*/
package org.sonarqube.ws.client.webhooks;
-import java.util.List;
import javax.annotation.Generated;
/**
public class UpdateRequest {
private String name;
+ private String secret;
private String url;
private String webhook;
return name;
}
+ /**
+ * Example value: "your_secret"
+ */
+ public UpdateRequest setSecret(String secret) {
+ this.secret = secret;
+ return this;
+ }
+
+ public String getSecret() {
+ return secret;
+ }
+
/**
* This is a mandatory parameter.
* Example value: "https://www.my-webhook-listener.com/sonar"
.setParam("name", request.getName())
.setParam("organization", request.getOrganization())
.setParam("project", request.getProject())
+ .setParam("secret", request.getSecret())
.setParam("url", request.getUrl()),
CreateWsResponse.parser());
}
call(
new PostRequest(path("delete"))
.setParam("webhook", request.getWebhook())
- .setMediaType(MediaTypes.JSON)
- ).content();
+ .setMediaType(MediaTypes.JSON)).content();
}
/**
call(
new PostRequest(path("update"))
.setParam("name", request.getName())
+ .setParam("secret", request.getSecret())
.setParam("url", request.getUrl())
.setParam("webhook", request.getWebhook())
- .setMediaType(MediaTypes.JSON)
- ).content();
+ .setMediaType(MediaTypes.JSON)).content();
}
}
optional string key = 1;
optional string name = 2;
optional string url = 3;
+ optional string secret = 4;
}
}