CREATE TABLE "GITHUB_PERMS_MAPPING"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"GITHUB_ROLE" CHARACTER VARYING(100) NOT NULL,
- "SONARQUBE_ROLE" CHARACTER VARYING(64) NOT NULL
+ "SONARQUBE_PERMISSION" CHARACTER VARYING(64) NOT NULL
);
ALTER TABLE "GITHUB_PERMS_MAPPING" ADD CONSTRAINT "PK_GITHUB_PERMS_MAPPING" PRIMARY KEY("UUID");
-CREATE UNIQUE NULLS DISTINCT INDEX "UNIQ_GITHUB_PERM_MAPPINGS" ON "GITHUB_PERMS_MAPPING"("GITHUB_ROLE" NULLS FIRST, "SONARQUBE_ROLE" NULLS FIRST);
+CREATE UNIQUE NULLS DISTINCT INDEX "UNIQ_GITHUB_PERM_MAPPINGS" ON "GITHUB_PERMS_MAPPING"("GITHUB_ROLE" NULLS FIRST, "SONARQUBE_PERMISSION" NULLS FIRST);
CREATE TABLE "GROUP_ROLES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
public class CreateGithubPermissionsMappingTable extends CreateTableChange {
static final String GITHUB_PERMISSIONS_MAPPING_TABLE_NAME = "github_perms_mapping";
static final String GITHUB_ROLE_COLUMN = "github_role";
- static final String SONARQUBE_ROLE_COLUMN = "sonarqube_role";
+ static final String SONARQUBE_PERMISSION_COLUMN = "sonarqube_permission";
public CreateGithubPermissionsMappingTable(Database db) {
super(db, GITHUB_PERMISSIONS_MAPPING_TABLE_NAME);
context.execute(new CreateTableBuilder(getDialect(), tableName)
.addPkColumn(newVarcharColumnDefBuilder().setColumnName("uuid").setIsNullable(false).setLimit(UUID_SIZE).build())
.addColumn(newVarcharColumnDefBuilder().setColumnName(GITHUB_ROLE_COLUMN).setIsNullable(false).setLimit(100).build())
- .addColumn(newVarcharColumnDefBuilder().setColumnName(SONARQUBE_ROLE_COLUMN).setIsNullable(false).setLimit(64).build())
+ .addColumn(newVarcharColumnDefBuilder().setColumnName(SONARQUBE_PERMISSION_COLUMN).setIsNullable(false).setLimit(64).build())
.build());
}
}
import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.GITHUB_PERMISSIONS_MAPPING_TABLE_NAME;
import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.GITHUB_ROLE_COLUMN;
-import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.SONARQUBE_ROLE_COLUMN;
+import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.SONARQUBE_PERMISSION_COLUMN;
public class CreateUniqueIndexForGithubPermissionsMappingTable extends DdlChange {
.setTable(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME)
.setName(INDEX_NAME)
.addColumn(GITHUB_ROLE_COLUMN)
- .addColumn(SONARQUBE_ROLE_COLUMN)
+ .addColumn(SONARQUBE_PERMISSION_COLUMN)
.setUnique(true)
.build());
}
.add(10_3_000, "Set 'sonar.qualityProfiles.allowDisableInheritedRules' to false for upgraded instances", SetAllowQualityProfileDisableInheritedRules.class)
.add(10_3_001, "Add table 'github_perms_mapping'", CreateGithubPermissionsMappingTable.class)
.add(10_3_002, "Create unique index on 'github_perms_mapping'", CreateUniqueIndexForGithubPermissionsMappingTable.class)
+ .add(10_3_003, "Add default mappings to 'github_perms_mapping'", PopulateGithubPermissionsMapping.class)
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.Select;
+import org.sonar.server.platform.db.migration.step.Upsert;
+
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
+import static org.sonar.api.web.UserRole.SCAN;
+import static org.sonar.api.web.UserRole.SECURITYHOTSPOT_ADMIN;
+import static org.sonar.api.web.UserRole.USER;
+
+public class PopulateGithubPermissionsMapping extends DataChange {
+
+ private static final Map<String, Set<String>> GITHUB_ROLE_TO_SQ_PERMISSIONS = Map.of(
+ "read", Set.of(USER, CODEVIEWER),
+ "triage", Set.of(USER, CODEVIEWER),
+ "write", Set.of(USER, CODEVIEWER, ISSUE_ADMIN, SECURITYHOTSPOT_ADMIN, SCAN),
+ "maintain", Set.of(USER, CODEVIEWER, ISSUE_ADMIN, SECURITYHOTSPOT_ADMIN, SCAN),
+ "admin", Set.of(USER, CODEVIEWER, ISSUE_ADMIN, SECURITYHOTSPOT_ADMIN, SCAN, ADMIN)
+ );
+
+ private static final String INSERT_QUERY = """
+ insert into github_perms_mapping (uuid, github_role, sonarqube_permission)
+ values (?, ?, ?)
+ """;
+
+ private final UuidFactory uuidFactory;
+
+ public PopulateGithubPermissionsMapping(Database db, UuidFactory uuidFactory) {
+ super(db);
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ if (isDefaultMappingAlreadyDefined(context)) {
+ return;
+ }
+ try (Upsert upsert = context.prepareUpsert(INSERT_QUERY)) {
+ GITHUB_ROLE_TO_SQ_PERMISSIONS.forEach((key, value) -> insertGithubRoleToSonarqubePermissionMapping(upsert, key, value));
+ upsert.commit();
+ }
+ }
+
+ private void insertGithubRoleToSonarqubePermissionMapping(Upsert upsert, String githubRole, Set<String> sonarqubePermissions) {
+ sonarqubePermissions.forEach(permission -> insertGithubRoleToSonarqubePermissionMapping(upsert, githubRole, permission));
+ }
+
+ private void insertGithubRoleToSonarqubePermissionMapping(Upsert upsert, String githubRole, String sonarqubePermission) {
+ try {
+ upsert
+ .setString(1, uuidFactory.create())
+ .setString(2, githubRole)
+ .setString(3, sonarqubePermission)
+ .execute();
+ } catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static boolean isDefaultMappingAlreadyDefined(Context context) throws SQLException {
+ try (Select select = context.prepareSelect("select count(*) from github_perms_mapping")) {
+ return Optional.ofNullable(select.get(t -> t.getInt(1) > 0))
+ .orElseThrow();
+ }
+ }
+
+}
db.assertTableExists(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME);
db.assertColumnDefinition(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, "uuid", Types.VARCHAR, UUID_SIZE, false);
db.assertColumnDefinition(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, "github_role", Types.VARCHAR, 100, false);
- db.assertColumnDefinition(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, "sonarqube_role", Types.VARCHAR, 64, false);
+ db.assertColumnDefinition(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, "sonarqube_permission", Types.VARCHAR, 64, false);
db.assertPrimaryKey(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, "pk_github_perms_mapping", "uuid");
}
import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.GITHUB_PERMISSIONS_MAPPING_TABLE_NAME;
import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.GITHUB_ROLE_COLUMN;
-import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.SONARQUBE_ROLE_COLUMN;
+import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.SONARQUBE_PERMISSION_COLUMN;
import static org.sonar.server.platform.db.migration.version.v103.CreateUniqueIndexForGithubPermissionsMappingTable.INDEX_NAME;
public class CreateUniqueIndexForGithubPermissionsMappingTableTest {
createIndex.execute();
- db.assertUniqueIndex(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, INDEX_NAME, GITHUB_ROLE_COLUMN, SONARQUBE_ROLE_COLUMN);
+ db.assertUniqueIndex(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, INDEX_NAME, GITHUB_ROLE_COLUMN, SONARQUBE_PERMISSION_COLUMN);
}
@Test
createIndex.execute();
createIndex.execute();
- db.assertUniqueIndex(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, INDEX_NAME, GITHUB_ROLE_COLUMN, SONARQUBE_ROLE_COLUMN);
+ db.assertUniqueIndex(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME, INDEX_NAME, GITHUB_ROLE_COLUMN, SONARQUBE_PERMISSION_COLUMN);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.testfixtures.log.LogTester;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.server.platform.db.migration.version.v103.CreateGithubPermissionsMappingTable.GITHUB_PERMISSIONS_MAPPING_TABLE_NAME;
+
+public class PopulateGithubPermissionsMappingTest {
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(PopulateGithubPermissionsMappingTest.class, "schema.sql");
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ private final PopulateGithubPermissionsMapping migration = new PopulateGithubPermissionsMapping(db.database(), UuidFactoryFast.getInstance());
+
+ @Test
+ public void execute_whenTableAlreadyPopulated_doesNothing() throws SQLException {
+ db.executeInsert(GITHUB_PERMISSIONS_MAPPING_TABLE_NAME,
+ "UUID", UuidFactoryFast.getInstance().create(),
+ "github_role", "gh_role",
+ "sonarqube_permission", "sq_perm");
+
+ migration.execute();
+
+ assertThat(db.select("select github_role, sonarqube_permission from github_perms_mapping"))
+ .extracting(stringObjectMap -> stringObjectMap.get("GITHUB_ROLE"), stringObjectMap -> stringObjectMap.get("SONARQUBE_PERMISSION"))
+ .containsExactly(tuple("gh_role", "sq_perm"));
+ }
+
+ @Test
+ public void execute_whenTableIsEmpty_shouldPopulate() throws SQLException {
+ migration.execute();
+
+ verifyMapping();
+ }
+
+ @Test
+ public void execute_isReentrant() throws SQLException {
+ migration.execute();
+ migration.execute();
+ migration.execute();
+
+ verifyMapping();
+ }
+
+ private void verifyMapping() {
+ assertThat(db.select("select github_role, sonarqube_permission from github_perms_mapping"))
+ .extracting(stringObjectMap -> stringObjectMap.get("GITHUB_ROLE"), stringObjectMap -> stringObjectMap.get("SONARQUBE_PERMISSION"))
+ .containsExactlyInAnyOrder(
+ tuple("read", "codeviewer"),
+ tuple("read", "user"),
+ tuple("triage", "codeviewer"),
+ tuple("triage", "user"),
+ tuple("write", "codeviewer"),
+ tuple("write", "user"),
+ tuple("write", "issueadmin"),
+ tuple("write", "securityhotspotadmin"),
+ tuple("write", "scan"),
+ tuple("maintain", "codeviewer"),
+ tuple("maintain", "user"),
+ tuple("maintain", "issueadmin"),
+ tuple("maintain", "securityhotspotadmin"),
+ tuple("maintain", "scan"),
+ tuple("admin", "codeviewer"),
+ tuple("admin", "user"),
+ tuple("admin", "issueadmin"),
+ tuple("admin", "securityhotspotadmin"),
+ tuple("admin", "scan"),
+ tuple("admin", "admin")
+ );
+ }
+
+}
CREATE TABLE "GITHUB_PERMS_MAPPING"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"GITHUB_ROLE" CHARACTER VARYING(100) NOT NULL,
- "SONARQUBE_ROLE" CHARACTER VARYING(64) NOT NULL
+ "SONARQUBE_PERMISSION" CHARACTER VARYING(64) NOT NULL
);
ALTER TABLE "GITHUB_PERMS_MAPPING" ADD CONSTRAINT "PK_GITHUB_PERMS_MAPPING" PRIMARY KEY("UUID");
--- /dev/null
+CREATE TABLE "GITHUB_PERMS_MAPPING"(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "GITHUB_ROLE" CHARACTER VARYING(100) NOT NULL,
+ "SONARQUBE_PERMISSION" CHARACTER VARYING(64) NOT NULL
+);
+ALTER TABLE "GITHUB_PERMS_MAPPING" ADD CONSTRAINT "PK_GITHUB_PERMS_MAPPING" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "UNIQ_GITHUB_PERM_MAPPINGS" ON "GITHUB_PERMS_MAPPING"("GITHUB_ROLE" NULLS FIRST, "SONARQUBE_PERMISSION" NULLS FIRST);