Browse Source

SONAR-12000 add DB column webhooks.secret

tags/7.8
Simon Brandhof 5 years ago
parent
commit
d73b2ba4be

+ 1
- 0
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl View File

@@ -857,6 +857,7 @@ CREATE TABLE "WEBHOOKS" (
"URL" VARCHAR(2000) NOT NULL,
"ORGANIZATION_UUID" VARCHAR(40),
"PROJECT_UUID" VARCHAR(40),
"SECRET" VARCHAR(200),
"CREATED_AT" BIGINT NOT NULL,
"UPDATED_AT" BIGINT NOT NULL,


+ 16
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/webhook/WebhookDto.java View File

@@ -36,6 +36,12 @@ public class WebhookDto {
@Nullable
private String projectUuid;

/**
* The optional secret used to generate payload signature
*/
@Nullable
private String secret;

private long createdAt;
private long updatedAt;

@@ -64,6 +70,11 @@ public class WebhookDto {
return this;
}

public WebhookDto setSecret(@Nullable String s) {
this.secret = s;
return this;
}

WebhookDto setCreatedAt(long createdAt) {
this.createdAt = createdAt;
return this;
@@ -96,6 +107,11 @@ public class WebhookDto {
return projectUuid;
}

@Nullable
public String getSecret() {
return secret;
}

public long getCreatedAt() {
return createdAt;
}

+ 8
- 5
server/sonar-db-dao/src/main/resources/org/sonar/db/webhook/WebhookMapper.xml View File

@@ -10,11 +10,11 @@
url,
organization_uuid as organizationUuid,
project_uuid as projectUuid,
secret,
created_at as createdAt,
updated_at as updatedAt
</sql>


<select id="selectByUuid" parameterType="String" resultType="org.sonar.db.webhook.WebhookDto">
select <include refid="sqlColumns" />
from webhooks
@@ -42,6 +42,7 @@
url,
organization_uuid,
project_uuid,
secret,
created_at,
updated_at
) values (
@@ -50,6 +51,7 @@
#{url,jdbcType=VARCHAR},
#{organizationUuid,jdbcType=VARCHAR},
#{projectUuid,jdbcType=VARCHAR},
#{secret,jdbcType=VARCHAR},
#{createdAt,jdbcType=BIGINT},
#{updatedAt,jdbcType=BIGINT}
)
@@ -57,10 +59,11 @@

<update id="update" parameterType="org.sonar.db.webhook.WebhookDto">
update webhooks set
name=#{name},
url=#{url},
updated_at=#{updatedAt, jdbcType=BIGINT}
where uuid=#{uuid, jdbcType=VARCHAR}
name=#{name,jdbcType=VARCHAR},
url=#{url,jdbcType=VARCHAR},
secret=#{secret,jdbcType=VARCHAR},
updated_at=#{updatedAt,jdbcType=BIGINT}
where uuid=#{uuid,jdbcType=VARCHAR}
</update>

<delete id="delete" parameterType="String">

+ 32
- 15
server/sonar-db-dao/src/test/java/org/sonar/db/webhook/WebhookDaoTest.java View File

@@ -60,12 +60,12 @@ public class WebhookDaoTest {

@Test
public void insert_row_with_organization() {

WebhookDto dto = new WebhookDto()
.setUuid("UUID_1")
.setName("NAME_1")
.setUrl("URL_1")
.setOrganizationUuid("UUID_2");
.setOrganizationUuid("UUID_2")
.setSecret("a_secret");

underTest.insert(dbSession, dto);

@@ -76,18 +76,19 @@ public class WebhookDaoTest {
assertThat(stored.getUrl()).isEqualTo(dto.getUrl());
assertThat(stored.getOrganizationUuid()).isEqualTo(dto.getOrganizationUuid());
assertThat(stored.getProjectUuid()).isNull();
assertThat(stored.getSecret()).isEqualTo(dto.getSecret());
assertThat(new Date(stored.getCreatedAt())).isInSameMinuteWindowAs(new Date(system2.now()));
assertThat(new Date(stored.getUpdatedAt())).isInSameMinuteWindowAs(new Date(system2.now()));
}

@Test
public void insert_row_with_project() {

WebhookDto dto = new WebhookDto()
.setUuid("UUID_1")
.setName("NAME_1")
.setUrl("URL_1")
.setProjectUuid("UUID_2");
.setProjectUuid("UUID_2")
.setSecret("a_secret");

underTest.insert(dbSession, dto);

@@ -98,17 +99,41 @@ public class WebhookDaoTest {
assertThat(reloaded.getUrl()).isEqualTo(dto.getUrl());
assertThat(reloaded.getOrganizationUuid()).isNull();
assertThat(reloaded.getProjectUuid()).isEqualTo(dto.getProjectUuid());
assertThat(reloaded.getSecret()).isEqualTo(dto.getSecret());
assertThat(new Date(reloaded.getCreatedAt())).isInSameMinuteWindowAs(new Date(system2.now()));
assertThat(new Date(reloaded.getUpdatedAt())).isInSameMinuteWindowAs(new Date(system2.now()));
}

@Test
public void update() {
public void update_with_only_required_fields() {
OrganizationDto organization = organizationDbTester.insert();
WebhookDto dto = webhookDbTester.insertWebhook(organization);

underTest.update(dbSession, dto
.setName("a-fancy-webhook")
.setUrl("http://www.fancy-webhook.io")
.setSecret(null));

WebhookDto reloaded = underTest.selectByUuid(dbSession, dto.getUuid()).get();
assertThat(reloaded.getUuid()).isEqualTo(dto.getUuid());
assertThat(reloaded.getName()).isEqualTo("a-fancy-webhook");
assertThat(reloaded.getUrl()).isEqualTo("http://www.fancy-webhook.io");
assertThat(reloaded.getProjectUuid()).isNull();
assertThat(reloaded.getOrganizationUuid()).isEqualTo(dto.getOrganizationUuid());
assertThat(reloaded.getSecret()).isNull();
assertThat(reloaded.getCreatedAt()).isEqualTo(dto.getCreatedAt());
assertThat(new Date(reloaded.getUpdatedAt())).isInSameMinuteWindowAs(new Date(system2.now()));
}

@Test
public void update_with_all_fields() {
OrganizationDto organization = organizationDbTester.insert();
WebhookDto dto = webhookDbTester.insertWebhook(organization);

underTest.update(dbSession, dto.setName("a-fancy-webhook").setUrl("http://www.fancy-webhook.io"));
underTest.update(dbSession, dto
.setName("a-fancy-webhook")
.setUrl("http://www.fancy-webhook.io")
.setSecret("a_new_secret"));

WebhookDto reloaded = underTest.selectByUuid(dbSession, dto.getUuid()).get();
assertThat(reloaded.getUuid()).isEqualTo(dto.getUuid());
@@ -116,13 +141,13 @@ public class WebhookDaoTest {
assertThat(reloaded.getUrl()).isEqualTo("http://www.fancy-webhook.io");
assertThat(reloaded.getProjectUuid()).isNull();
assertThat(reloaded.getOrganizationUuid()).isEqualTo(dto.getOrganizationUuid());
assertThat(reloaded.getSecret()).isEqualTo("a_new_secret");
assertThat(reloaded.getCreatedAt()).isEqualTo(dto.getCreatedAt());
assertThat(new Date(reloaded.getUpdatedAt())).isInSameMinuteWindowAs(new Date(system2.now()));
}

@Test
public void cleanWebhooksOfAProject() {

OrganizationDto organization = organizationDbTester.insert();
ComponentDto componentDto = componentDbTester.insertPrivateProject(organization);
webhookDbTester.insertWebhook(componentDto);
@@ -138,7 +163,6 @@ public class WebhookDaoTest {

@Test
public void cleanWebhooksOfAnOrganization() {

OrganizationDto organization = organizationDbTester.insert();
webhookDbTester.insertWebhook(organization);
webhookDbTester.insertWebhook(organization);
@@ -153,9 +177,7 @@ public class WebhookDaoTest {

@Test
public void delete() {

OrganizationDto organization = organizationDbTester.insert();

WebhookDto dto = webhookDbTester.insertWebhook(organization);

underTest.delete(dbSession, dto.getUuid());
@@ -164,10 +186,8 @@ public class WebhookDaoTest {
assertThat(reloaded).isEmpty();
}


@Test
public void fail_if_webhook_does_not_have_an_organization_nor_a_project() {

expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("A webhook can not be created if not linked to an organization or a project.");

@@ -177,12 +197,10 @@ public class WebhookDaoTest {
.setUrl("URL_1");

underTest.insert(dbSession, dto);

}

@Test
public void fail_if_webhook_have_both_an_organization_nor_a_project() {

expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("A webhook can not be linked to both an organization and a project.");

@@ -194,7 +212,6 @@ public class WebhookDaoTest {
.setProjectUuid("UUID_3");

underTest.insert(dbSession, dto);

}

private WebhookDto selectByUuid(String uuid) {

+ 1
- 0
server/sonar-db-dao/src/test/java/org/sonar/db/webhook/WebhookTesting.java View File

@@ -62,6 +62,7 @@ public class WebhookTesting {
.setUuid(randomAlphanumeric(40))
.setName(randomAlphanumeric(64))
.setUrl("https://www.random-site/" + randomAlphanumeric(256))
.setSecret(randomAlphanumeric(10))
.setCreatedAt(Calendar.getInstance().getTimeInMillis());
Arrays.stream(consumers).forEach(consumer -> consumer.accept(res));
return res;

+ 47
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v78/AddWebhooksSecret.java View File

@@ -0,0 +1,47 @@
/*
* SonarQube
* Copyright (C) 2009-2019 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.platform.db.migration.version.v78;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.SupportsBlueGreen;
import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;

import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;

@SupportsBlueGreen
public class AddWebhooksSecret extends DdlChange {

public AddWebhooksSecret(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
context.execute(new AddColumnsBuilder(getDialect(), "webhooks")
.addColumn(newVarcharColumnDefBuilder()
.setColumnName("secret")
.setIsNullable(true)
.setLimit(200)
.build())
.build());
}
}

+ 2
- 1
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v78/DbVersion78.java View File

@@ -28,6 +28,7 @@ public class DbVersion78 implements DbVersion {
public void addSteps(MigrationStepRegistry registry) {
registry
.add(2700, "Drop overall subscriptions on notifications about new and resolved issues", DeleteOverallSubscriptionsOnNewAndResolvedIssuesNotifications.class)
.add(2701, "Add index to org_qprofile.parent_uuid", AddIndexToOrgQProfileParentUuid.class);
.add(2701, "Add index to org_qprofile.parent_uuid", AddIndexToOrgQProfileParentUuid.class)
.add(2702, "Add column webhooks.secret", AddWebhooksSecret.class);
}
}

+ 55
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v78/AddWebhooksSecretTest.java View File

@@ -0,0 +1,55 @@
/*
* SonarQube
* Copyright (C) 2009-2019 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.platform.db.migration.version.v78;

import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DdlChange;

import static java.sql.Types.VARCHAR;

public class AddWebhooksSecretTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(AddWebhooksSecretTest.class, "webhooks.sql");

private DdlChange underTest = new AddWebhooksSecret(db.database());

@Test
public void creates_table_on_empty_db() throws SQLException {
underTest.execute();

db.assertColumnDefinition("webhooks", "secret", VARCHAR, 200, true);
}

@Test
public void migration_is_not_reentrant() throws SQLException {
underTest.execute();

expectedException.expect(IllegalStateException.class);

underTest.execute();
}
}

+ 13
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v78/AddWebhooksSecretTest/webhooks.sql View File

@@ -0,0 +1,13 @@
CREATE TABLE "WEBHOOKS" (
"UUID" VARCHAR(40) NOT NULL,
"NAME" VARCHAR(100) NOT NULL,
"URL" VARCHAR(2000) NOT NULL,
"ORGANIZATION_UUID" VARCHAR(40),
"PROJECT_UUID" VARCHAR(40),
"CREATED_AT" BIGINT NOT NULL,
"UPDATED_AT" BIGINT NOT NULL,

CONSTRAINT "PK_WEBHOOKS" PRIMARY KEY ("UUID")
);
CREATE INDEX "ORGANIZATION_WEBHOOK" ON "WEBHOOKS" ("ORGANIZATION_UUID");
CREATE INDEX "PROJECT_WEBHOOK" ON "WEBHOOKS" ("PROJECT_UUID");

Loading…
Cancel
Save