Skip to content

Commit

Permalink
Testing update
Browse files Browse the repository at this point in the history
  • Loading branch information
C4tWithShell committed Dec 11, 2023
1 parent bad5315 commit 513f32a
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 312 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2023 Michael Clarke
* Copyright (C) 2020-2022 Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -28,14 +28,9 @@
import com.github.mc1arke.sonarqube.plugin.almclient.github.v3.model.AppToken;
import com.github.mc1arke.sonarqube.plugin.almclient.github.v3.model.InstallationRepositories;
import com.github.mc1arke.sonarqube.plugin.almclient.github.v3.model.Repository;
import com.google.common.annotations.VisibleForTesting;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultJwtBuilder;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
Expand All @@ -46,8 +41,16 @@
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;

@ServerSide
@ComputeEngineSide
Expand All @@ -72,70 +75,68 @@ public RestApplicationAuthenticationProvider(Clock clock, LinkHeaderReader linkH
this.objectMapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}

@Override
public RepositoryAuthenticationToken getInstallationToken(String apiUrl, String appId, String apiPrivateKey,
String projectPath) throws IOException {

Instant issued = clock.instant().minus(10, ChronoUnit.SECONDS);
Instant expiry = issued.plus(2, ChronoUnit.MINUTES);
String jwtToken = new DefaultJwtBuilder().setIssuedAt(Date.from(issued)).setExpiration(Date.from(expiry))
.claim("iss", appId).signWith(createPrivateKey(apiPrivateKey), SignatureAlgorithm.RS256).compact();
@VisibleForTesting
protected List<AppInstallation> getAppInstallations(ObjectMapper objectMapper, String apiUrl, String jwtToken) throws IOException {

Optional<RepositoryAuthenticationToken> repositoryAuthenticationToken = findTokenFromAppInstallationList(getV3Url(apiUrl) + "/app/installations", jwtToken, projectPath);

return repositoryAuthenticationToken.orElseThrow(() -> new InvalidConfigurationException(InvalidConfigurationException.Scope.PROJECT,
"No token could be found with access to the requested repository using the given application ID and key"));
}
List<AppInstallation> appInstallations = new ArrayList<>();

private Optional<RepositoryAuthenticationToken> findTokenFromAppInstallationList(String apiUrl, String jwtToken, String projectPath) throws IOException {
URLConnection appConnection = urlProvider.createUrlConnection(apiUrl);
appConnection.setRequestProperty(ACCEPT_HEADER, APP_PREVIEW_ACCEPT_HEADER);
appConnection.setRequestProperty(AUTHORIZATION_HEADER, BEARER_AUTHORIZATION_HEADER_PREFIX + jwtToken);

try (Reader reader = new InputStreamReader(appConnection.getInputStream())) {
AppInstallation[] appInstallations = objectMapper.readerFor(AppInstallation[].class).readValue(reader);
for (AppInstallation appInstallation : appInstallations) {
Optional<RepositoryAuthenticationToken> repositoryAuthenticationToken = findAppTokenFromAppInstallation(appInstallation, jwtToken, projectPath);

if (repositoryAuthenticationToken.isPresent()) {
return repositoryAuthenticationToken;
}
}
appInstallations.addAll(Arrays.asList(objectMapper.readerFor(AppInstallation[].class).readValue(reader)));
}

Optional<String> nextLink = linkHeaderReader.findNextLink(appConnection.getHeaderField("Link"));
if (nextLink.isEmpty()) {
return Optional.empty();
if (nextLink.isPresent()) {
appInstallations.addAll(getAppInstallations(objectMapper, nextLink.get(), jwtToken));
}

return findTokenFromAppInstallationList(nextLink.get(), jwtToken, projectPath);
return appInstallations;
}

private Optional<RepositoryAuthenticationToken> findAppTokenFromAppInstallation(AppInstallation installation, String jwtToken, String projectPath) throws IOException {
URLConnection accessTokenConnection = urlProvider.createUrlConnection(installation.getAccessTokensUrl());
((HttpURLConnection) accessTokenConnection).setRequestMethod("POST");
accessTokenConnection.setRequestProperty(ACCEPT_HEADER, APP_PREVIEW_ACCEPT_HEADER);
accessTokenConnection
.setRequestProperty(AUTHORIZATION_HEADER, BEARER_AUTHORIZATION_HEADER_PREFIX + jwtToken);
@Override
public RepositoryAuthenticationToken getInstallationToken(String apiUrl, String appId, String apiPrivateKey,
String projectPath) throws IOException {

Instant issued = clock.instant().minus(10, ChronoUnit.SECONDS);
Instant expiry = issued.plus(2, ChronoUnit.MINUTES);
String jwtToken = new DefaultJwtBuilder().setIssuedAt(Date.from(issued)).setExpiration(Date.from(expiry))
.claim("iss", appId).signWith(createPrivateKey(apiPrivateKey), SignatureAlgorithm.RS256).compact();

ObjectMapper objectMapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

try (Reader reader = new InputStreamReader(accessTokenConnection.getInputStream())) {
AppToken appToken = objectMapper.readerFor(AppToken.class).readValue(reader);
List<AppInstallation> appInstallations = getAppInstallations(objectMapper, getV3Url(apiUrl) + "/app/installations", jwtToken);

String targetUrl = installation.getRepositoriesUrl();
for (AppInstallation installation : appInstallations) {
URLConnection accessTokenConnection = urlProvider.createUrlConnection(installation.getAccessTokensUrl());
((HttpURLConnection) accessTokenConnection).setRequestMethod("POST");
accessTokenConnection.setRequestProperty(ACCEPT_HEADER, APP_PREVIEW_ACCEPT_HEADER);
accessTokenConnection
.setRequestProperty(AUTHORIZATION_HEADER, BEARER_AUTHORIZATION_HEADER_PREFIX + jwtToken);

Optional<RepositoryAuthenticationToken> potentialRepositoryAuthenticationToken = findRepositoryAuthenticationToken(appToken, targetUrl, projectPath);

if (potentialRepositoryAuthenticationToken.isPresent()) {
return potentialRepositoryAuthenticationToken;
}
try (Reader reader = new InputStreamReader(accessTokenConnection.getInputStream())) {
AppToken appToken = objectMapper.readerFor(AppToken.class).readValue(reader);

String targetUrl = installation.getRepositoriesUrl();

Optional<RepositoryAuthenticationToken> potentialRepositoryAuthenticationToken = findRepositoryAuthenticationToken(appToken, targetUrl, projectPath, objectMapper);

if (potentialRepositoryAuthenticationToken.isPresent()) {
return potentialRepositoryAuthenticationToken.get();
}

}
}

return Optional.empty();
throw new InvalidConfigurationException(InvalidConfigurationException.Scope.PROJECT,
"No token could be found with access to the requested repository using the given application ID and key");
}

private Optional<RepositoryAuthenticationToken> findRepositoryAuthenticationToken(AppToken appToken, String targetUrl,
String projectPath) throws IOException {
String projectPath, ObjectMapper objectMapper) throws IOException {
URLConnection installationRepositoriesConnection = urlProvider.createUrlConnection(targetUrl);
((HttpURLConnection) installationRepositoriesConnection).setRequestMethod("GET");
installationRepositoriesConnection.setRequestProperty(ACCEPT_HEADER, APP_PREVIEW_ACCEPT_HEADER);
Expand All @@ -160,7 +161,7 @@ private Optional<RepositoryAuthenticationToken> findRepositoryAuthenticationToke
return Optional.empty();
}

return findRepositoryAuthenticationToken(appToken, nextLink.get(), projectPath);
return findRepositoryAuthenticationToken(appToken, nextLink.get(), projectPath, objectMapper);
}

private static String getV3Url(String apiUrl) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ public String getPullRequestKey() {
public String getTargetBranchName() {
return targetBranchName;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private static Branch createBranch(DbClient dbClient, String branchName, String

private static Optional<BranchDto> findBranchByUuid(String projectUuid, DbClient dbClient) {
try (DbSession dbSession = dbClient.openSession(false)) {
return dbClient.branchDao().selectMainBranchByProjectUuid(dbSession, projectUuid);
return dbClient.branchDao().selectByUuid(dbSession, projectUuid);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,21 @@
*/
package com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup;

import java.util.Set;

public final class Link extends Node {

private static final Set<Class<? extends Node>> SUPPORTED_CHILDREN = Set.of(Text.class, Image.class);
private final String url;

public Link(String url, Node... children) {
super(children);
this.url = url;
}
this.url=url;
}

public String getUrl() {
return url;
}

@Override
boolean isValidChild(Node child) {
return child != null && SUPPORTED_CHILDREN.contains(child.getClass());
return child instanceof Text;
}
}
Loading

0 comments on commit 513f32a

Please sign in to comment.