]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11271 Add application and portfolio creator to sonar-administrators group
authorEric Hartmann <hartmann.eric@gmail.com>
Tue, 9 Oct 2018 05:38:37 +0000 (07:38 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 10 Oct 2018 18:20:58 +0000 (20:20 +0200)
server/sonar-db-core/src/main/resources/org/sonar/db/version/rows-h2.sql
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest/group_roles_and_internal_properties.sql [new file with mode: 0644]

index 03a0ce6a1e4a9a97a7760ee724c5eea0d5dade64..643be98566392d512fb2e7cb788093bc10a0045d 100644 (file)
@@ -18,7 +18,9 @@ INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALU
 INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (4, 'AVdqnciQUUs7Zd3KPvFD', null, null, 'scan');
 INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (5, 'AVdqnciQUUs7Zd3KPvFD', null, null, 'provisioning');
 INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (6, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'provisioning');
-ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 7;
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (7, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'applicationcreator');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (8, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'portfoliocreator');
+ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 9;
 
 INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1);
 INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2);
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator.java
new file mode 100644 (file)
index 0000000..32e8512
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.platform.db.migration.version.v74;
+
+import java.sql.SQLException;
+import org.sonar.api.config.Configuration;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.SupportsBlueGreen;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProvider;
+
+@SupportsBlueGreen
+public class AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator extends DataChange {
+
+  private final Configuration configuration;
+  private final DefaultOrganizationUuidProvider defaultOrganizationUuidProvider;
+
+  public AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator(Database db, Configuration configuration,
+    DefaultOrganizationUuidProvider defaultOrganizationUuidProvider) {
+    super(db);
+    this.configuration = configuration;
+    this.defaultOrganizationUuidProvider = defaultOrganizationUuidProvider;
+  }
+
+  @Override
+  protected void execute(Context context) throws SQLException {
+    if (configuration.getBoolean("sonar.sonarcloud.enabled").orElse(false)) {
+      // Nothing to do on SonarCloud
+      return;
+    }
+
+    Integer sonarAdmGroupId = context.prepareSelect("select ID from GROUPS where name=?")
+      .setString(1, "sonar-administrators")
+      .get(r -> r.getInt(1));
+
+    if (sonarAdmGroupId == null) {
+      // We cannot find the default sonar-administrators groups
+      return;
+    }
+
+    insertPermissionIfMissing(context, sonarAdmGroupId, "applicationcreator");
+    insertPermissionIfMissing(context, sonarAdmGroupId, "portfoliocreator");
+  }
+
+  private void insertPermissionIfMissing(Context context, Integer sonarAdmGroupId, String role) throws SQLException {
+    if (isPermissionMissing(context, sonarAdmGroupId, role)) {
+      context.prepareUpsert("insert into GROUP_ROLES(ORGANIZATION_UUID, GROUP_ID, ROLE) values(?, ?, ?)")
+        .setString(1, defaultOrganizationUuidProvider.get(context))
+        .setInt(2, sonarAdmGroupId)
+        .setString(3, role)
+        .execute()
+        .commit();
+    }
+  }
+
+  private static boolean isPermissionMissing(Context context, Integer sonarAdmGroupId, String role) throws SQLException {
+    Integer count = context.prepareSelect("select count(ID) from GROUP_ROLES where GROUP_ID=? and ROLE=?")
+      .setInt(1, sonarAdmGroupId)
+      .setString(2, role)
+      .get(r -> r.getInt(1));
+
+    return count == null || count == 0;
+  }
+}
index 285adb6a2f471182dbe7b52221fbf1ca80b75725..b092e76abdc5cbd3f8d1003e7e4b1ccc65e2ee6a 100644 (file)
@@ -47,8 +47,8 @@ public class DbVersion74 implements DbVersion {
       .add(2324, "Create new creator permissions for applications and portfolios", CreateApplicationsAndPortfoliosCreatorPermissions.class)
       .add(2325, "Add default templates for applications and portfolios", AddDefaultPermTemplateColumnsToOrganizations.class)
       .add(2326, "Create new creator permissions for applications and portfolios", CreateApplicationsAndPortfoliosCreatorPermissions.class)
-      .add(2327, "Add default templates for applications and portfolios", AddDefaultPermTemplateColumnsToOrganizations.class)
-      .add(2328, "Populate default template permissions on organizations", PopulateDefaultPermTemplateOnOrganizations.class)
+      .add(2327, "Populate default template permissions on organizations", PopulateDefaultPermTemplateOnOrganizations.class)
+      .add(2328, "Add portfolio and application creator permissions on sonar-administrators group", AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator.class)
     ;
   }
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest.java
new file mode 100644 (file)
index 0000000..b9908b7
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.platform.db.migration.version.v74;
+
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProvider;
+import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProviderImpl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest {
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest.class,
+    "group_roles_and_internal_properties.sql");
+
+  private UuidFactoryFast uuidFactoryFast = UuidFactoryFast.getInstance();
+  private MapSettings settings = new MapSettings();
+  private DefaultOrganizationUuidProvider defaultOrganizationUuidProvider = new DefaultOrganizationUuidProviderImpl();
+  private AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator underTest = new AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator(db.database(), settings.asConfig(),
+    defaultOrganizationUuidProvider);
+
+  @Test
+  public void is_reentrant() throws SQLException {
+    String orgUuid = uuidFactoryFast.create();
+    insertDefaultOrganizationUuid(orgUuid);
+    insertGroup(orgUuid, "sonar-administrators");
+    Long adminGroupId = getGroupId("sonar-administrators");
+
+    underTest.execute();
+    underTest.execute();
+
+    assertGroupRoles(
+      tuple(orgUuid, adminGroupId, null, "applicationcreator"),
+      tuple(orgUuid, adminGroupId, null, "portfoliocreator"));
+  }
+
+  @Test
+  public void create_missing_permissions() throws SQLException {
+    String orgUuid = uuidFactoryFast.create();
+    insertDefaultOrganizationUuid(orgUuid);
+    insertGroup(orgUuid, "sonar-administrators");
+    Long adminGroupId = getGroupId("sonar-administrators");
+
+    underTest.execute();
+
+    assertGroupRoles(
+      tuple(orgUuid, adminGroupId, null, "applicationcreator"),
+      tuple(orgUuid, adminGroupId, null, "portfoliocreator"));
+  }
+
+  @Test
+  public void has_no_effect_if_group_does_not_exist() throws SQLException {
+    String orgUuid = uuidFactoryFast.create();
+    insertDefaultOrganizationUuid(orgUuid);
+    insertGroup(orgUuid, "sonar");
+
+    underTest.execute();
+
+    assertGroupRoles();
+  }
+
+  @Test
+  public void has_no_effect_if_roles_are_already_present() throws SQLException {
+    String orgUuid = uuidFactoryFast.create();
+    insertDefaultOrganizationUuid(orgUuid);
+    insertGroup(orgUuid, "sonar-administrators");
+    Long adminGroupId = getGroupId("sonar-administrators");
+    insertGroupRole(orgUuid, adminGroupId, null, "applicationcreator");
+    insertGroupRole(orgUuid, adminGroupId, null, "portfoliocreator");
+
+    underTest.execute();
+
+    assertGroupRoles(
+      tuple(orgUuid, adminGroupId, null, "applicationcreator"),
+      tuple(orgUuid, adminGroupId, null, "portfoliocreator"));
+  }
+
+  @Test
+  public void has_no_effect_on_SonarCloud() throws SQLException {
+    settings.setProperty("sonar.sonarcloud.enabled", true);
+    underTest.execute();
+    assertGroupRoles();
+  }
+
+  private void insertDefaultOrganizationUuid(String uuid) {
+    db.executeInsert("INTERNAL_PROPERTIES",
+      "KEE", "organization.default",
+      "IS_EMPTY", false,
+      "TEXT_VALUE", uuid,
+      "CREATED_AT", System.currentTimeMillis());
+  }
+
+  private void insertGroup(String organizationUuid, String name) {
+    db.executeInsert("GROUPS",
+      "ORGANIZATION_UUID", organizationUuid,
+      "NAME", name,
+      "CREATED_AT", new Date(),
+      "UPDATED_AT", new Date());
+  }
+
+  private void insertGroupRole(String organizationUuid, @Nullable Long groupId, @Nullable Integer resourceId, String role) {
+    db.executeInsert("GROUP_ROLES",
+      "ORGANIZATION_UUID", organizationUuid,
+      "GROUP_ID", groupId,
+      "RESOURCE_ID", resourceId,
+      "ROLE", role);
+  }
+
+  private Long getGroupId(String groupName) {
+    return (Long) db.selectFirst("SELECT id FROM groups WHERE name = '" + groupName + "'").get("ID");
+  }
+
+  private void assertGroupRoles(Tuple... expectedTuples) {
+    assertThat(db.select("SELECT organization_uuid, group_id, resource_id, role FROM group_roles")
+      .stream()
+      .map(row -> new Tuple(row.get("ORGANIZATION_UUID"), row.get("GROUP_ID"), row.get("RESOURCE_ID"), row.get("ROLE")))
+      .collect(Collectors.toList()))
+      .containsExactlyInAnyOrder(expectedTuples);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest/group_roles_and_internal_properties.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest/group_roles_and_internal_properties.sql
new file mode 100644 (file)
index 0000000..8871f93
--- /dev/null
@@ -0,0 +1,36 @@
+CREATE TABLE "PROPERTIES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROP_KEY" VARCHAR(512),
+  "RESOURCE_ID" INTEGER,
+  "TEXT_VALUE" CLOB(2147483647),
+  "USER_ID" INTEGER
+);
+
+CREATE TABLE "INTERNAL_PROPERTIES" (
+  "KEE" VARCHAR(50) NOT NULL PRIMARY KEY,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT
+);
+
+CREATE UNIQUE INDEX "UNIQ_INTERNAL_PROPERTIES" ON "INTERNAL_PROPERTIES" ("KEE");
+
+CREATE TABLE "GROUPS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(500),
+  "DESCRIPTION" VARCHAR(200),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+CREATE TABLE "GROUP_ROLES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "GROUP_ID" INTEGER,
+  "RESOURCE_ID" INTEGER,
+  "ROLE" VARCHAR(64) NOT NULL
+);
+CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES" ("RESOURCE_ID");
+CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES" ("ORGANIZATION_UUID", "GROUP_ID", "RESOURCE_ID", "ROLE");