Merge branch 'master' into fix-dateTimeHelpers-test-linter-error

This commit is contained in:
Roman Zabaluev 2023-08-10 20:20:21 +07:00 committed by GitHub
commit 387554ebdb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 25 deletions

View file

@ -49,7 +49,7 @@ jobs:
cd kafka-ui-react-app/
pnpm test:CI
- name: SonarCloud Scan
uses: workshur/sonarcloud-github-action@improved_basedir
uses: sonarsource/sonarcloud-github-action@master
with:
projectBaseDir: ./kafka-ui-react-app
args: -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} -Dsonar.pullrequest.branch=${{ github.head_ref }} -Dsonar.pullrequest.base=${{ github.base_ref }}

View file

@ -5,6 +5,8 @@ import static com.provectus.kafka.ui.model.rbac.provider.Provider.Name.GITHUB;
import com.provectus.kafka.ui.model.rbac.Role;
import com.provectus.kafka.ui.model.rbac.provider.Provider;
import com.provectus.kafka.ui.service.rbac.AccessControlService;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -26,6 +28,8 @@ public class GithubAuthorityExtractor implements ProviderAuthorityExtractor {
private static final String ORGANIZATION_ATTRIBUTE_NAME = "organizations_url";
private static final String USERNAME_ATTRIBUTE_NAME = "login";
private static final String ORGANIZATION_NAME = "login";
private static final String ORGANIZATION = "organization";
private static final String TEAM_NAME = "slug";
private static final String GITHUB_ACCEPT_HEADER = "application/vnd.github+json";
private static final String DUMMY = "dummy";
// The number of results (max 100) per page of list organizations for authenticated user.
@ -46,7 +50,7 @@ public class GithubAuthorityExtractor implements ProviderAuthorityExtractor {
throw new RuntimeException();
}
Set<String> groupsByUsername = new HashSet<>();
Set<String> rolesByUsername = new HashSet<>();
String username = principal.getAttribute(USERNAME_ATTRIBUTE_NAME);
if (username == null) {
log.debug("Github username param is not present");
@ -59,13 +63,7 @@ public class GithubAuthorityExtractor implements ProviderAuthorityExtractor {
.filter(s -> s.getType().equals("user"))
.anyMatch(s -> s.getValue().equals(username)))
.map(Role::getName)
.forEach(groupsByUsername::add);
}
String organization = principal.getAttribute(ORGANIZATION_ATTRIBUTE_NAME);
if (organization == null) {
log.debug("Github organization param is not present");
return Mono.just(groupsByUsername);
.forEach(rolesByUsername::add);
}
OAuth2UserRequest req = (OAuth2UserRequest) additionalParams.get("request");
@ -80,8 +78,24 @@ public class GithubAuthorityExtractor implements ProviderAuthorityExtractor {
.getUserInfoEndpoint()
.getUri();
}
var webClient = WebClient.create(infoEndpoint);
WebClient webClient = WebClient.create(infoEndpoint);
Mono<Set<String>> rolesByOrganization = getOrganizationRoles(principal, additionalParams, acs, webClient);
Mono<Set<String>> rolesByTeams = getTeamRoles(webClient, additionalParams, acs);
return Mono.zip(rolesByOrganization, rolesByTeams)
.map((t) -> Stream.of(t.getT1(), t.getT2(), rolesByUsername)
.flatMap(Collection::stream)
.collect(Collectors.toSet()));
}
private Mono<Set<String>> getOrganizationRoles(DefaultOAuth2User principal, Map<String, Object> additionalParams,
AccessControlService acs, WebClient webClient) {
String organization = principal.getAttribute(ORGANIZATION_ATTRIBUTE_NAME);
if (organization == null) {
log.debug("Github organization param is not present");
return Mono.just(Collections.emptySet());
}
final Mono<List<Map<String, Object>>> userOrganizations = webClient
.get()
@ -99,22 +113,76 @@ public class GithubAuthorityExtractor implements ProviderAuthorityExtractor {
//@formatter:on
return userOrganizations
.map(orgsMap -> {
var groupsByOrg = acs.getRoles()
.stream()
.filter(role -> role.getSubjects()
.stream()
.filter(s -> s.getProvider().equals(Provider.OAUTH_GITHUB))
.filter(s -> s.getType().equals("organization"))
.anyMatch(subject -> orgsMap.stream()
.map(org -> org.get(ORGANIZATION_NAME).toString())
.distinct()
.anyMatch(orgName -> orgName.equalsIgnoreCase(subject.getValue()))
))
.map(Role::getName);
.map(orgsMap -> acs.getRoles()
.stream()
.filter(role -> role.getSubjects()
.stream()
.filter(s -> s.getProvider().equals(Provider.OAUTH_GITHUB))
.filter(s -> s.getType().equals(ORGANIZATION))
.anyMatch(subject -> orgsMap.stream()
.map(org -> org.get(ORGANIZATION_NAME).toString())
.anyMatch(orgName -> orgName.equalsIgnoreCase(subject.getValue()))
))
.map(Role::getName)
.collect(Collectors.toSet()));
}
return Stream.concat(groupsByOrg, groupsByUsername.stream()).collect(Collectors.toSet());
});
@SuppressWarnings("unchecked")
private Mono<Set<String>> getTeamRoles(WebClient webClient, Map<String, Object> additionalParams,
AccessControlService acs) {
var requestedTeams = acs.getRoles()
.stream()
.filter(r -> r.getSubjects()
.stream()
.filter(s -> s.getProvider().equals(Provider.OAUTH_GITHUB))
.anyMatch(s -> s.getType().equals("team")))
.collect(Collectors.toSet());
if (requestedTeams.isEmpty()) {
log.debug("No roles with github teams found, skipping");
return Mono.just(Collections.emptySet());
}
final Mono<List<Map<String, Object>>> rawTeams = webClient
.get()
.uri(uriBuilder -> uriBuilder.path("/teams")
.queryParam("per_page", ORGANIZATIONS_PER_PAGE)
.build())
.headers(headers -> {
headers.set(HttpHeaders.ACCEPT, GITHUB_ACCEPT_HEADER);
OAuth2UserRequest request = (OAuth2UserRequest) additionalParams.get("request");
headers.setBearerAuth(request.getAccessToken().getTokenValue());
})
.retrieve()
//@formatter:off
.bodyToMono(new ParameterizedTypeReference<>() {});
//@formatter:on
final Mono<List<String>> mappedTeams = rawTeams
.map(teams -> teams.stream()
.map(teamInfo -> {
var name = teamInfo.get(TEAM_NAME);
var orgInfo = (Map<String, Object>) teamInfo.get(ORGANIZATION);
var orgName = orgInfo.get(ORGANIZATION_NAME);
return orgName + "/" + name;
})
.map(Object::toString)
.collect(Collectors.toList())
);
return mappedTeams
.map(teams -> acs.getRoles()
.stream()
.filter(role -> role.getSubjects()
.stream()
.filter(s -> s.getProvider().equals(Provider.OAUTH_GITHUB))
.filter(s -> s.getType().equals("team"))
.anyMatch(subject -> teams.stream()
.anyMatch(teamName -> teamName.equalsIgnoreCase(subject.getValue()))
))
.map(Role::getName)
.collect(Collectors.toSet()));
}
}