]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19085 Remove external_groups entries when GitHub provisioning is deactivated
authorAurelien Poscia <aurelien.poscia@sonarsource.com>
Wed, 10 May 2023 08:40:24 +0000 (10:40 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 11 May 2023 20:03:15 +0000 (20:03 +0000)
server/sonar-auth-github/src/main/java/org/sonar/auth/github/GitHubSettings.java
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubIdentityProviderTest.java
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubSettingsTest.java
server/sonar-auth-github/src/test/java/org/sonar/auth/github/IntegrationTest.java
server/sonar-db-dao/src/it/java/org/sonar/db/user/ExternalGroupDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/user/ExternalGroupDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/user/ExternalGroupMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/user/ExternalGroupMapper.xml

index f3fb6f07304625bc0d7c8ad374304919584a381e..32465a2d9991bc87811f2d8c96d4f05f8e1a234e 100644 (file)
@@ -27,6 +27,8 @@ import javax.annotation.Nullable;
 import org.sonar.api.PropertyType;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.PropertyDefinition;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
 import org.sonar.server.property.InternalProperties;
 
 import static java.lang.String.format;
@@ -60,10 +62,12 @@ public class GitHubSettings {
   private final Configuration configuration;
 
   private final InternalProperties internalProperties;
+  private final DbClient dbClient;
 
-  public GitHubSettings(Configuration configuration, InternalProperties internalProperties) {
+  public GitHubSettings(Configuration configuration, InternalProperties internalProperties, DbClient dbClient) {
     this.configuration = configuration;
     this.internalProperties = internalProperties;
+    this.dbClient = dbClient;
   }
 
   String clientId() {
@@ -119,10 +123,19 @@ public class GitHubSettings {
   public void setProvisioning(boolean enableProvisioning) {
     if (enableProvisioning) {
       checkGithubConfigIsCompleteForProvisioning();
+    } else {
+      removeExternalGroupsForGithub();
     }
     internalProperties.write(PROVISIONING, String.valueOf(enableProvisioning));
   }
 
+  private void removeExternalGroupsForGithub() {
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      dbClient.externalGroupDao().deleteByExternalIdentityProvider(dbSession, GitHubIdentityProvider.KEY);
+      dbSession.commit();
+    }
+  }
+
   private void checkGithubConfigIsCompleteForProvisioning() {
     checkState(isEnabled(), getErrorMessage("GitHub authentication must be enabled"));
     checkState(isNotBlank(appId()), getErrorMessage("Application ID must be provided"));
index 491413a39ec566283e218e5bf2feba8f342b1ff5..c702c39b3fe51b8c441ac4f9949be1abb553bcc5 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.auth.github;
 import org.junit.Test;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.authentication.OAuth2IdentityProvider;
+import org.sonar.db.DbClient;
 import org.sonar.server.property.InternalProperties;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -35,7 +36,7 @@ public class GitHubIdentityProviderTest {
 
   private MapSettings settings = new MapSettings();
   private InternalProperties internalProperties = mock(InternalProperties.class);
-  private GitHubSettings gitHubSettings = new GitHubSettings(settings.asConfig(), internalProperties);
+  private GitHubSettings gitHubSettings = new GitHubSettings(settings.asConfig(), internalProperties, mock(DbClient.class));
   private UserIdentityFactoryImpl userIdentityFactory = mock(UserIdentityFactoryImpl.class);
   private ScribeGitHubApi scribeApi = new ScribeGitHubApi(gitHubSettings);
   private GitHubRestClient gitHubRestClient = new GitHubRestClient(gitHubSettings);
index c5291b5babc689b3decd64c80f689cac0e2a4daa..8fb0125b7f87f4d65086a59468729231496a7dcf 100644 (file)
 package org.sonar.auth.github;
 
 import java.util.Optional;
+import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.config.PropertyDefinitions;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.GroupDto;
 import org.sonar.server.property.InternalProperties;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -34,11 +37,13 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class GitHubSettingsTest {
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
 
   private MapSettings settings = new MapSettings(new PropertyDefinitions(System2.INSTANCE, GitHubSettings.definitions()));
   private InternalProperties internalProperties = mock(InternalProperties.class);
 
-  private GitHubSettings underTest = new GitHubSettings(settings.asConfig(), internalProperties);
+  private GitHubSettings underTest = new GitHubSettings(settings.asConfig(), internalProperties, db.getDbClient());
 
   @Test
   public void is_enabled() {
@@ -133,11 +138,22 @@ public class GitHubSettingsTest {
   }
 
   @Test
-  public void setProvisioning_whenPassedFalse_delegatesToInternalPropertiesWrite() {
+  public void setProvisioning_whenPassedFalse_delegatesToInternalPropertiesWriteAndCleansUpExternalGroups() {
+    GroupDto groupDto = createGithubManagedGroup();
+
     underTest.setProvisioning(false);
+
     verify(internalProperties).write(GitHubSettings.PROVISIONING, Boolean.FALSE.toString());
+    assertThat(db.getDbClient().externalGroupDao().selectByGroupUuid(db.getSession(), groupDto.getUuid())).isEmpty();
   }
 
+  private GroupDto createGithubManagedGroup() {
+    GroupDto groupDto = db.users().insertGroup();
+    db.users().markGroupAsGithubManaged(groupDto.getUuid());
+    return groupDto;
+  }
+
+
   @Test
   public void return_client_id() {
     settings.setProperty("sonar.auth.github.clientId.secured", "id");
index 9af6681ab46da28dbc55a0288036e163ca7f626c..1cccec8eab1736a84a09b47b8878d1a97b13d835 100644 (file)
@@ -64,7 +64,7 @@ public class IntegrationTest {
   // load settings with default values
   private MapSettings settings = new MapSettings(new PropertyDefinitions(System2.INSTANCE, GitHubSettings.definitions()));
   private InternalProperties internalProperties = new InternalPropertiesImpl(db.getDbClient());
-  private GitHubSettings gitHubSettings = new GitHubSettings(settings.asConfig(), internalProperties);
+  private GitHubSettings gitHubSettings = new GitHubSettings(settings.asConfig(), internalProperties, db.getDbClient());
   private UserIdentityFactoryImpl userIdentityFactory = new UserIdentityFactoryImpl();
   private ScribeGitHubApi scribeApi = new ScribeGitHubApi(gitHubSettings);
   private GitHubRestClient gitHubRestClient = new GitHubRestClient(gitHubSettings);
index 6de7ba2c279c62f67df94fa46da115ccae56d948..57c31bc2ccf12ec35c9acfa57218975cfbb2ae91 100644 (file)
@@ -34,6 +34,7 @@ public class ExternalGroupDaoIT {
   private static final String GROUP_UUID = "uuid";
   private static final String EXTERNAL_ID = "external_id";
   private static final String EXTERNAL_IDENTITY_PROVIDER = "external_identity_provider";
+  private static final String PROVIDER = "provider1";
 
   @Rule
   public final DbTester db = DbTester.create();
@@ -69,9 +70,9 @@ public class ExternalGroupDaoIT {
 
   @Test
   public void selectByIdentityProvider_returnOnlyGroupForTheIdentityProvider() {
-    List<ExternalGroupDto> expectedGroups = createAndInsertExternalGroupDtos("provider1", 3);
+    List<ExternalGroupDto> expectedGroups = createAndInsertExternalGroupDtos(PROVIDER, 3);
     createAndInsertExternalGroupDtos("provider2", 1);
-    List<ExternalGroupDto> savedGroup = underTest.selectByIdentityProvider(dbSession, "provider1");
+    List<ExternalGroupDto> savedGroup = underTest.selectByIdentityProvider(dbSession, PROVIDER);
     assertThat(savedGroup).containsExactlyInAnyOrderElementsOf(expectedGroups);
   }
 
@@ -96,14 +97,25 @@ public class ExternalGroupDaoIT {
 
   @Test
   public void deleteByGroupUuid_deletesTheGroup() {
-    List<ExternalGroupDto> insertedGroups = createAndInsertExternalGroupDtos("provider1", 3);
+    List<ExternalGroupDto> insertedGroups = createAndInsertExternalGroupDtos(PROVIDER, 3);
 
     ExternalGroupDto toRemove = insertedGroups.remove(0);
     underTest.deleteByGroupUuid(dbSession, toRemove.groupUuid());
-    List<ExternalGroupDto> remainingGroups = underTest.selectByIdentityProvider(dbSession, "provider1");
+    List<ExternalGroupDto> remainingGroups = underTest.selectByIdentityProvider(dbSession, PROVIDER);
     assertThat(remainingGroups).containsExactlyInAnyOrderElementsOf(insertedGroups);
   }
 
+  @Test
+  public void deleteByExternalIdentityProvider_onlyDeletesGroupOfTheRequestedProvider() {
+    createAndInsertExternalGroupDtos(PROVIDER, 3);
+    List<ExternalGroupDto> groupsProvider2 = createAndInsertExternalGroupDtos("provider2", 3);
+
+    underTest.deleteByExternalIdentityProvider(dbSession, PROVIDER);
+
+    assertThat(underTest.selectByIdentityProvider(dbSession, PROVIDER)).isEmpty();
+    assertThat(underTest.selectByIdentityProvider(dbSession, "provider2")).containsExactlyInAnyOrderElementsOf(groupsProvider2);
+  }
+
   @Test
   public void getManagedGroupsSqlFilter_whenFilterByManagedIsTrue_returnsCorrectQuery() {
     String filterManagedUser = underTest.getManagedGroupSqlFilter(true);
index 743236638fb4aa05a142567a1a5c38532088424d..748260d9ae1f7f659794a684ba14ca7ed8eaa245 100644 (file)
@@ -53,4 +53,8 @@ public class ExternalGroupDao implements Dao {
   public String getManagedGroupSqlFilter(boolean filterByManaged) {
     return String.format("%s exists (select group_uuid from external_groups eg where eg.group_uuid = uuid)", filterByManaged ? "" : "not");
   }
+
+  public void deleteByExternalIdentityProvider(DbSession dbSession, String externalIdentityProvider) {
+    mapper(dbSession).deleteByExternalIdentityProvider(externalIdentityProvider);
+  }
 }
index 908aae7664f9351f12c14c02815db0d7e9c9a9e1..6a5c89a26b576910c5bceeb1b1950e6e7f098df9 100644 (file)
@@ -34,4 +34,6 @@ public interface ExternalGroupMapper {
   Optional<ExternalGroupDto> selectByExternalIdAndIdentityProvider(@Param("externalId") String externalId, @Param("identityProvider") String identityProvider);
 
   void deleteByGroupUuid(@Param("groupUuid") String groupUuid);
+
+  void deleteByExternalIdentityProvider(String externalIdentityProvider);
 }
index a63497ece33e2518790a05c747430dd866e49024..e82fce1efdd77035427c5cd0ee14f566f84a8ba9 100644 (file)
@@ -50,4 +50,8 @@
     delete from external_groups where group_uuid = #{groupUuid, jdbcType=VARCHAR}
   </delete>
 
+  <delete id="deleteByExternalIdentityProvider" parameterType="String">
+    delete from external_groups where external_identity_provider = #{externalIdentityProvider, jdbcType=VARCHAR}
+  </delete>
+
 </mapper>