Skip to content

Commit 731d2e8

Browse files
authored
Merge pull request #666 from akash-manna-sky/JENKINS-72544
Hide source code if user does not have access to workspace
2 parents cc932e7 + dec1163 commit 731d2e8

File tree

5 files changed

+77
-11
lines changed

5 files changed

+77
-11
lines changed

plugin/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
<dependency>
150150
<groupId>io.jenkins.plugins</groupId>
151151
<artifactId>prism-api</artifactId>
152+
<version>1.30.0-703.v116fb_3b_5b_b_a_a_</version>
152153
</dependency>
153154

154155
<!-- Test Dependencies -->

plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModel.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import hudson.model.Run;
4141

4242
import io.jenkins.plugins.bootstrap5.MessagesViewModel;
43+
import io.jenkins.plugins.prism.SourceCodeViewModel;
4344
import io.jenkins.plugins.coverage.metrics.charts.TreeMapNodeConverter;
4445
import io.jenkins.plugins.coverage.metrics.color.ColorProvider;
4546
import io.jenkins.plugins.coverage.metrics.color.ColorProviderFactory;
@@ -401,6 +402,9 @@ public String getUrlForBuild(final String selectedBuildDisplayName, final String
401402
*/
402403
@JavaScriptMethod
403404
public String getSourceCode(final String fileHash, final String tableId) {
405+
if (!SourceCodeViewModel.hasPermissionToViewSourceCode(getOwner())) {
406+
return Messages.Coverage_Permission_Denied();
407+
}
404408
Optional<Node> targetResult
405409
= getNode().findByHashCode(Metric.FILE, Integer.parseInt(fileHash));
406410
if (targetResult.isPresent()) {
@@ -519,7 +523,9 @@ public Object getDynamic(final String link, final StaplerRequest2 request, final
519523
Optional<Node> targetResult
520524
= getNode().findByHashCode(Metric.FILE, Integer.parseInt(link));
521525
if (targetResult.isPresent() && targetResult.get() instanceof FileNode) {
522-
return new SourceViewModel(getOwner(), getId(), (FileNode) targetResult.get());
526+
var fileNode = (FileNode) targetResult.get();
527+
var view = new SourceViewModel(getOwner(), getId(), fileNode);
528+
return SourceCodeViewModel.protectedSourceCodeView(view, getOwner(), fileNode.getName());
523529
}
524530
}
525531
catch (NumberFormatException exception) {

plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/Messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Parser.VectorCAST=VectorCAST Coverage Results
1414
Parser.Xunit=XUnit Test Results
1515

1616
Coverage.Not.Available=N/A
17+
Coverage.Permission.Denied=You do not have Jenkins' WORKSPACE permission to view the source code
1718
Coverage.Link.Name=Coverage Report
1819
Coverage.Trend.Name={0} Trend
1920
Coverage.Trend.Default.Name=Code Coverage Trend
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package io.jenkins.plugins.coverage.metrics.steps;
2+
3+
import org.apache.commons.lang3.StringUtils;
4+
import org.junit.jupiter.api.Test;
5+
6+
import edu.hm.hafner.coverage.Node;
7+
import edu.hm.hafner.coverage.parser.JacocoParser;
8+
import edu.hm.hafner.util.FilteredLog;
9+
10+
import java.io.IOException;
11+
import java.io.InputStream;
12+
import java.io.InputStreamReader;
13+
import java.nio.charset.StandardCharsets;
14+
import java.util.function.Function;
15+
16+
import hudson.model.Run;
17+
18+
import io.jenkins.plugins.coverage.metrics.AbstractCoverageITest;
19+
import io.jenkins.plugins.coverage.metrics.AbstractCoverageTest;
20+
import io.jenkins.plugins.util.QualityGateResult;
21+
22+
import static io.jenkins.plugins.coverage.metrics.steps.CoverageViewModel.*;
23+
import static org.assertj.core.api.Assertions.*;
24+
import static org.mockito.Mockito.*;
25+
26+
/**
27+
* Integration tests for the class {@link CoverageViewModel} that require a running Jenkins instance.
28+
* These tests verify permission-protected functionality like source code viewing.
29+
*
30+
* @author Akash Manna
31+
*/
32+
class CoverageViewModelITest extends AbstractCoverageITest {
33+
@Test
34+
void shouldReturnEmptySourceViewForExistingLinkButMissingSourceFile() {
35+
var model = createModelFromCodingStyleReport();
36+
37+
String hash = String.valueOf("PathUtil.java".hashCode());
38+
assertThat(model.getSourceCode(hash, ABSOLUTE_COVERAGE_TABLE_ID)).isEqualTo("N/A");
39+
assertThat(model.getSourceCode(hash, MODIFIED_LINES_COVERAGE_TABLE_ID)).isEqualTo("N/A");
40+
assertThat(model.getSourceCode(hash, INDIRECT_COVERAGE_TABLE_ID)).isEqualTo("N/A");
41+
}
42+
43+
private CoverageViewModel createModelFromCodingStyleReport() {
44+
return createModel(readJacocoResult("jacoco-codingstyle.xml"));
45+
}
46+
47+
private Node readJacocoResult(final String fileName) {
48+
FilteredLog log = new FilteredLog("Errors");
49+
try (InputStream stream = CoverageViewModelITest.class.getResourceAsStream(fileName);
50+
InputStreamReader reader = stream == null ? null : new InputStreamReader(stream, StandardCharsets.UTF_8)) {
51+
if (reader == null) {
52+
throw new AssertionError("Test resource not found: " + fileName);
53+
}
54+
var node = new JacocoParser().parse(reader, fileName, log);
55+
node.splitPackages();
56+
return node;
57+
}
58+
catch (IOException e) {
59+
throw new AssertionError("Failed to read test resource: " + fileName, e);
60+
}
61+
}
62+
63+
private CoverageViewModel createModel(final Node node) {
64+
return new CoverageViewModel(mock(Run.class), "id", StringUtils.EMPTY,
65+
node, AbstractCoverageTest.createStatistics(), new QualityGateResult(), "-", new FilteredLog("Errors"),
66+
Function.identity(), Function.identity());
67+
}
68+
}

plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModelTest.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@
3030
* @author Florian Orendi
3131
*/
3232
class CoverageViewModelTest extends AbstractCoverageTest {
33-
@Test
34-
void shouldReturnEmptySourceViewForExistingLinkButMissingSourceFile() {
35-
var model = createModelFromCodingStyleReport();
36-
37-
String hash = String.valueOf("PathUtil.java".hashCode());
38-
assertThat(model.getSourceCode(hash, ABSOLUTE_COVERAGE_TABLE_ID)).isEqualTo("N/A");
39-
assertThat(model.getSourceCode(hash, MODIFIED_LINES_COVERAGE_TABLE_ID)).isEqualTo("N/A");
40-
assertThat(model.getSourceCode(hash, INDIRECT_COVERAGE_TABLE_ID)).isEqualTo("N/A");
41-
}
42-
4333
@Test
4434
void shouldReportOverview() {
4535
var model = createModelFromCodingStyleReport();

0 commit comments

Comments
 (0)