Ver código fonte

SONAR-20312 add migration to require user consent for GH synchronization

tags/10.2.0.77647
Aurelien Poscia 9 meses atrás
pai
commit
1d8607c201

+ 72
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v102/AddUserConsentRequiredIfGithubAutoProvisioningEnabled.java Ver arquivo

@@ -0,0 +1,72 @@
package org.sonar.server.platform.db.migration.version.v102;

import com.google.common.annotations.VisibleForTesting;
import java.sql.SQLException;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.System2;
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.Upsert;

public class AddUserConsentRequiredIfGithubAutoProvisioningEnabled extends DataChange {

private static final Logger LOG = LoggerFactory.getLogger(AddUserConsentRequiredIfGithubAutoProvisioningEnabled.class);
@VisibleForTesting
static final String PROVISIONING_GITHUB_ENABLED_PROP_KEY = "provisioning.github.enabled";

@VisibleForTesting
static final String PROP_KEY = "sonar.auth.github.userConsentForPermissionProvisioningRequired";

private static final String INSERT_QUERY = """
INSERT INTO PROPERTIES (UUID, PROP_KEY, IS_EMPTY, CREATED_AT)
VALUES (?, ?, ?, ?)
""";

private final System2 system2;
private final UuidFactory uuidFactory;

public AddUserConsentRequiredIfGithubAutoProvisioningEnabled(Database db, System2 system2, UuidFactory uuidFactory) {
super(db);
this.system2 = system2;
this.uuidFactory = uuidFactory;
}

@Override
protected void execute(DataChange.Context context) throws SQLException {
if (!isGithubAutoProvisioningEnabled(context)) {
return;
}
if (isUserConsentAlreadyRequired(context)) {
return;
}
LOG.warn("Automatic synchronization was previously activated for GitHub. It requires user consent to continue working as new " +
" features were added with the synchronization. Please read the upgrade notes.");
Upsert upsert = context.prepareUpsert(INSERT_QUERY);
upsert
.setString(1, uuidFactory.create())
.setString(2, PROP_KEY)
.setBoolean(3, true)
.setLong(4, system2.now())
.execute()
.commit();
}

private static boolean isUserConsentAlreadyRequired(Context context) throws SQLException {
return Optional.ofNullable(context.prepareSelect("select count(*) from properties where prop_key = ?")
.setString(1, PROP_KEY)
.get(t -> 1 == t.getInt(1)))
.orElseThrow();
}

private static boolean isGithubAutoProvisioningEnabled(Context context) throws SQLException {
return Optional.ofNullable(context.prepareSelect("select count(*) from internal_properties where kee = ? and text_value = ?")
.setString(1, PROVISIONING_GITHUB_ENABLED_PROP_KEY)
.setString(2, "true")
.get(t -> 1 == t.getInt(1)))
.orElseThrow();
}

}

+ 1
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v102/DbVersion102.java Ver arquivo

@@ -110,6 +110,7 @@ public class DbVersion102 implements DbVersion {
.add(10_2_052, "Create index 'wd_task_uuid_created_at' in 'webhook_deliveries'", CreateIndexTaskUuidCreatedAtInWebhookDeliveries.class)
.add(10_2_053, "Create index 'wd_created_at' in 'webhook_deliveries'", CreateIndexCreatedAtInWebhookDeliveries.class)

.add(10_2_054, "Insert property github.userConsentementForPermissionProvisioningRequired", AddUserConsentRequiredIfGithubAutoProvisioningEnabled.class)
;
}
}

+ 106
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v102/AddUserConsentRequiredIfGithubAutoProvisioningEnabledTest.java Ver arquivo

@@ -0,0 +1,106 @@
/*
* 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.v102;

import java.sql.SQLException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.event.Level;
import org.sonar.api.testfixtures.log.LogTester;
import org.sonar.api.utils.System2;
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.sonar.server.platform.db.migration.version.v102.AddUserConsentRequiredIfGithubAutoProvisioningEnabled.PROP_KEY;
import static org.sonar.server.platform.db.migration.version.v102.AddUserConsentRequiredIfGithubAutoProvisioningEnabled.PROVISIONING_GITHUB_ENABLED_PROP_KEY;

public class AddUserConsentRequiredIfGithubAutoProvisioningEnabledTest {

@Rule
public LogTester logger = new LogTester();

@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(AddUserConsentRequiredIfGithubAutoProvisioningEnabledTest.class, "schema.sql");

private final DataChange underTest = new AddUserConsentRequiredIfGithubAutoProvisioningEnabled(db.database(), new System2(), UuidFactoryFast.getInstance());

@Before
public void before() {
logger.clear();
}

@Test
public void migration_whenGitHubAutoProvisioningPropertyNotPresent_shouldNotRequireConsent() throws SQLException {
underTest.execute();

assertThat(logger.logs(Level.WARN)).isEmpty();
assertThat(isConsentRequired()).isFalse();
}

@Test
public void migration_whenGitHubAutoProvisioningDisabled_shouldNotRequireConsent() throws SQLException {
disableGithubProvisioning();
underTest.execute();

assertThat(logger.logs(Level.WARN)).isEmpty();
assertThat(isConsentRequired()).isFalse();
}

@Test
public void migration_whenGitHubAutoProvisioningEnabled_shouldRequireConsent() throws SQLException {
enableGithubProvisioning();

underTest.execute();

assertThat(logger.logs(Level.WARN)).containsExactly("Automatic synchronization was previously activated for GitHub. It requires user consent to continue working as new"
+ " features were added with the synchronization. Please read the upgrade notes.");
assertThat(isConsentRequired()).isTrue();
}

@Test
public void migration_is_reentrant() throws SQLException {
enableGithubProvisioning();

underTest.execute();
underTest.execute();

assertThat(logger.logs(Level.WARN)).containsExactly("Automatic synchronization was previously activated for GitHub. It requires user consent to continue working as new"
+ " features were added with the synchronization. Please read the upgrade notes.");
assertThat(isConsentRequired()).isTrue();
}

private void disableGithubProvisioning() {
toggleGithubProvisioning(false);
}
private void enableGithubProvisioning() {
toggleGithubProvisioning(true);
}

private boolean isConsentRequired() {
return db.countSql("select count(*) from properties where prop_key = '" + PROP_KEY + "'") >= 1;
}

private void toggleGithubProvisioning(boolean enabled) {
db.executeInsert("internal_properties", "kee", PROVISIONING_GITHUB_ENABLED_PROP_KEY, "text_value", String.valueOf(enabled), "is_empty", true, "created_at", 0);
}
}

+ 21
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v102/AddUserConsentRequiredIfGithubAutoProvisioningEnabledTest/schema.sql Ver arquivo

@@ -0,0 +1,21 @@
CREATE TABLE "INTERNAL_PROPERTIES"(
"KEE" CHARACTER VARYING(40) NOT NULL,
"IS_EMPTY" BOOLEAN NOT NULL,
"TEXT_VALUE" CHARACTER VARYING(4000),
"CLOB_VALUE" CHARACTER LARGE OBJECT,
"CREATED_AT" BIGINT NOT NULL
);
ALTER TABLE "INTERNAL_PROPERTIES" ADD CONSTRAINT "PK_INTERNAL_PROPERTIES" PRIMARY KEY("KEE");

CREATE TABLE "PROPERTIES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"PROP_KEY" CHARACTER VARYING(512) NOT NULL,
"IS_EMPTY" BOOLEAN NOT NULL,
"TEXT_VALUE" CHARACTER VARYING(4000),
"CLOB_VALUE" CHARACTER LARGE OBJECT,
"CREATED_AT" BIGINT NOT NULL,
"ENTITY_UUID" CHARACTER VARYING(40),
"USER_UUID" CHARACTER VARYING(255)
);
ALTER TABLE "PROPERTIES" ADD CONSTRAINT "PK_PROPERTIES" PRIMARY KEY("UUID");
CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES"("PROP_KEY" NULLS FIRST);

Carregando…
Cancelar
Salvar