Skip to content

Commit

Permalink
SONAR-10345 Add Webhooks creation ws
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume Jambet authored and gjambet committed Mar 1, 2018
1 parent fd1ca85 commit 67ac2e4
Show file tree
Hide file tree
Showing 13 changed files with 525 additions and 18 deletions.
@@ -0,0 +1,49 @@
/*
* SonarQube
* Copyright (C) 2009-2018 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.db.webhook;

import java.util.Calendar;

import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;

public class WebhookTesting {

private WebhookTesting() {
// only statics
}

public static WebhookDto newWebhookDtoForProject(String projectUuid) {
return getWebhookDto()
.setProjectUuid(projectUuid);
}

public static WebhookDto newWebhookDtoForOrganization(String organizationUuid) {
return getWebhookDto()
.setOrganizationUuid(organizationUuid);
}

private static WebhookDto getWebhookDto() {
return new WebhookDto()
.setUuid(randomAlphanumeric(40))
.setName(randomAlphanumeric(64))
.setUrl("https://www.random-site/" + randomAlphanumeric(256))
.setCreatedAt(Calendar.getInstance().getTimeInMillis());
}
}
7 changes: 7 additions & 0 deletions server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
Expand Up @@ -48,6 +48,7 @@
import org.sonar.db.source.FileSourceTester;
import org.sonar.db.user.RootFlagAssertions;
import org.sonar.db.user.UserDbTester;
import org.sonar.db.webhook.WebhookDbTester;

import static com.google.common.base.Preconditions.checkState;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
Expand Down Expand Up @@ -83,6 +84,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
private final MeasureDbTester measureDbTester;
private final FileSourceTester fileSourceTester;
private final PluginDbTester pluginDbTester;
private final WebhookDbTester webhookDbTester;

public DbTester(System2 system2, @Nullable String schemaPath) {
super(TestDb.create(schemaPath));
Expand All @@ -106,6 +108,7 @@ public DbTester(System2 system2, @Nullable String schemaPath) {
this.measureDbTester = new MeasureDbTester(this);
this.fileSourceTester = new FileSourceTester(this);
this.pluginDbTester = new PluginDbTester(this);
this.webhookDbTester = new WebhookDbTester(this);
}

public static DbTester create() {
Expand Down Expand Up @@ -248,6 +251,10 @@ public PluginDbTester pluginDbTester() {
return pluginDbTester;
}

public WebhookDbTester webhooks(){
return webhookDbTester;
}

@Override
protected void after() {
if (session != null) {
Expand Down
@@ -0,0 +1,48 @@
/*
* SonarQube
* Copyright (C) 2009-2018 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.db.webhook;

import org.sonar.db.DbSession;
import org.sonar.db.DbTester;

public class WebhookDbTester {

private final DbTester dbTester;

public WebhookDbTester(DbTester dbTester) {
this.dbTester = dbTester;
}

public WebhookDto insertForOrganizationUuid(String organizationUuid) {
return insert(WebhookTesting.newWebhookDtoForOrganization(organizationUuid));
}

public WebhookDto insertWebhookForProjectUuid(String projectUuid) {
return insert(WebhookTesting.newWebhookDtoForProject(projectUuid));
}

public WebhookDto insert(WebhookDto dto) {
DbSession dbSession = dbTester.getSession();
dbTester.getDbClient().webhookDao().insert(dbSession, dto);
dbSession.commit();
return dto;
}

}
Expand Up @@ -24,7 +24,6 @@
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
Expand Down Expand Up @@ -56,6 +55,7 @@
import static org.sonar.server.ws.KeyExamples.NAME_WEBHOOK_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.URL_WEBHOOK_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.CreateWsResponse.Webhook;
import static org.sonarqube.ws.Webhooks.CreateWsResponse.newBuilder;
Expand All @@ -68,14 +68,12 @@ public class CreateAction implements WebhooksWsAction {
private final UserSession userSession;
private final DefaultOrganizationProvider defaultOrganizationProvider;
private final UuidFactory uuidFactory;
private final System2 system;

public CreateAction(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider, UuidFactory uuidFactory, System2 system) {
public CreateAction(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider, UuidFactory uuidFactory) {
this.dbClient = dbClient;
this.userSession = userSession;
this.defaultOrganizationProvider = defaultOrganizationProvider;
this.uuidFactory = uuidFactory;
this.system = system;
}

@Override
Expand Down Expand Up @@ -126,7 +124,7 @@ public void handle(Request request, Response response) throws Exception {
String projectKey = request.param(PROJECT_KEY_PARAM);
String organizationKey = request.param(ORGANIZATION_KEY_PARAM);

try (DbSession dbSession = dbClient.openSession(true)) {
try (DbSession dbSession = dbClient.openSession(false)) {

OrganizationDto organizationDto;
if (isNotBlank(organizationKey)) {
Expand All @@ -138,18 +136,24 @@ public void handle(Request request, Response response) throws Exception {

ComponentDto projectDto = null;
if (isNotBlank(projectKey)) {
com.google.common.base.Optional<ComponentDto> dtoOptional = dbClient.componentDao().selectByKey(dbSession, projectKey);
checkFoundWithOptional(dtoOptional, "No project with key '%s'", projectKey);
checkThatProjectBelongsToOrganization(dtoOptional.get(), organizationDto, "Project '%s' does not belong to organisation '%s'", projectKey, organizationKey);
checkUserPermissionOn(dtoOptional.get());
projectDto = dtoOptional.get();
Optional<ComponentDto> dtoOptional = Optional.ofNullable(dbClient.componentDao().selectByKey(dbSession, projectKey).orNull());
ComponentDto componentDto = checkFoundWithOptional(dtoOptional, "No project with key '%s'", projectKey);
checkThatProjectBelongsToOrganization(componentDto, organizationDto, "Project '%s' does not belong to organisation '%s'", projectKey, organizationKey);
checkUserPermissionOn(componentDto);
projectDto = componentDto;
} else {
checkUserPermissionOn(organizationDto);
}

checkUrlPattern(url, "Url parameter with value '%s' is not a valid url", url);

writeResponse(request, response, doHandle(dbSession, organizationDto, projectDto, name, url));
WebhookDto webhookDto = doHandle(dbSession, organizationDto, projectDto, name, url);

dbClient.webhookDao().insert(dbSession, webhookDto);

dbSession.commit();

writeResponse(request, response, webhookDto);
}

}
Expand All @@ -172,8 +176,6 @@ private WebhookDto doHandle(DbSession dbSession, @Nullable OrganizationDto organ
dto.setOrganizationUuid(organization.getUuid());
}

dbClient.webhookDao().insert(dbSession, dto);

return dto;
}

Expand Down Expand Up @@ -227,6 +229,7 @@ private static void checkUrlPattern(String url, String message, Object... messag

private OrganizationDto defaultOrganizationDto(DbSession dbSession) {
String uuid = defaultOrganizationProvider.get().getUuid();
return dbClient.organizationDao().selectByUuid(dbSession, uuid).get();
Optional<OrganizationDto> organizationDto = dbClient.organizationDao().selectByUuid(dbSession, uuid);
return checkStateWithOptional(organizationDto, "the default organization '%s' was not found", uuid);
}
}
Expand Up @@ -27,6 +27,7 @@ protected void configureModule() {
add(
WebhooksWs.class,
SearchAction.class,
CreateAction.class,
WebhookDeliveryAction.class,
WebhookDeliveriesAction.class);
}
Expand Down
Expand Up @@ -23,13 +23,24 @@ class WebhooksWsParameters {

static final String WEBHOOKS_CONTROLLER = "api/webhooks";


static final String ACTION_CREATE = "create";
static final String SEARCH_ACTION = "search";


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 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 COMPONENT_KEY_PARAM = "component";
static final int COMPONENT_KEY_PARAM_MAXIMUM_LENGTH = 255;

private WebhooksWsParameters() {
// hiding constructor
// prevent instantiation
}

}
Expand Up @@ -31,6 +31,9 @@ public class KeyExamples {

public static final String KEY_BRANCH_EXAMPLE_001 = "feature/my_branch";

public static final String NAME_WEBHOOK_EXAMPLE_001 = "my-webhook";
public static final String URL_WEBHOOK_EXAMPLE_001 = "https://www.my-webhook-listener.com/sonar";

private KeyExamples() {
// prevent instantiation
}
Expand Down
Expand Up @@ -109,4 +109,12 @@ public static <T> T checkFoundWithOptional(java.util.Optional<T> value, String m

return value.get();
}

public static <T> T checkStateWithOptional(java.util.Optional<T> value, String message, Object... messageArguments) {
if (!value.isPresent()) {
throw new IllegalStateException(format(message, messageArguments));
}

return value.get();
}
}
@@ -0,0 +1,7 @@
{
"webhook": {
"key": "uuid",
"name": "my-webhook",
"url": "https://www.my-webhook-listener.com/sonar"
}
}

0 comments on commit 67ac2e4

Please sign in to comment.