aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2019-10-08 17:51:53 +0200
committersonartech <sonartech@sonarsource.com>2019-11-06 10:04:19 +0100
commit58d04f69bb33f17cfe6db3d9885fe4c9adabd2d1 (patch)
treebc48a5c0b0e2884ffa6ec2b61c99326844f030ba /server
parentf8c9b9c8b3e7040907e0ded89511f86b827449ad (diff)
downloadsonarqube-58d04f69bb33f17cfe6db3d9885fe4c9adabd2d1.tar.gz
sonarqube-58d04f69bb33f17cfe6db3d9885fe4c9adabd2d1.zip
SONAR-12512 Allow configuration of multiple GitHub instances
Diffstat (limited to 'server')
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java4
-rw-r--r--server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java1
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java7
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/ALM.java36
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDao.java73
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDto.java127
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingMapper.java41
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/package-info.java24
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/alm/setting/AlmSettingMapper.xml86
-rw-r--r--server/sonar-db-dao/src/schema/schema-sq.ddl14
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java2
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/alm/setting/AlmSettingDaoTest.java140
-rw-r--r--server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java7
-rw-r--r--server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsDbTester.java47
-rw-r--r--server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsTesting.java37
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java4
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTable.java109
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81.java31
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/package-info.java23
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTableTest.java65
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81Test.java43
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWs.java42
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsAction.java26
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsModule.java34
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/CreateGithubAction.java102
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/DeleteAction.java77
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ListDefinitionsAction.java86
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/UpdateGitHubAction.java114
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/package-info.java24
-rw-r--r--server/sonar-webserver-webapi/src/main/resources/org/sonar/server/almsettings/list_definitions-example.json10
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/AlmSettingsWsModuleTest.java38
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/CreateGithubActionTest.java107
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/DeleteActionTest.java97
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/ListDefinitionsActionTest.java114
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/UpdateGithubActionTest.java151
-rw-r--r--server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java2
40 files changed, 1947 insertions, 6 deletions
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
index 1e9ae9a5156..c44ad41287f 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
@@ -123,12 +123,12 @@ public class ComputeEngineContainerImplTest {
assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize(
CONTAINER_ITSELF
+ 6 // MigrationConfigurationModule
- + 15 // level 2
+ + 16 // level 2
);
assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
+ 27 // level 1
- + 63 // content of DaoModule
+ + 64 // content of DaoModule
+ 3 // content of EsModule
+ 51 // content of CorePropertyDefinitions
+ 1 // StopFlagContainer
diff --git a/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java b/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
index 160fa40e821..a2b67326dd3 100644
--- a/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
+++ b/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
@@ -53,6 +53,7 @@ public final class SqTables {
"active_rules",
"active_rule_parameters",
"alm_app_installs",
+ "alm_settings",
"analysis_properties",
"ce_activity",
"ce_queue",
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
index f5cca91191f..add145bf020 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.List;
import org.sonar.core.platform.Module;
import org.sonar.db.alm.AlmAppInstallDao;
+import org.sonar.db.alm.setting.AlmSettingDao;
import org.sonar.db.alm.OrganizationAlmBindingDao;
import org.sonar.db.alm.ProjectAlmBindingDao;
import org.sonar.db.ce.CeActivityDao;
@@ -115,6 +116,7 @@ public class DaoModule extends Module {
GroupMembershipDao.class,
GroupPermissionDao.class,
AlmAppInstallDao.class,
+ AlmSettingDao.class,
ProjectAlmBindingDao.class,
InternalComponentPropertiesDao.class,
InternalPropertiesDao.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
index 33fbf8d2662..fea23b1b590 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
@@ -24,6 +24,7 @@ import java.util.Map;
import org.sonar.db.alm.AlmAppInstallDao;
import org.sonar.db.alm.OrganizationAlmBindingDao;
import org.sonar.db.alm.ProjectAlmBindingDao;
+import org.sonar.db.alm.setting.AlmSettingDao;
import org.sonar.db.ce.CeActivityDao;
import org.sonar.db.ce.CeQueueDao;
import org.sonar.db.ce.CeScannerContextDao;
@@ -99,6 +100,7 @@ public class DbClient {
private final QualityProfileExportDao qualityProfileExportDao;
private final PropertiesDao propertiesDao;
private final AlmAppInstallDao almAppInstallDao;
+ private final AlmSettingDao almSettingDao;
private final ProjectAlmBindingDao projectAlmBindingDao;
private final InternalComponentPropertiesDao internalComponentPropertiesDao;
private final InternalPropertiesDao internalPropertiesDao;
@@ -165,6 +167,7 @@ public class DbClient {
map.put(dao.getClass(), dao);
}
almAppInstallDao = getDao(map, AlmAppInstallDao.class);
+ almSettingDao = getDao(map, AlmSettingDao.class);
projectAlmBindingDao = getDao(map, ProjectAlmBindingDao.class);
schemaMigrationDao = getDao(map, SchemaMigrationDao.class);
authorizationDao = getDao(map, AuthorizationDao.class);
@@ -241,6 +244,10 @@ public class DbClient {
return almAppInstallDao;
}
+ public AlmSettingDao almSettingDao() {
+ return almSettingDao;
+ }
+
public ProjectAlmBindingDao projectAlmBindingsDao() {
return projectAlmBindingDao;
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
index e9bf8807ba5..09cce2fab5a 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
@@ -38,6 +38,7 @@ import org.sonar.db.alm.AlmAppInstallMapper;
import org.sonar.db.alm.OrganizationAlmBindingMapper;
import org.sonar.db.alm.ProjectAlmBindingDto;
import org.sonar.db.alm.ProjectAlmBindingMapper;
+import org.sonar.db.alm.setting.AlmSettingMapper;
import org.sonar.db.ce.CeActivityMapper;
import org.sonar.db.ce.CeQueueMapper;
import org.sonar.db.ce.CeScannerContextMapper;
@@ -224,6 +225,7 @@ public class MyBatis implements Startable {
Class<?>[] mappers = {
ActiveRuleMapper.class,
AlmAppInstallMapper.class,
+ AlmSettingMapper.class,
AnalysisPropertiesMapper.class,
AuthorizationMapper.class,
BranchMapper.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/ALM.java b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/ALM.java
new file mode 100644
index 00000000000..e99482e3ed8
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/ALM.java
@@ -0,0 +1,36 @@
+/*
+ * 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.db.alm.setting;
+
+import java.util.Locale;
+
+public enum ALM {
+ GITHUB,
+ BITBUCKET,
+ AZURE_DEVOPS;
+
+ public static ALM fromId(String almId) {
+ return ALM.valueOf(almId.toUpperCase(Locale.ENGLISH));
+ }
+
+ public String getId() {
+ return this.name().toLowerCase(Locale.ENGLISH);
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDao.java
new file mode 100644
index 00000000000..d416dcb72f7
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDao.java
@@ -0,0 +1,73 @@
+/*
+ * 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.db.alm.setting;
+
+import java.util.List;
+import java.util.Optional;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+public class AlmSettingDao implements Dao {
+
+ private final System2 system2;
+ private final UuidFactory uuidFactory;
+
+ public AlmSettingDao(System2 system2, UuidFactory uuidFactory) {
+ this.system2 = system2;
+ this.uuidFactory = uuidFactory;
+ }
+
+ private static AlmSettingMapper getMapper(DbSession dbSession) {
+ return dbSession.getMapper(AlmSettingMapper.class);
+ }
+
+ public void insert(DbSession dbSession, AlmSettingDto almSettingDto) {
+ String uuid = uuidFactory.create();
+ long now = system2.now();
+ getMapper(dbSession).insert(almSettingDto, uuid, now);
+ almSettingDto.setUuid(uuid);
+ almSettingDto.setCreatedAt(now);
+ almSettingDto.setUpdatedAt(now);
+ }
+
+ public Optional<AlmSettingDto> selectByUuid(DbSession dbSession, String uuid) {
+ return Optional.ofNullable(getMapper(dbSession).selectByUuid(uuid));
+ }
+
+ public Optional<AlmSettingDto> selectByKey(DbSession dbSession, String key) {
+ return Optional.ofNullable(getMapper(dbSession).selectByKey(key));
+ }
+
+ public List<AlmSettingDto> selectAll(DbSession dbSession) {
+ return getMapper(dbSession).selectAll();
+ }
+
+ public void delete(DbSession dbSession, AlmSettingDto almSettingDto){
+ getMapper(dbSession).deleteByKey(almSettingDto.getKey());
+ }
+
+ public void update(DbSession dbSession, AlmSettingDto almSettingDto) {
+ long now = system2.now();
+ getMapper(dbSession).update(almSettingDto, now);
+ almSettingDto.setUpdatedAt(now);
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDto.java
new file mode 100644
index 00000000000..82f5db0b6d2
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingDto.java
@@ -0,0 +1,127 @@
+/*
+ * 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.db.alm.setting;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class AlmSettingDto {
+
+ private String uuid;
+ private String key;
+ private String rawAlm;
+ private String url;
+ private String appId;
+ private String privateKey;
+ private String personalAccessToken;
+ private long updatedAt;
+ private long createdAt;
+
+ String getUuid() {
+ return uuid;
+ }
+
+ void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public AlmSettingDto setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ public ALM getAlm() {
+ return ALM.fromId(rawAlm);
+ }
+
+ public AlmSettingDto setAlm(ALM alm) {
+ rawAlm = alm.getId();
+ return this;
+ }
+
+ public String getRawAlm() {
+ return rawAlm;
+ }
+
+ public AlmSettingDto setRawAlm(String rawAlm) {
+ this.rawAlm = rawAlm;
+ return this;
+ }
+
+ @CheckForNull
+ public String getUrl() {
+ return url;
+ }
+
+ public AlmSettingDto setUrl(@Nullable String url) {
+ this.url = url;
+ return this;
+ }
+
+ @CheckForNull
+ public String getAppId() {
+ return appId;
+ }
+
+ public AlmSettingDto setAppId(@Nullable String appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ @CheckForNull
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public AlmSettingDto setPrivateKey(@Nullable String privateKey) {
+ this.privateKey = privateKey;
+ return this;
+ }
+
+ @CheckForNull
+ public String getPersonalAccessToken() {
+ return personalAccessToken;
+ }
+
+ public AlmSettingDto setPersonalAccessToken(@Nullable String personalAccessToken) {
+ this.personalAccessToken = personalAccessToken;
+ return this;
+ }
+
+ long getUpdatedAt() {
+ return updatedAt;
+ }
+
+ void setUpdatedAt(long updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ long getCreatedAt() {
+ return createdAt;
+ }
+
+ void setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingMapper.java
new file mode 100644
index 00000000000..584cd4a648c
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/AlmSettingMapper.java
@@ -0,0 +1,41 @@
+/*
+ * 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.db.alm.setting;
+
+import java.util.List;
+import javax.annotation.CheckForNull;
+import org.apache.ibatis.annotations.Param;
+
+public interface AlmSettingMapper {
+
+ @CheckForNull
+ AlmSettingDto selectByUuid(@Param("uuid") String uuid);
+
+ @CheckForNull
+ AlmSettingDto selectByKey(@Param("key") String key);
+
+ List<AlmSettingDto> selectAll();
+
+ void insert(@Param("dto") AlmSettingDto almSettingDto, @Param("uuid") String uuid, @Param("now") long now);
+
+ void update(@Param("dto") AlmSettingDto almSettingDto, @Param("now") long now);
+
+ void deleteByKey(@Param("key") String key);
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/package-info.java b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/package-info.java
new file mode 100644
index 00000000000..1e3bea4ce3a
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/alm/setting/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.db.alm.setting;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/alm/setting/AlmSettingMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/alm/setting/AlmSettingMapper.xml
new file mode 100644
index 00000000000..bf66e2983fe
--- /dev/null
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/alm/setting/AlmSettingMapper.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.db.alm.setting.AlmSettingMapper">
+
+ <sql id="sqlColumns">
+ a.kee as key,
+ a.uuid as uuid,
+ a.alm_id as rawAlm,
+ a.url as url,
+ a.app_id as appId,
+ a.private_key as privateKey,
+ a.pat as personalAccessToken,
+ a.created_at as createdAt,
+ a.updated_at as updatedAt
+ </sql>
+
+ <select id="selectByUuid" parameterType="string" resultType="org.sonar.db.alm.setting.AlmSettingDto">
+ select <include refid="sqlColumns"/>
+ from
+ alm_settings a
+ where
+ a.uuid = #{uuid, jdbcType=VARCHAR}
+ </select>
+
+ <select id="selectByKey" parameterType="string" resultType="org.sonar.db.alm.setting.AlmSettingDto">
+ select <include refid="sqlColumns"/>
+ from
+ alm_settings a
+ where
+ a.kee = #{key, jdbcType=VARCHAR}
+ </select>
+
+ <select id="selectAll" resultType="org.sonar.db.alm.setting.AlmSettingDto">
+ select <include refid="sqlColumns"/>
+ from alm_settings a
+ </select>
+
+
+ <insert id="insert" parameterType="Map" useGeneratedKeys="false">
+ INSERT INTO alm_settings
+ (
+ uuid,
+ kee,
+ alm_id,
+ url,
+ app_id,
+ private_key,
+ pat,
+ created_at,
+ updated_at
+ )
+ VALUES (
+ #{uuid, jdbcType=VARCHAR},
+ #{dto.key, jdbcType=VARCHAR},
+ #{dto.rawAlm, jdbcType=VARCHAR},
+ #{dto.url, jdbcType=VARCHAR},
+ #{dto.appId, jdbcType=VARCHAR},
+ #{dto.privateKey, jdbcType=VARCHAR},
+ #{dto.personalAccessToken, jdbcType=VARCHAR},
+ #{now, jdbcType=BIGINT},
+ #{now, jdbcType=BIGINT}
+ )
+ </insert>
+
+ <update id="update" parameterType="Map">
+ UPDATE alm_settings
+ <set>
+ kee = #{dto.key, jdbcType=VARCHAR},
+ url = #{dto.url, jdbcType=VARCHAR},
+ app_id = #{dto.appId, jdbcType=VARCHAR},
+ private_key = #{dto.privateKey, jdbcType=VARCHAR},
+ pat = #{dto.personalAccessToken, jdbcType=VARCHAR},
+ updated_at = #{now, jdbcType=BIGINT}
+ </set>
+ <where>
+ uuid = #{dto.uuid, jdbcType=VARCHAR}
+ </where>
+ </update>
+
+ <delete id="deleteByKey" parameterType="String">
+ DELETE FROM alm_settings WHERE kee = #{key, jdbcType=VARCHAR}
+ </delete>
+
+
+</mapper>
diff --git a/server/sonar-db-dao/src/schema/schema-sq.ddl b/server/sonar-db-dao/src/schema/schema-sq.ddl
index 9f5c9f136b8..b286019ea08 100644
--- a/server/sonar-db-dao/src/schema/schema-sq.ddl
+++ b/server/sonar-db-dao/src/schema/schema-sq.ddl
@@ -50,6 +50,20 @@ CREATE UNIQUE INDEX ALM_APP_INSTALLS_OWNER ON ALM_APP_INSTALLS(ALM_ID, OWNER_ID)
CREATE UNIQUE INDEX ALM_APP_INSTALLS_INSTALL ON ALM_APP_INSTALLS(ALM_ID, INSTALL_ID);
CREATE INDEX ALM_APP_INSTALLS_EXTERNAL_ID ON ALM_APP_INSTALLS(USER_EXTERNAL_ID);
+CREATE TABLE ALM_SETTINGS(
+ UUID VARCHAR(40) NOT NULL,
+ ALM_ID VARCHAR(40) NOT NULL,
+ KEE VARCHAR(40) NOT NULL,
+ URL VARCHAR(2000),
+ APP_ID VARCHAR(80),
+ PRIVATE_KEY VARCHAR(2000),
+ PAT VARCHAR(2000),
+ UPDATED_AT BIGINT NOT NULL,
+ CREATED_AT BIGINT NOT NULL
+);
+ALTER TABLE ALM_SETTINGS ADD CONSTRAINT PK_ALM_SETTINGS PRIMARY KEY(UUID);
+CREATE UNIQUE INDEX UNIQ_ALM_SETTINGS ON ALM_SETTINGS(KEE);
+
CREATE TABLE ANALYSIS_PROPERTIES(
UUID VARCHAR(40) NOT NULL,
ANALYSIS_UUID VARCHAR(40) NOT NULL,
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
index 5063ba33bd1..d805141a0f2 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
@@ -30,6 +30,6 @@ public class DaoModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new DaoModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 63);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 64);
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/alm/setting/AlmSettingDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/alm/setting/AlmSettingDaoTest.java
new file mode 100644
index 00000000000..14dd5311aa4
--- /dev/null
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/alm/setting/AlmSettingDaoTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.db.alm.setting;
+
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.almsettings.AlmSettingsTesting;
+
+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.almsettings.AlmSettingsTesting.newGithubAlmSettingDto;
+
+public class AlmSettingDaoTest {
+
+ public static final long NOW = 1000000L;
+ private static final String A_UUID = "SOME_UUID";
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ private System2 system2 = mock(System2.class);
+ @Rule
+ public DbTester db = DbTester.create(system2);
+
+ private DbSession dbSession = db.getSession();
+ private UuidFactory uuidFactory = mock(UuidFactory.class);
+ private AlmSettingDao underTest = new AlmSettingDao(system2, uuidFactory);
+
+ @Test
+ public void selectByUuid() {
+ when(uuidFactory.create()).thenReturn(A_UUID);
+ when(system2.now()).thenReturn(NOW);
+
+ AlmSettingDto almSettingDto = newGithubAlmSettingDto();
+ underTest.insert(dbSession, almSettingDto);
+
+ assertThat(underTest.selectByUuid(dbSession, A_UUID).get())
+ .extracting(AlmSettingDto::getUuid, AlmSettingDto::getKey, AlmSettingDto::getRawAlm, AlmSettingDto::getUrl,
+ AlmSettingDto::getAppId, AlmSettingDto::getPrivateKey, AlmSettingDto::getPersonalAccessToken,
+ AlmSettingDto::getCreatedAt, AlmSettingDto::getUpdatedAt)
+ .containsExactly(A_UUID, almSettingDto.getKey(), ALM.GITHUB.getId(), almSettingDto.getUrl(),
+ almSettingDto.getAppId(), almSettingDto.getPrivateKey(),
+ almSettingDto.getPersonalAccessToken(), NOW, NOW);
+
+ assertThat(underTest.selectByUuid(dbSession, "foo")).isNotPresent();
+ }
+
+ @Test
+ public void selectByKey() {
+ when(uuidFactory.create()).thenReturn(A_UUID);
+ when(system2.now()).thenReturn(NOW);
+
+ AlmSettingDto almSettingDto = AlmSettingsTesting.newGithubAlmSettingDto();
+ underTest.insert(dbSession, almSettingDto);
+
+ assertThat(underTest.selectByKey(dbSession, almSettingDto.getKey()).get())
+ .extracting(AlmSettingDto::getUuid, AlmSettingDto::getKey, AlmSettingDto::getRawAlm, AlmSettingDto::getUrl,
+ AlmSettingDto::getAppId, AlmSettingDto::getPrivateKey, AlmSettingDto::getPersonalAccessToken,
+ AlmSettingDto::getCreatedAt, AlmSettingDto::getUpdatedAt)
+ .containsExactly(A_UUID, almSettingDto.getKey(), ALM.GITHUB.getId(), almSettingDto.getUrl(),
+ almSettingDto.getAppId(), almSettingDto.getPrivateKey(),
+ almSettingDto.getPersonalAccessToken(), NOW, NOW);
+
+ assertThat(underTest.selectByKey(dbSession, "foo")).isNotPresent();
+ }
+
+ @Test
+ public void selectAll() {
+ when(uuidFactory.create()).thenReturn(A_UUID);
+ when(system2.now()).thenReturn(NOW);
+ underTest.insert(dbSession, newGithubAlmSettingDto());
+ when(uuidFactory.create()).thenReturn(A_UUID + "bis");
+ underTest.insert(dbSession, newGithubAlmSettingDto());
+
+ List<AlmSettingDto> almSettings = underTest.selectAll(dbSession);
+ assertThat(almSettings).isNotNull();
+ assertThat(almSettings).size().isEqualTo(2);
+ }
+
+ @Test
+ public void update() {
+ when(uuidFactory.create()).thenReturn(A_UUID);
+ when(system2.now()).thenReturn(NOW);
+ AlmSettingDto almSettingDto = newGithubAlmSettingDto();
+ underTest.insert(dbSession, almSettingDto);
+
+ almSettingDto.setPrivateKey("updated private key");
+ almSettingDto.setAppId("updated app id");
+ almSettingDto.setUrl("updated url");
+ almSettingDto.setPersonalAccessToken("updated pat");
+ almSettingDto.setKey("updated key");
+
+ when(system2.now()).thenReturn(NOW + 1);
+ underTest.update(dbSession, almSettingDto);
+
+ AlmSettingDto result = underTest.selectByUuid(dbSession, A_UUID).get();
+ assertThat(result)
+ .extracting(AlmSettingDto::getUuid, AlmSettingDto::getKey, AlmSettingDto::getRawAlm, AlmSettingDto::getUrl,
+ AlmSettingDto::getAppId, AlmSettingDto::getPrivateKey, AlmSettingDto::getPersonalAccessToken,
+ AlmSettingDto::getCreatedAt, AlmSettingDto::getUpdatedAt)
+ .containsExactly(A_UUID, almSettingDto.getKey(), ALM.GITHUB.getId(), almSettingDto.getUrl(),
+ almSettingDto.getAppId(), almSettingDto.getPrivateKey(),
+ almSettingDto.getPersonalAccessToken(), NOW, NOW + 1);
+ }
+
+ @Test
+ public void delete() {
+ when(uuidFactory.create()).thenReturn(A_UUID);
+ when(system2.now()).thenReturn(NOW);
+ AlmSettingDto almSettingDto = newGithubAlmSettingDto();
+ underTest.insert(dbSession, almSettingDto);
+
+ underTest.delete(dbSession, almSettingDto);
+
+ assertThat(underTest.selectByKey(dbSession, almSettingDto.getKey()).isPresent()).isFalse();
+ }
+
+}
diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java
index 1fc19513ada..a39cd1dea64 100644
--- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java
+++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java
@@ -33,6 +33,7 @@ import org.picocontainer.containers.TransientPicoContainer;
import org.sonar.api.utils.System2;
import org.sonar.core.util.SequenceUuidFactory;
import org.sonar.db.alm.AlmDbTester;
+import org.sonar.db.almsettings.AlmSettingsDbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ProjectLinkDbTester;
import org.sonar.db.event.EventDbTester;
@@ -96,6 +97,7 @@ public class DbTester extends AbstractDbTester<TestDbImpl> {
private final WebhookDeliveryDbTester webhookDeliveryDbTester;
private final AlmDbTester almDbTester;
private final InternalComponentPropertyDbTester internalComponentPropertyTester;
+ private final AlmSettingsDbTester almSettingsDbTester;
private DbTester(System2 system2, @Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
super(TestDbImpl.create(schemaPath, confExtensions));
@@ -124,6 +126,7 @@ public class DbTester extends AbstractDbTester<TestDbImpl> {
this.almDbTester = new AlmDbTester(this);
this.internalComponentPropertyTester = new InternalComponentPropertyDbTester(this);
this.newCodePeriodTester = new NewCodePeriodDbTester(this);
+ this.almSettingsDbTester = new AlmSettingsDbTester(this);
}
public static DbTester create() {
@@ -294,6 +297,10 @@ public class DbTester extends AbstractDbTester<TestDbImpl> {
return internalComponentPropertyTester;
}
+ public AlmSettingsDbTester almSettings() {
+ return almSettingsDbTester;
+ }
+
@Override
protected void after() {
if (session != null) {
diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsDbTester.java
new file mode 100644
index 00000000000..0a74acc40cf
--- /dev/null
+++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsDbTester.java
@@ -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.db.almsettings;
+
+import java.util.function.Consumer;
+import org.sonar.db.DbTester;
+import org.sonar.db.alm.setting.AlmSettingDto;
+
+import static java.util.Arrays.stream;
+import static org.sonar.db.almsettings.AlmSettingsTesting.newGithubAlmSettingDto;
+
+public class AlmSettingsDbTester {
+
+ private final DbTester db;
+
+ public AlmSettingsDbTester(DbTester db) {
+ this.db = db;
+ }
+
+ @SafeVarargs
+ public final AlmSettingDto insertGitHubAlmSetting(Consumer<AlmSettingDto>... populators) {
+ AlmSettingDto dto = newGithubAlmSettingDto();
+ stream(populators).forEach(p -> p.accept(dto));
+
+ db.getDbClient().almSettingDao().insert(db.getSession(), dto);
+ db.commit();
+ return dto;
+ }
+
+}
diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsTesting.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsTesting.java
new file mode 100644
index 00000000000..e799a859f8f
--- /dev/null
+++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/almsettings/AlmSettingsTesting.java
@@ -0,0 +1,37 @@
+/*
+ * 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.db.almsettings;
+
+import org.sonar.db.alm.setting.ALM;
+import org.sonar.db.alm.setting.AlmSettingDto;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+
+public class AlmSettingsTesting {
+
+ public static AlmSettingDto newGithubAlmSettingDto() {
+ return new AlmSettingDto()
+ .setKey(randomAlphanumeric(40))
+ .setUrl(randomAlphanumeric(2000))
+ .setAppId(randomAlphanumeric(80))
+ .setAlm(ALM.GITHUB)
+ .setPrivateKey(randomAlphanumeric(2000));
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
index b199571a48c..1fc8fe3222f 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
@@ -26,6 +26,7 @@ import org.sonar.server.platform.db.migration.step.MigrationStepRegistryImpl;
import org.sonar.server.platform.db.migration.step.MigrationStepsProvider;
import org.sonar.server.platform.db.migration.version.v00.DbVersion00;
import org.sonar.server.platform.db.migration.version.v80.DbVersion80;
+import org.sonar.server.platform.db.migration.version.v81.DbVersion81;
public class MigrationConfigurationModule extends Module {
@Override
@@ -34,6 +35,7 @@ public class MigrationConfigurationModule extends Module {
// DbVersion implementations
DbVersion00.class,
DbVersion80.class,
+ DbVersion81.class,
// migration steps
MigrationStepRegistryImpl.class,
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java
index 0af992cc500..271b94f43f5 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java
@@ -74,8 +74,8 @@ public class PopulateInitialSchema extends DataChange {
long now = system2.now();
context.prepareUpsert("insert into users " +
- "(uuid, login, name, email, external_id, external_login, external_identity_provider, user_local, crypted_password, salt, hash_method, is_root, onboarded, created_at, updated_at)"
- +
+ "(uuid, login, name, email, external_id, external_login, external_identity_provider, user_local, crypted_password, salt, hash_method, is_root, onboarded, " +
+ "created_at, updated_at)" +
" values " +
"(?, ?, 'Administrator', null, 'admin', 'admin', 'sonarqube', ?, '$2a$12$uCkkXmhW5ThVK8mpBvnXOOJRLd64LJeHTeCkSuB3lfaR2N0AYBaSi', null, 'BCRYPT', ?, ?, ?, ?)")
.setString(1, uuidFactory.create())
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTable.java
new file mode 100644
index 00000000000..abdfd3188eb
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTable.java
@@ -0,0 +1,109 @@
+/*
+ * 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.v81;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.sql.CreateTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class CreateAlmSettingsTable extends DdlChange {
+
+ private static final String TABLE_NAME = "alm_settings";
+
+ private static final VarcharColumnDef KEY = newVarcharColumnDefBuilder()
+ .setColumnName("kee")
+ .setIsNullable(false)
+ .setLimit(40)
+ .build();
+
+ public CreateAlmSettingsTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ if (tableExists()) {
+ return;
+ }
+ context.execute(new CreateTableBuilder(getDialect(), TABLE_NAME)
+ .addPkColumn(newVarcharColumnDefBuilder()
+ .setColumnName("uuid")
+ .setIsNullable(false)
+ .setLimit(UUID_SIZE)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("alm_id")
+ .setIsNullable(false)
+ .setLimit(40)
+ .build())
+ .addColumn(KEY)
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("url")
+ .setIsNullable(true)
+ .setLimit(2000)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("app_id")
+ .setIsNullable(true)
+ .setLimit(80)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("private_key")
+ .setIsNullable(true)
+ .setLimit(2000)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("pat")
+ .setIsNullable(true)
+ .setLimit(2000)
+ .build())
+ .addColumn(newBigIntegerColumnDefBuilder()
+ .setColumnName("updated_at")
+ .setIsNullable(false)
+ .build())
+ .addColumn(newBigIntegerColumnDefBuilder()
+ .setColumnName("created_at")
+ .setIsNullable(false)
+ .build())
+ .build());
+
+ context.execute(new CreateIndexBuilder()
+ .setTable(TABLE_NAME)
+ .addColumn(KEY)
+ .setName("uniq_alm_settings")
+ .setUnique(true)
+ .build());
+ }
+
+ private boolean tableExists() throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ return DatabaseUtils.tableExists(TABLE_NAME, connection);
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81.java
new file mode 100644
index 00000000000..b5b2897a92b
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81.java
@@ -0,0 +1,31 @@
+/*
+ * 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.v81;
+
+import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
+import org.sonar.server.platform.db.migration.version.DbVersion;
+
+public class DbVersion81 implements DbVersion {
+ @Override
+ public void addSteps(MigrationStepRegistry registry) {
+ registry
+ .add(3100, "Create ALM_SETTINGS table", CreateAlmSettingsTable.class);
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/package-info.java
new file mode 100644
index 00000000000..835eb4a8909
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v81/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.platform.db.migration.version.v81;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java
index 4244868b614..aa4755278b6 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java
@@ -37,7 +37,7 @@ public class MigrationConfigurationModuleTest {
assertThat(container.getPicoContainer().getComponentAdapters())
.hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER
// DbVersion classes
- + 2
+ + 3
// Others
+ 4);
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTableTest.java
new file mode 100644
index 00000000000..cd9114c28bf
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/CreateAlmSettingsTableTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.v81;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.BIGINT;
+import static java.sql.Types.VARCHAR;
+
+public class CreateAlmSettingsTableTest {
+
+ private static final String TABLE_NAME = "alm_settings";
+
+ @Rule
+ public CoreDbTester dbTester = CoreDbTester.createEmpty();
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private CreateAlmSettingsTable underTest = new CreateAlmSettingsTable(dbTester.database());
+
+ @Test
+ public void table_has_been_created() throws SQLException {
+ underTest.execute();
+
+ dbTester.assertTableExists(TABLE_NAME);
+ dbTester.assertPrimaryKey(TABLE_NAME, "pk_alm_settings", "uuid");
+ dbTester.assertUniqueIndex(TABLE_NAME, "uniq_alm_settings", "kee");
+
+ dbTester.assertColumnDefinition(TABLE_NAME, "uuid", VARCHAR, 40, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "alm_id", VARCHAR, 40, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "url", VARCHAR, 2000, true);
+ dbTester.assertColumnDefinition(TABLE_NAME, "app_id", VARCHAR, 80, true);
+ dbTester.assertColumnDefinition(TABLE_NAME, "private_key", VARCHAR, 2000, true);
+ dbTester.assertColumnDefinition(TABLE_NAME, "pat", VARCHAR, 2000, true);
+ dbTester.assertColumnDefinition(TABLE_NAME, "updated_at", BIGINT, 20, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "created_at", BIGINT, 20, false);
+
+ // script should not fail if executed twice
+ underTest.execute();
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81Test.java
new file mode 100644
index 00000000000..a8dcfb748ca
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v81/DbVersion81Test.java
@@ -0,0 +1,43 @@
+/*
+ * 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.v81;
+
+import org.junit.Test;
+import org.sonar.server.platform.db.migration.version.DbVersion;
+
+import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
+import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
+
+public class DbVersion81Test {
+
+ private DbVersion underTest = new DbVersion81();
+
+ @Test
+ public void migrationNumber_starts_at_3000() {
+ verifyMinimumMigrationNumber(underTest, 3100);
+ }
+
+ @Test
+ public void verify_migration_count() {
+ verifyMigrationCount(underTest, 1);
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWs.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWs.java
new file mode 100644
index 00000000000..19cf36a7547
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWs.java
@@ -0,0 +1,42 @@
+/*
+ * 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.almsettings;
+
+import java.util.List;
+import org.sonar.api.server.ws.WebService;
+
+public class AlmSettingsWs implements WebService {
+ private final List<AlmSettingsWsAction> actions;
+
+ public AlmSettingsWs(List<AlmSettingsWsAction> actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public void define(Context context) {
+ NewController controller = context.createController("api/alm_settings")
+ .setDescription("Manage ALM Settings")
+ .setSince("8.1");
+
+ actions.forEach(a -> a.define(controller));
+
+ controller.done();
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsAction.java
new file mode 100644
index 00000000000..c9508e79f88
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsAction.java
@@ -0,0 +1,26 @@
+/*
+ * 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.almsettings;
+
+import org.sonar.server.ws.WsAction;
+
+public interface AlmSettingsWsAction extends WsAction {
+ // marker interface
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsModule.java
new file mode 100644
index 00000000000..2b568c07bef
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/AlmSettingsWsModule.java
@@ -0,0 +1,34 @@
+/*
+ * 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.almsettings;
+
+import org.sonar.core.platform.Module;
+
+public class AlmSettingsWsModule extends Module {
+ @Override
+ protected void configureModule() {
+ add(
+ AlmSettingsWs.class,
+ ListDefinitionsAction.class,
+ CreateGithubAction.class,
+ UpdateGitHubAction.class,
+ DeleteAction.class);
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/CreateGithubAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/CreateGithubAction.java
new file mode 100644
index 00000000000..6412a90293c
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/CreateGithubAction.java
@@ -0,0 +1,102 @@
+/*
+ * 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.almsettings;
+
+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.alm.setting.AlmSettingDto;
+import org.sonar.server.user.UserSession;
+
+import static java.lang.String.format;
+import static org.sonar.db.alm.setting.ALM.GITHUB;
+
+public class CreateGithubAction implements AlmSettingsWsAction {
+
+ private static final String PARAM_KEY = "key";
+ private static final String PARAM_URL = "url";
+ private static final String PARAM_APP_ID = "appId";
+ private static final String PARAM_PRIVATE_KEY = "privateKey";
+
+ private final DbClient dbClient;
+ private UserSession userSession;
+
+ public CreateGithubAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("create_github")
+ .setDescription("Create GitHub ALM instance Setting. <br/>" +
+ "Requires the 'Administer System' permission")
+ .setPost(true)
+ .setSince("8.1")
+ .setHandler(this);
+
+ action.createParam(PARAM_KEY)
+ .setRequired(true)
+ .setMaximumLength(40)
+ .setDescription("Unique key of the GitHub instance setting");
+ action.createParam(PARAM_URL)
+ .setRequired(true)
+ .setMaximumLength(2000)
+ .setDescription("GitHub API URL");
+ action.createParam(PARAM_APP_ID)
+ .setRequired(true)
+ .setMaximumLength(80)
+ .setDescription("GitHub API ID");
+ action.createParam(PARAM_PRIVATE_KEY)
+ .setRequired(true)
+ .setMaximumLength(2000)
+ .setDescription("GitHub App private key");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ userSession.checkIsSystemAdministrator();
+ doHandle(request);
+ response.noContent();
+ }
+
+ private void doHandle(Request request) {
+ String key = request.mandatoryParam(PARAM_KEY);
+ String url = request.mandatoryParam(PARAM_URL);
+ String appId = request.mandatoryParam(PARAM_APP_ID);
+ String privateKey = request.mandatoryParam(PARAM_PRIVATE_KEY);
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ dbClient.almSettingDao().selectByKey(dbSession, key)
+ .ifPresent(almSetting -> {
+ throw new IllegalArgumentException(format("An ALM setting with key '%s' already exist", almSetting.getKey()));
+ });
+ dbClient.almSettingDao().insert(dbSession, new AlmSettingDto()
+ .setAlm(GITHUB)
+ .setKey(key)
+ .setUrl(url)
+ .setAppId(appId)
+ .setPrivateKey(privateKey));
+ dbSession.commit();
+ }
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/DeleteAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/DeleteAction.java
new file mode 100644
index 00000000000..915430c839f
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/DeleteAction.java
@@ -0,0 +1,77 @@
+/*
+ * 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.almsettings;
+
+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.alm.setting.AlmSettingDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import static java.lang.String.format;
+
+public class DeleteAction implements AlmSettingsWsAction {
+
+ private static final String PARAM_KEY = "key";
+
+ private final DbClient dbClient;
+ private UserSession userSession;
+
+ public DeleteAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context
+ .createAction("delete")
+ .setDescription("Delete ALM Settings.<br/>" +
+ "Requires the 'Administer System' permission")
+ .setSince("8.1")
+ .setPost(true)
+ .setHandler(this);
+
+ action
+ .createParam(PARAM_KEY)
+ .setDescription("ALM Setting key")
+ .setRequired(true);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ userSession.checkIsSystemAdministrator();
+ doHandle(request);
+ response.noContent();
+ }
+
+ private void doHandle(Request request) {
+ String key = request.mandatoryParam(PARAM_KEY);
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ AlmSettingDto almSettingDto = dbClient.almSettingDao().selectByKey(dbSession, key)
+ .orElseThrow(() -> new NotFoundException(format("No ALM setting with key '%s' has been found", key)));
+ dbClient.almSettingDao().delete(dbSession, almSettingDto);
+ dbSession.commit();
+ }
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ListDefinitionsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ListDefinitionsAction.java
new file mode 100644
index 00000000000..a79ef988ee1
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ListDefinitionsAction.java
@@ -0,0 +1,86 @@
+/*
+ * 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.almsettings;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+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.alm.setting.ALM;
+import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.AlmSettings.AlmSettingGithub;
+
+import static java.util.Collections.emptyList;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.AlmSettings.ListDefinitionsWsResponse;
+
+public class ListDefinitionsAction implements AlmSettingsWsAction {
+
+ private final DbClient dbClient;
+ private UserSession userSession;
+
+ public ListDefinitionsAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ private static AlmSettingGithub convert(AlmSettingDto settingDto) {
+ return AlmSettingGithub
+ .newBuilder()
+ .setKey(settingDto.getKey())
+ .setUrl(requireNonNull(settingDto.getUrl(), "URL cannot be null for GitHub ALM setting"))
+ .setAppId(requireNonNull(settingDto.getAppId(), "App ID cannot be null for GitHub ALM setting"))
+ .setPrivateKey(requireNonNull(settingDto.getPrivateKey(), "Private Key cannot be null for GitHub ALM setting"))
+ .build();
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ context.createAction("list_definitions")
+ .setDescription("List ALM Settings. <br/>" +
+ "Requires the 'Administer System' permission")
+ .setSince("8.1")
+ .setResponseExample(getClass().getResource("list_definitions-example.json"))
+ .setHandler(this);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ userSession.checkIsSystemAdministrator();
+ ListDefinitionsWsResponse wsResponse = doHandle();
+ writeProtobuf(wsResponse, request, response);
+ }
+
+ private ListDefinitionsWsResponse doHandle() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<AlmSettingDto> settings = dbClient.almSettingDao().selectAll(dbSession);
+ Map<ALM, List<AlmSettingDto>> settingsByAlm = settings.stream().collect(Collectors.groupingBy(AlmSettingDto::getAlm));
+ List<AlmSettingGithub> githubSettings = settingsByAlm.getOrDefault(ALM.GITHUB, emptyList()).stream()
+ .map(ListDefinitionsAction::convert).collect(Collectors.toList());
+ return ListDefinitionsWsResponse.newBuilder().addAllGithub(githubSettings).build();
+ }
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/UpdateGitHubAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/UpdateGitHubAction.java
new file mode 100644
index 00000000000..d2e05875764
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/UpdateGitHubAction.java
@@ -0,0 +1,114 @@
+/*
+ * 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.almsettings;
+
+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.alm.setting.AlmSettingDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import static java.lang.String.format;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
+public class UpdateGitHubAction implements AlmSettingsWsAction {
+
+ private static final String PARAM_KEY = "key";
+ private static final String PARAM_NEW_KEY = "newKey";
+ private static final String PARAM_URL = "url";
+ private static final String PARAM_APP_ID = "appId";
+ private static final String PARAM_PRIVATE_KEY = "privateKey";
+
+ private final DbClient dbClient;
+ private UserSession userSession;
+
+ public UpdateGitHubAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("update_github")
+ .setDescription("Update GitHub ALM instance Setting. <br/>" +
+ "Requires the 'Administer System' permission")
+ .setPost(true)
+ .setSince("8.1")
+ .setHandler(this);
+
+ action.createParam(PARAM_KEY)
+ .setRequired(true)
+ .setMaximumLength(40)
+ .setDescription("Unique key of the GitHub instance setting");
+ action.createParam(PARAM_NEW_KEY)
+ .setRequired(false)
+ .setMaximumLength(40)
+ .setDescription("Optional new value for an unique key of the GitHub instance setting");
+ action.createParam(PARAM_URL)
+ .setRequired(true)
+ .setMaximumLength(2000)
+ .setDescription("GitHub API URL");
+ action.createParam(PARAM_APP_ID)
+ .setRequired(true)
+ .setMaximumLength(80)
+ .setDescription("GitHub API ID");
+ action.createParam(PARAM_PRIVATE_KEY)
+ .setRequired(true)
+ .setMaximumLength(2000)
+ .setDescription("GitHub App private key");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ userSession.checkIsSystemAdministrator();
+ doHandle(request);
+ response.noContent();
+ }
+
+ private void doHandle(Request request) {
+ String key = request.mandatoryParam(PARAM_KEY);
+ String newKey = request.param(PARAM_NEW_KEY);
+ String url = request.mandatoryParam(PARAM_URL);
+ String appId = request.mandatoryParam(PARAM_APP_ID);
+ String privateKey = request.mandatoryParam(PARAM_PRIVATE_KEY);
+
+ try (DbSession dbSession = dbClient.openSession(false)) {
+
+ AlmSettingDto almSettingDto = dbClient.almSettingDao().selectByKey(dbSession, key)
+ .orElseThrow(() -> new NotFoundException(format("No ALM setting with key '%s' has been found", key)));
+ if (isNotBlank(newKey) && !newKey.equals(key)) {
+ dbClient.almSettingDao().selectByKey(dbSession, newKey)
+ .ifPresent(almSetting -> {
+ throw new IllegalArgumentException(format("ALM setting with key '%s' already exists", almSetting.getKey()));
+ });
+ }
+ dbClient.almSettingDao().update(dbSession, almSettingDto
+ .setKey(isNotBlank(newKey) ? newKey : key)
+ .setUrl(url)
+ .setAppId(appId)
+ .setPrivateKey(privateKey));
+ dbSession.commit();
+ }
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/package-info.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/package-info.java
new file mode 100644
index 00000000000..a01307de8b1
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.almsettings;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/almsettings/list_definitions-example.json b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/almsettings/list_definitions-example.json
new file mode 100644
index 00000000000..a4d22e5844c
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/almsettings/list_definitions-example.json
@@ -0,0 +1,10 @@
+{
+ "github": [
+ {
+ "key": "GitHub Server - Dev Team",
+ "url": "https://github.enterprise.com",
+ "appId": "12345",
+ "privateKey": "54684654"
+ }
+ ]
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/AlmSettingsWsModuleTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/AlmSettingsWsModuleTest.java
new file mode 100644
index 00000000000..2ebabef0854
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/AlmSettingsWsModuleTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.almsettings;
+
+import org.junit.Test;
+import org.sonar.core.platform.ComponentContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
+
+public class AlmSettingsWsModuleTest {
+
+ @Test
+ public void verify_count_of_added_components() {
+ ComponentContainer container = new ComponentContainer();
+ new AlmSettingsWsModule().configure(container);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5);
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/CreateGithubActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/CreateGithubActionTest.java
new file mode 100644
index 00000000000..3e48df770b5
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/CreateGithubActionTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.almsettings;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbTester;
+import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class CreateGithubActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private WsActionTester ws = new WsActionTester(new CreateGithubAction(db.getDbClient(), userSession));
+
+ @Test
+ public void create() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+
+ ws.newRequest()
+ .setParam("key", "GitHub Server - Dev Team")
+ .setParam("url", "https://github.enterprise.com")
+ .setParam("appId", "12345")
+ .setParam("privateKey", "678910")
+ .execute();
+
+ assertThat(db.getDbClient().almSettingDao().selectAll(db.getSession()))
+ .extracting(AlmSettingDto::getKey, AlmSettingDto::getUrl, AlmSettingDto::getAppId, AlmSettingDto::getPrivateKey)
+ .containsOnly(tuple("GitHub Server - Dev Team", "https://github.enterprise.com", "12345", "678910"));
+ }
+
+ @Test
+ public void fail_when_key_is_already_used() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ AlmSettingDto gitHubAlmSetting = db.almSettings().insertGitHubAlmSetting();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(String.format("An ALM setting with key '%s' already exist", gitHubAlmSetting.getKey()));
+
+ ws.newRequest()
+ .setParam("key", gitHubAlmSetting.getKey())
+ .setParam("url", "https://github.enterprise.com")
+ .setParam("appId", "12345")
+ .setParam("privateKey", "678910")
+ .execute();
+ }
+
+ @Test
+ public void fail_when_missing_administer_system_permission() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newRequest()
+ .setParam("key", "GitHub Server - Dev Team")
+ .setParam("url", "https://github.enterprise.com")
+ .setParam("appId", "12345")
+ .setParam("privateKey", "678910")
+ .execute();
+ }
+
+ @Test
+ public void definition() {
+ WebService.Action def = ws.getDef();
+
+ assertThat(def.since()).isEqualTo("8.1");
+ assertThat(def.isPost()).isTrue();
+ assertThat(def.params())
+ .extracting(WebService.Param::key, WebService.Param::isRequired)
+ .containsExactlyInAnyOrder(tuple("key", true), tuple("url", true), tuple("appId", true), tuple("privateKey", true));
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/DeleteActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/DeleteActionTest.java
new file mode 100644
index 00000000000..aec45c06f25
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/DeleteActionTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.almsettings;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbTester;
+import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class DeleteActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private WsActionTester ws = new WsActionTester(new DeleteAction(db.getDbClient(), userSession));
+
+ @Test
+ public void delete() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ AlmSettingDto almSettingDto = db.almSettings().insertGitHubAlmSetting();
+
+ ws.newRequest()
+ .setParam("key", almSettingDto.getKey())
+ .execute();
+
+ assertThat(db.getDbClient().almSettingDao().selectAll(db.getSession())).isEmpty();
+ }
+
+ @Test
+ public void fail_when_key_does_not_match_existing_alm_setting() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("No ALM setting with key 'unknown' has been found");
+
+ ws.newRequest()
+ .setParam("key", "unknown")
+ .execute();
+ }
+
+ @Test
+ public void fail_when_missing_administer_system_permission() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ AlmSettingDto almSettingDto = db.almSettings().insertGitHubAlmSetting();
+
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newRequest()
+ .setParam("key", almSettingDto.getKey())
+ .execute();
+ }
+
+ @Test
+ public void definition() {
+ WebService.Action def = ws.getDef();
+
+ assertThat(def.since()).isEqualTo("8.1");
+ assertThat(def.isPost()).isTrue();
+ assertThat(def.params())
+ .extracting(WebService.Param::key, WebService.Param::isRequired)
+ .containsExactlyInAnyOrder(tuple("key", true));
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/ListDefinitionsActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/ListDefinitionsActionTest.java
new file mode 100644
index 00000000000..63a9dac0d4d
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/ListDefinitionsActionTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.almsettings;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbTester;
+import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.AlmSettings;
+import org.sonarqube.ws.AlmSettings.AlmSettingGithub;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.junit.rules.ExpectedException.none;
+import static org.sonar.server.tester.UserSessionRule.standalone;
+import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.AlmSettings.*;
+
+public class ListDefinitionsActionTest {
+
+ @Rule
+ public ExpectedException expectedException = none();
+ @Rule
+ public UserSessionRule userSession = standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private WsActionTester ws = new WsActionTester(new ListDefinitionsAction(db.getDbClient(), userSession));
+
+ @Test
+ public void list_github_settings() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ AlmSettingDto almSetting1 = db.almSettings().insertGitHubAlmSetting();
+ AlmSettingDto almSetting2 = db.almSettings().insertGitHubAlmSetting();
+
+ ListDefinitionsWsResponse wsResponse = ws.newRequest().executeProtobuf(ListDefinitionsWsResponse.class);
+
+ assertThat(wsResponse.getGithubList())
+ .extracting(AlmSettingGithub::getKey, AlmSettingGithub::getUrl, AlmSettingGithub::getAppId, AlmSettingGithub::getPrivateKey)
+ .containsExactlyInAnyOrder(
+ tuple(almSetting1.getKey(), almSetting1.getUrl(), almSetting1.getAppId(), almSetting1.getPrivateKey()),
+ tuple(almSetting2.getKey(), almSetting2.getUrl(), almSetting2.getAppId(), almSetting2.getPrivateKey()));
+ }
+
+ @Test
+ public void return_empty_list_when_no_settings() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+
+ ListDefinitionsWsResponse wsResponse = ws.newRequest().executeProtobuf(ListDefinitionsWsResponse.class);
+
+ assertThat(wsResponse.getGithubList()).isEmpty();
+ }
+
+ @Test
+ public void fail_when_user_is_not_system_administrator() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ db.almSettings().insertGitHubAlmSetting();
+
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newRequest().executeProtobuf(ListDefinitionsWsResponse.class);
+ }
+
+ @Test
+ public void json_example() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ db.almSettings().insertGitHubAlmSetting(
+ almSettingDto -> almSettingDto
+ .setKey("GitHub Server - Dev Team")
+ .setUrl("https://github.enterprise.com")
+ .setAppId("12345")
+ .setPrivateKey("54684654"));
+
+ String response = ws.newRequest().execute().getInput();
+
+ assertJson(response).isSimilarTo(getClass().getResource("list_definitions-example.json"));
+ }
+
+ @Test
+ public void definition() {
+ WebService.Action def = ws.getDef();
+
+ assertThat(def.since()).isEqualTo("8.1");
+ assertThat(def.params()).isEmpty();
+ assertThat(def.isPost()).isFalse();
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/UpdateGithubActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/UpdateGithubActionTest.java
new file mode 100644
index 00000000000..c0deea9aa10
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/almsettings/UpdateGithubActionTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.almsettings;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbTester;
+import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class UpdateGithubActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private WsActionTester ws = new WsActionTester(new UpdateGitHubAction(db.getDbClient(), userSession));
+
+ @Test
+ public void update() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ AlmSettingDto almSettingDto = db.almSettings().insertGitHubAlmSetting();
+
+ ws.newRequest()
+ .setParam("key", almSettingDto.getKey())
+ .setParam("url", "https://github.enterprise-unicorn.com")
+ .setParam("appId", "54321")
+ .setParam("privateKey", "10987654321")
+ .execute();
+
+ assertThat(db.getDbClient().almSettingDao().selectAll(db.getSession()))
+ .extracting(AlmSettingDto::getKey, AlmSettingDto::getUrl, AlmSettingDto::getAppId, AlmSettingDto::getPrivateKey)
+ .containsOnly(tuple(almSettingDto.getKey(), "https://github.enterprise-unicorn.com", "54321", "10987654321"));
+ }
+
+ @Test
+ public void update_with_new_key() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ AlmSettingDto almSettingDto = db.almSettings().insertGitHubAlmSetting();
+
+ ws.newRequest()
+ .setParam("key", almSettingDto.getKey())
+ .setParam("newKey", "GitHub Server - Infra Team")
+ .setParam("url", "https://github.enterprise-unicorn.com")
+ .setParam("appId", "54321")
+ .setParam("privateKey", "10987654321")
+ .execute();
+
+ assertThat(db.getDbClient().almSettingDao().selectAll(db.getSession()))
+ .extracting(AlmSettingDto::getKey, AlmSettingDto::getUrl, AlmSettingDto::getAppId, AlmSettingDto::getPrivateKey)
+ .containsOnly(tuple("GitHub Server - Infra Team", "https://github.enterprise-unicorn.com", "54321", "10987654321"));
+ }
+
+ @Test
+ public void fail_when_key_does_not_match_existing_alm_setting() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("No ALM setting with key 'unknown' has been found");
+
+ ws.newRequest()
+ .setParam("key", "unknown")
+ .setParam("newKey", "GitHub Server - Infra Team")
+ .setParam("url", "https://github.enterprise-unicorn.com")
+ .setParam("appId", "54321")
+ .setParam("privateKey", "10987654321")
+ .execute();
+ }
+
+ @Test
+ public void fail_when_new_key_matches_existing_alm_setting() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ AlmSettingDto almSetting1 = db.almSettings().insertGitHubAlmSetting();
+ AlmSettingDto almSetting2 = db.almSettings().insertGitHubAlmSetting();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(format("ALM setting with key '%s' already exists", almSetting2.getKey()));
+
+ ws.newRequest()
+ .setParam("key", almSetting1.getKey())
+ .setParam("newKey", almSetting2.getKey())
+ .setParam("url", "https://github.enterprise-unicorn.com")
+ .setParam("appId", "54321")
+ .setParam("privateKey", "10987654321")
+ .execute();
+ }
+
+ @Test
+ public void fail_when_missing_administer_system_permission() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ AlmSettingDto almSettingDto = db.almSettings().insertGitHubAlmSetting();
+
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newRequest()
+ .setParam("key", almSettingDto.getKey())
+ .setParam("newKey", "GitHub Server - Infra Team")
+ .setParam("url", "https://github.enterprise-unicorn.com")
+ .setParam("appId", "54321")
+ .setParam("privateKey", "10987654321")
+ .execute();
+ }
+
+ @Test
+ public void definition() {
+ WebService.Action def = ws.getDef();
+
+ assertThat(def.since()).isEqualTo("8.1");
+ assertThat(def.isPost()).isTrue();
+ assertThat(def.params())
+ .extracting(WebService.Param::key, WebService.Param::isRequired)
+ .containsExactlyInAnyOrder(tuple("key", true), tuple("newKey", false), tuple("url", true), tuple("appId", true), tuple("privateKey", true));
+ }
+
+}
diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
index 23601bc33b6..3e4cef7bb38 100644
--- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
+++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
@@ -38,6 +38,7 @@ import org.sonar.core.component.DefaultResourceTypes;
import org.sonar.core.extension.CoreExtensionsInstaller;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PlatformEditionProvider;
+import org.sonar.server.almsettings.AlmSettingsWsModule;
import org.sonar.server.authentication.AuthenticationModule;
import org.sonar.server.authentication.LogOAuthWarning;
import org.sonar.server.authentication.ws.AuthenticationWsModule;
@@ -469,6 +470,7 @@ public class PlatformLevel4 extends PlatformLevel {
PropertiesWs.class,
org.sonar.server.property.ws.IndexAction.class,
SettingsWsModule.class,
+ AlmSettingsWsModule.class,
TypeValidationModule.class,