diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2020-10-12 16:57:03 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2020-10-16 20:07:41 +0000 |
commit | a4ab9ccfce778e88cc82d1d04f197af9b3d1af19 (patch) | |
tree | 4b5947045bac1b24ad5d5f6840c3bef6e4eb13b3 /server/sonar-db-migration | |
parent | 16df95a4fa061755d0129927e29a3e7dc4794e8d (diff) | |
download | sonarqube-a4ab9ccfce778e88cc82d1d04f197af9b3d1af19.tar.gz sonarqube-a4ab9ccfce778e88cc82d1d04f197af9b3d1af19.zip |
SONAR-13936 Move default permission templates to internal properties
Diffstat (limited to 'server/sonar-db-migration')
6 files changed, 335 insertions, 0 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v85/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v85/package-info.java new file mode 100644 index 00000000000..62c81368b98 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v85/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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.v85; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/DbVersion86.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/DbVersion86.java index d759359e750..9e2283de50d 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/DbVersion86.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/DbVersion86.java @@ -41,6 +41,7 @@ public class DbVersion86 implements DbVersion { .add(4111, "Drop 'organization_uuid' in 'groups'", DropOrganizationInGroups.class) .add(4112, "Make 'name' column in 'groups' table not nullable", MakeNameColumnInGroupsTableNotNullable.class) .add(4113, "Make 'name' column in 'groups' table unique", AddUniqueIndexOnNameColumnOfGroupsTable.class) + .add(4114, "Move default permission templates to internal properties", MoveDefaultTemplatesToInternalProperties.class) ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalProperties.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalProperties.java new file mode 100644 index 00000000000..bec8fff7402 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalProperties.java @@ -0,0 +1,109 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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.v86; + +import java.sql.SQLException; +import java.util.Optional; +import org.sonar.api.utils.System2; +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; + +public class MoveDefaultTemplatesToInternalProperties extends DataChange { + + private final System2 system2; + + public MoveDefaultTemplatesToInternalProperties(Database db, System2 system2) { + super(db); + this.system2 = system2; + } + + @Override + protected void execute(Context context) throws SQLException { + OrganizationDefaultTemplates organizationDefaultTemplates = context + .prepareSelect("select org.default_perm_template_project, org.default_perm_template_port, org.default_perm_template_app from organizations org " + + "where org.kee = 'default-organization'") + .get(OrganizationDefaultTemplates::new); + if (organizationDefaultTemplates == null) { + throw new IllegalStateException("Default organization is missing"); + } + Upsert updateInternalProperties = context.prepareUpsert("insert into internal_properties (kee, text_value, is_empty, created_at) values (?, ?, ?, ?)"); + + Optional<String> defaultPermissionTemplateForProject = organizationDefaultTemplates.getDefaultPermissionTemplateForProject(); + if (defaultPermissionTemplateForProject.isPresent()) { + insertInInternalProperties(context, updateInternalProperties, "defaultTemplate.prj", defaultPermissionTemplateForProject.get()); + } else { + // If default permission templates are missing, they will be added during the startup task "RegisterPermissionTemplates" + return; + } + + organizationDefaultTemplates.getDefaultPermissionTemplateForPortfolio() + .ifPresent( + defaultPermissionTemplate -> insertInInternalProperties(context, updateInternalProperties, "defaultTemplate.port", defaultPermissionTemplate)); + organizationDefaultTemplates.getDefaultPermissionTemplateForApplication() + .ifPresent( + defaultPermissionTemplate -> insertInInternalProperties(context, updateInternalProperties, "defaultTemplate.app", defaultPermissionTemplate)); + } + + private void insertInInternalProperties(Context context, Upsert updateInternalProperties, String key, String value) { + try { + Integer isInternalPropertyAlreadyExists = context.prepareSelect("select count(1) from internal_properties ip where ip.kee = ?") + .setString(1, key) + .get(row -> row.getInt(1)); + if (isInternalPropertyAlreadyExists != null && isInternalPropertyAlreadyExists > 0) { + return; + } + updateInternalProperties + .setString(1, key) + .setString(2, value) + .setBoolean(3, false) + .setLong(4, system2.now()) + .execute() + .commit(); + } catch (SQLException throwables) { + throw new IllegalStateException(throwables); + } + } + + private static class OrganizationDefaultTemplates { + private final String defaultPermissionTemplateForProject; + private final String defaultPermissionTemplateForPortfolio; + private final String defaultPermissionTemplateForApplication; + + OrganizationDefaultTemplates(Select.Row row) throws SQLException { + this.defaultPermissionTemplateForProject = row.getNullableString(1); + this.defaultPermissionTemplateForPortfolio = row.getNullableString(2); + this.defaultPermissionTemplateForApplication = row.getNullableString(3); + } + + Optional<String> getDefaultPermissionTemplateForProject() { + return Optional.ofNullable(defaultPermissionTemplateForProject); + } + + Optional<String> getDefaultPermissionTemplateForPortfolio() { + return Optional.ofNullable(defaultPermissionTemplateForPortfolio); + } + + Optional<String> getDefaultPermissionTemplateForApplication() { + return Optional.ofNullable(defaultPermissionTemplateForApplication); + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/package-info.java new file mode 100644 index 00000000000..f5eff666f26 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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.v86; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalPropertiesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalPropertiesTest.java new file mode 100644 index 00000000000..32a6c3badd5 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalPropertiesTest.java @@ -0,0 +1,150 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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.v86; + +import java.sql.SQLException; +import javax.annotation.Nullable; +import org.assertj.core.groups.Tuple; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.impl.utils.TestSystem2; +import org.sonar.api.utils.System2; +import org.sonar.core.util.UuidFactory; +import org.sonar.core.util.UuidFactoryFast; +import org.sonar.db.CoreDbTester; +import org.sonar.server.platform.db.migration.step.DataChange; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +public class MoveDefaultTemplatesToInternalPropertiesTest { + + private static final long NOW = 100_000_000_000L; + + @Rule + public CoreDbTester db = CoreDbTester.createForSchema(MoveDefaultTemplatesToInternalPropertiesTest.class, "schema.sql"); + + private final UuidFactory uuidFactory = UuidFactoryFast.getInstance(); + private final System2 system2 = new TestSystem2().setNow(NOW); + + private final DataChange underTest = new MoveDefaultTemplatesToInternalProperties(db.database(), system2); + + @Test + public void create_internal_properties_for_all_components() throws SQLException { + insertDefaultOrganization("PRJ", "PORT", "APP"); + + underTest.execute(); + + assertInternalProperties( + tuple("defaultTemplate.prj", "PRJ", NOW), + tuple("defaultTemplate.port", "PORT", NOW), + tuple("defaultTemplate.app", "APP", NOW) + ); + } + + @Test + public void create_internal_properties_when_only_template_for_project() throws SQLException { + insertDefaultOrganization("PRJ", null, null); + + underTest.execute(); + + assertInternalProperties( + tuple("defaultTemplate.prj", "PRJ", NOW)); + } + + @Test + public void create_internal_properties_when_template_for_project_and_portfolio() throws SQLException { + insertDefaultOrganization("PRJ", "PORT", null); + + underTest.execute(); + + assertInternalProperties( + tuple("defaultTemplate.prj", "PRJ", NOW), + tuple("defaultTemplate.port", "PORT", NOW) + ); + } + + @Test + public void create_internal_properties_when_template_for_project_and_application() throws SQLException { + insertDefaultOrganization("PRJ", null, "APP"); + + underTest.execute(); + + assertInternalProperties( + tuple("defaultTemplate.prj", "PRJ", NOW), + tuple("defaultTemplate.app", "APP", NOW) + ); + } + + @Test + public void do_nothing_when_permission_template_for_project_is_missing() throws SQLException { + insertDefaultOrganization(null, null, "APP"); + + underTest.execute(); + + assertThat(db.countRowsOfTable("internal_properties")).isZero(); + } + + @Test + public void migration_is_reentrant() throws SQLException { + insertDefaultOrganization("PRJ", "PORT", "APP"); + + underTest.execute(); + underTest.execute(); + + assertInternalProperties( + tuple("defaultTemplate.prj", "PRJ", NOW), + tuple("defaultTemplate.port", "PORT", NOW), + tuple("defaultTemplate.app", "APP", NOW) + ); + } + + @Test + public void fail_when_default_organization_is_missing() { + assertThatThrownBy(underTest::execute) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Default organization is missing"); + } + + private void assertInternalProperties(Tuple... tuples) { + assertThat(db.select("select kee, text_value, created_at from internal_properties")) + .extracting(m -> m.get("KEE"), m -> m.get("TEXT_VALUE"), m -> m.get("CREATED_AT")) + .containsExactlyInAnyOrder(tuples); + } + + private void insertDefaultOrganization(@Nullable String defaultPermissionTemplateForProject, @Nullable String defaultPermissionTemplateForPortfolio, + @Nullable String defaultPermissionTemplateForApplication) { + String uuid = uuidFactory.create(); + db.executeInsert("organizations", + "uuid", uuid, + "kee", "default-organization", + "name", "name" + uuid, + "default_perm_template_project", defaultPermissionTemplateForProject, + "default_perm_template_port", defaultPermissionTemplateForPortfolio, + "default_perm_template_app", defaultPermissionTemplateForApplication, + "default_quality_gate_uuid", uuid, + "new_project_private", true, + "subscription", uuid, + "created_at", NOW, + "updated_at", NOW); + } + +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalPropertiesTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalPropertiesTest/schema.sql new file mode 100644 index 00000000000..a101d7797ce --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v86/MoveDefaultTemplatesToInternalPropertiesTest/schema.sql @@ -0,0 +1,29 @@ +CREATE TABLE "INTERNAL_PROPERTIES"( + "KEE" VARCHAR(20) NOT NULL, + "IS_EMPTY" BOOLEAN NOT NULL, + "TEXT_VALUE" VARCHAR(4000), + "CLOB_VALUE" CLOB, + "CREATED_AT" BIGINT NOT NULL +); +ALTER TABLE "INTERNAL_PROPERTIES" ADD CONSTRAINT "PK_INTERNAL_PROPERTIES" PRIMARY KEY("KEE"); + +CREATE TABLE "ORGANIZATIONS"( + "UUID" VARCHAR(40) NOT NULL, + "KEE" VARCHAR(255) NOT NULL, + "NAME" VARCHAR(255) NOT NULL, + "DESCRIPTION" VARCHAR(256), + "URL" VARCHAR(256), + "AVATAR_URL" VARCHAR(256), + "GUARDED" BOOLEAN, + "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40) NOT NULL, + "DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40), + "DEFAULT_PERM_TEMPLATE_APP" VARCHAR(40), + "DEFAULT_PERM_TEMPLATE_PORT" VARCHAR(40), + "NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL, + "SUBSCRIPTION" VARCHAR(40) NOT NULL, + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL, + "DEFAULT_GROUP_UUID" VARCHAR(40) +); +ALTER TABLE "ORGANIZATIONS" ADD CONSTRAINT "PK_ORGANIZATIONS" PRIMARY KEY("UUID"); +CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS"("KEE"); |