forked from SonarSource/sonarqube
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SONAR-11271 Add application and portfolio creator to sonar-administra…
…tors group
- Loading branch information
Showing
5 changed files
with
272 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
...b/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministrator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
...gration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
...reatorAndPortfolioCreatorToSonarAdministratorTest/group_roles_and_internal_properties.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"); |