Sfoglia il codice sorgente

SONAR-20700 Move GithubPermissionConverter to community edition

tags/10.3.0.82913
Aurelien Poscia 7 mesi fa
parent
commit
f5f71fdbe1

+ 109
- 0
server/sonar-auth-github/src/main/java/org/sonar/auth/github/GithubPermissionConverter.java Vedi File

@@ -0,0 +1,109 @@
/*
* 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.auth.github;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.db.provisioning.GithubPermissionsMappingDto;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.sonar.server.permission.PermissionServiceImpl.ALL_PROJECT_PERMISSIONS;

public class GithubPermissionConverter {
private static final Logger LOG = LoggerFactory.getLogger(GithubPermissionConverter.class);
private static final String PULL_GROUP_PERMISSION = "pull";
private static final String TRIAGE_GROUP_PERMISSION = "triage";
private static final String PUSH_GROUP_PERMISSION = "push";
private static final String MAINTAIN_GROUP_PERMISSION = "maintain";
private static final String ADMIN_GROUP_PERMISSION = "admin";
private static final String READ_GITHUB_ROLE = "read";
private static final String TRIAGE_GITHUB_ROLE = "triage";
private static final String WRITE_GITHUB_ROLE = "write";
private static final String MAINTAIN_GITHUB_ROLE = "maintain";
private static final String ADMIN_GITHUB_ROLE = "admin";

private static final Map<String, String> GITHUB_GROUP_PERMISSION_TO_ROLE_NAME = Map.of(
PULL_GROUP_PERMISSION, READ_GITHUB_ROLE,
TRIAGE_GROUP_PERMISSION, TRIAGE_GITHUB_ROLE,
PUSH_GROUP_PERMISSION, WRITE_GITHUB_ROLE,
MAINTAIN_GROUP_PERMISSION, MAINTAIN_GITHUB_ROLE,
ADMIN_GROUP_PERMISSION, ADMIN_GITHUB_ROLE);

private static final Map<GsonRepositoryPermissions, String> GITHUB_PERMISSION_TO_GITHUB_BASE_ROLE = Map.of(
new GsonRepositoryPermissions(false, false, false, false, false), "none",
new GsonRepositoryPermissions(false, false, false, false, true), READ_GITHUB_ROLE,
new GsonRepositoryPermissions(false, false, false, true, true), TRIAGE_GITHUB_ROLE,
new GsonRepositoryPermissions(false, false, true, true, true), WRITE_GITHUB_ROLE,
new GsonRepositoryPermissions(false, true, true, true, true), MAINTAIN_GITHUB_ROLE,
new GsonRepositoryPermissions(true, true, true, true, true), ADMIN_GITHUB_ROLE
);

public Map<String, Boolean> toSonarqubeRolesToHasPermissions(Set<String> sonarqubeRoles) {
return ALL_PROJECT_PERMISSIONS.stream()
.collect(toMap(identity(), sonarqubeRoles::contains));
}

public Set<String> toSonarqubeRolesWithFallbackOnRepositoryPermissions(Set<GithubPermissionsMappingDto> allPermissionsMappings,
String githubRoleOrPermission, GsonRepositoryPermissions repositoryPermissions) {
String roleName = toRoleName(githubRoleOrPermission);
return toSonarqubeRoles(allPermissionsMappings, roleName, repositoryPermissions);
}

private static String toRoleName(String permission) {
return GITHUB_GROUP_PERMISSION_TO_ROLE_NAME.getOrDefault(permission, permission);
}

public Set<String> toSonarqubeRolesForDefaultRepositoryPermission(Set<GithubPermissionsMappingDto> allPermissionsMappings, String roleName) {
return toSonarqubeRoles(allPermissionsMappings, roleName, null);
}

private static Set<String> toSonarqubeRoles(Set<GithubPermissionsMappingDto> allPermissionsMappings, String githubRoleName,
@Nullable GsonRepositoryPermissions repositoryPermissions) {
Map<String, List<GithubPermissionsMappingDto>> permissionMappings = allPermissionsMappings.stream()
.collect(Collectors.groupingBy(GithubPermissionsMappingDto::githubRole));

Set<String> sonarqubePermissions = Optional.ofNullable(permissionMappings.get(githubRoleName))
.orElse(GithubPermissionConverter.computeBaseRoleAndGetSqPermissions(permissionMappings, repositoryPermissions))
.stream()
.map(GithubPermissionsMappingDto::sonarqubePermission)
.collect(Collectors.toSet());

if (sonarqubePermissions.isEmpty()) {
LOG.warn("No permission found matching role:{}, and permissions {}", githubRoleName, repositoryPermissions);
}
return sonarqubePermissions;
}

private static List<GithubPermissionsMappingDto> computeBaseRoleAndGetSqPermissions(Map<String, List<GithubPermissionsMappingDto>> permissionMappings,
@Nullable GsonRepositoryPermissions repositoryPermissions) {
return Optional.ofNullable(repositoryPermissions)
.map(GITHUB_PERMISSION_TO_GITHUB_BASE_ROLE::get)
.map(permissionMappings::get)
.orElse(List.of());
}

}

+ 30
- 0
server/sonar-auth-github/src/main/java/org/sonar/auth/github/GsonRepositoryPermissions.java Vedi File

@@ -0,0 +1,30 @@
/*
* 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.auth.github;

import com.google.gson.annotations.SerializedName;

public record GsonRepositoryPermissions(
@SerializedName("admin") boolean admin,
@SerializedName("maintain") boolean maintain,
@SerializedName("push") boolean push,
@SerializedName("triage") boolean triage,
@SerializedName("pull") boolean pull) {
}

+ 123
- 0
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GithubPermissionConverterTest.java Vedi File

@@ -0,0 +1,123 @@
/*
* 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.auth.github;

import java.util.Arrays;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Suite;
import org.sonar.db.provisioning.GithubPermissionsMappingDto;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(Suite.class)
@Suite.SuiteClasses({
GithubPermissionConverterTest.ToSonarqubeRolesForDefaultRepositoryPermissionTest.class,
GithubPermissionConverterTest.ToSonarqubeRolesWithFallbackOnRepositoryPermissionsTest.class
})
public class GithubPermissionConverterTest {

private static final Set<GithubPermissionsMappingDto> ALL_PERMISSIONS_MAPPING_FROM_DB = Set.of(
new GithubPermissionsMappingDto("uuid1", "read", "roleRead"),
new GithubPermissionsMappingDto("uuid2", "triage", "roleTriage"),
new GithubPermissionsMappingDto("uuid3", "write", "roleWrite"),
new GithubPermissionsMappingDto("uuid4", "maintain", "roleMaintain"),
new GithubPermissionsMappingDto("uuid5", "admin", "roleAdmin")
) ;

private static final GsonRepositoryPermissions NO_PERMS = new GsonRepositoryPermissions(false, false, false, false, false);
private static final GsonRepositoryPermissions READ_PERMS = new GsonRepositoryPermissions(false, false, false, false, true);
private static final GsonRepositoryPermissions TRIAGE_PERMS = new GsonRepositoryPermissions(false, false, false, true, true);
private static final GsonRepositoryPermissions WRITE_PERMS = new GsonRepositoryPermissions(false, false, true, true, true);
private static final GsonRepositoryPermissions MAINTAIN_PERMS = new GsonRepositoryPermissions(false, true, true, true, true);
private static final GsonRepositoryPermissions ADMIN_PERMS = new GsonRepositoryPermissions(true, true, true, true, true);

@RunWith(Parameterized.class)
public static class ToSonarqubeRolesWithFallbackOnRepositoryPermissionsTest {
private final GithubPermissionConverter githubPermissionConverter = new GithubPermissionConverter();
private final String role;
private final GsonRepositoryPermissions repositoryPermissions;
private final Set<String> expectedSqPermissions;

@Parameterized.Parameters(name = "GH role:{0}, GH perms:{1}, Expected SQ perms:{2}")
public static Iterable<Object[]> testData() {
return Arrays.asList(new Object[][] {
{"none", NO_PERMS, Set.of()},
{"read", NO_PERMS, Set.of("roleRead")},
{"read", READ_PERMS, Set.of("roleRead")},
{"pull", NO_PERMS, Set.of("roleRead")},
{"triage", NO_PERMS, Set.of("roleTriage")},
{"write", NO_PERMS, Set.of("roleWrite")},
{"push", NO_PERMS, Set.of("roleWrite")},
{"maintain", NO_PERMS, Set.of("roleMaintain")},
{"admin", NO_PERMS, Set.of("roleAdmin")},
{"custom_role_extending_read", READ_PERMS, Set.of("roleRead")},
{"custom_role_extending_triage", TRIAGE_PERMS, Set.of("roleTriage")},
{"custom_role_extending_write", WRITE_PERMS, Set.of("roleWrite")},
{"custom_role_extending_maintain", MAINTAIN_PERMS, Set.of("roleMaintain")},
{"custom_role_extending_admin", ADMIN_PERMS, Set.of("roleAdmin")},
});
}

public ToSonarqubeRolesWithFallbackOnRepositoryPermissionsTest(String role, GsonRepositoryPermissions repositoryPermissions, Set<String> expectedSqPermissions) {
this.role = role;
this.repositoryPermissions = repositoryPermissions;
this.expectedSqPermissions = expectedSqPermissions;
}

@Test
public void toGithubRepositoryPermissions_convertsCorrectly() {
Set<String> actualPermissions = githubPermissionConverter.toSonarqubeRolesWithFallbackOnRepositoryPermissions(ALL_PERMISSIONS_MAPPING_FROM_DB, role, repositoryPermissions);
assertThat(actualPermissions).isEqualTo(expectedSqPermissions);
}
}

@RunWith(Parameterized.class)
public static class ToSonarqubeRolesForDefaultRepositoryPermissionTest {
private final GithubPermissionConverter githubPermissionConverter = new GithubPermissionConverter();
private final String role;
private final Set<String> expectedSqPermissions;

@Parameterized.Parameters(name = "GH role:{0}, GH perms:{1}, Expected SQ perms:{2}")
public static Iterable<Object[]> testData() {
return Arrays.asList(new Object[][] {
{"none", Set.of()},
{"read", Set.of("roleRead")},
{"triage", Set.of("roleTriage")},
{"write", Set.of("roleWrite")},
{"maintain", Set.of("roleMaintain")},
{"admin", Set.of("roleAdmin")}
});
}

public ToSonarqubeRolesForDefaultRepositoryPermissionTest(String role, Set<String> expectedSqPermissions) {
this.role = role;
this.expectedSqPermissions = expectedSqPermissions;
}

@Test
public void toGithubRepositoryPermissions_convertsCorrectly() {
Set<String> actualPermissions = githubPermissionConverter.toSonarqubeRolesForDefaultRepositoryPermission(ALL_PERMISSIONS_MAPPING_FROM_DB, role);
assertThat(actualPermissions).isEqualTo(expectedSqPermissions);
}
}
}

server/sonar-webserver-auth/src/main/java/org/sonar/server/permission/PermissionService.java → server/sonar-server-common/src/main/java/org/sonar/server/permission/PermissionService.java Vedi File


server/sonar-webserver-auth/src/main/java/org/sonar/server/permission/PermissionServiceImpl.java → server/sonar-server-common/src/main/java/org/sonar/server/permission/PermissionServiceImpl.java Vedi File


+ 23
- 0
server/sonar-server-common/src/main/java/org/sonar/server/permission/package-info.java Vedi File

@@ -0,0 +1,23 @@
/*
* 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.
*/
@ParametersAreNonnullByDefault
package org.sonar.server.permission;

import javax.annotation.ParametersAreNonnullByDefault;

server/sonar-webserver-auth/src/test/java/org/sonar/server/permission/PermissionServiceImplTest.java → server/sonar-server-common/src/test/java/org/sonar/server/permission/PermissionServiceImplTest.java Vedi File


Loading…
Annulla
Salva