Skip to content

Commit

Permalink
Merge branch 'master' into new-alerts-3
Browse files Browse the repository at this point in the history
  • Loading branch information
janfaracik committed Feb 29, 2024
2 parents 29374b0 + 0eed048 commit 5fd2b74
Show file tree
Hide file tree
Showing 21 changed files with 659 additions and 364 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/announce-lts-rc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Post on Discourse
uses: roots/discourse-topic-github-release-action@fc9e50fa1a1ce6255ba4d03f104382845b79ad5f # v1.0.0
uses: roots/discourse-topic-github-release-action@c30dc233349b7c6f24f52fb1c659cc64f13b5474 # v1.0.1
with:
discourse-api-key: ${{ secrets.DISCOURSE_RELEASES_API_KEY }}
discourse-base-url: https://community.jenkins.io/
Expand Down
4 changes: 2 additions & 2 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ THE SOFTWARE.
<properties>
<asm.version>9.6</asm.version>
<slf4jVersion>2.0.12</slf4jVersion>
<stapler.version>1822.v120278426e1c</stapler.version>
<stapler.version>1839.ved17667b_a_eb_5</stapler.version>
<groovy.version>2.4.21</groovy.version>
</properties>

Expand All @@ -64,7 +64,7 @@ THE SOFTWARE.
<!-- https://docs.spring.io/spring-security/site/docs/5.5.4/reference/html5/#getting-maven-no-boot -->
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>5.8.9</version>
<version>5.8.10</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down
2 changes: 1 addition & 1 deletion cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>
<executions>
<execution>
<goals>
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/hudson/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -2242,10 +2242,19 @@ public static boolean isWipeOutPermissionEnabled() {
return SystemProperties.getBoolean("hudson.security.WipeOutPermission");
}

@Deprecated
public static String createRenderOnDemandProxy(JellyContext context, String attributesToCapture) {
return Stapler.getCurrentRequest().createJavaScriptProxy(new RenderOnDemandClosure(context, attributesToCapture));
}

/**
* Called from renderOnDemand.jelly to generate the parameters for the proxy object generation.
*/
@Restricted(NoExternalUse.class)
public static StaplerRequest.RenderOnDemandParameters createRenderOnDemandProxyParameters(JellyContext context, String attributesToCapture) {
return Stapler.getCurrentRequest().createJavaScriptProxyParameters(new RenderOnDemandClosure(context, attributesToCapture));
}

public static String getCurrentDescriptorByNameUrl() {
return Descriptor.getCurrentDescriptorByNameUrl();
}
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/hudson/util/FormValidation.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import static hudson.Util.singleQuote;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.FilePath;
import hudson.Functions;
import hudson.Launcher;
Expand Down Expand Up @@ -225,6 +226,7 @@ public static FormValidation warning(Throwable e, String format, Object... args)
* @return Validation of the least successful kind aggregating all child messages.
* @since 1.590
*/
@SuppressFBWarnings(value = "POTENTIAL_XML_INJECTION", justification = "intentional; caller's responsibility to escape HTML")
public static @NonNull FormValidation aggregate(@NonNull Collection<FormValidation> validations) {
if (validations == null || validations.isEmpty()) return FormValidation.ok();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ THE SOFTWARE.
</j:choose>
<j:if test="${!item.params.isEmpty()}">
<div style="float:right;margin-right:10px;">
<a href="#" tooltip="Build Parameters:${item.params}"><l:icon class="icon-notepad icon-sm" /></a>
<l:icon src="symbol-parameters" class="icon-sm" tooltip="Build Parameters:${item.params}"/>
</div>
</j:if>
</div>
Expand Down
6 changes: 5 additions & 1 deletion core/src/main/resources/lib/layout/renderOnDemand.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ THE SOFTWARE.
</st:attribute>
</st:documentation>

<j:set var="parameters" value="${h.createRenderOnDemandProxyParameters(context,attrs.capture)}"/>
<x:element name="${attrs.tag?:'div'}">
<x:attribute name="class">render-on-demand ${attrs.clazz}</x:attribute>
<x:attribute name="proxy">${h.createRenderOnDemandProxy(context,attrs.capture)}</x:attribute>
<x:attribute name="data-proxy-method">${parameters.proxyMethod}</x:attribute>
<x:attribute name="data-proxy-url">${parameters.url}</x:attribute>
<x:attribute name="data-proxy-crumb">${parameters.crumb}</x:attribute>
<x:attribute name="data-proxy-url-names">${parameters.urlNames}</x:attribute>
</x:element>
</j:jelly>
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci</groupId>
<artifactId>jenkins</artifactId>
<version>1.110</version>
<version>1.111</version>
<relativePath />
</parent>

Expand Down Expand Up @@ -73,7 +73,7 @@ THE SOFTWARE.
</issueManagement>

<properties>
<revision>2.447</revision>
<revision>2.448</revision>
<changelist>-SNAPSHOT</changelist>

<!-- configuration for patch tracker plugin -->
Expand Down
6 changes: 3 additions & 3 deletions test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ THE SOFTWARE.
<!-- RequireUpperBoundDeps between bootstrap5-api and echarts-api -->
<groupId>io.jenkins.plugins</groupId>
<artifactId>font-awesome-api</artifactId>
<version>6.5.1-2</version>
<version>6.5.1-3</version>
</dependency>
<dependency>
<groupId>io.jenkins.plugins</groupId>
Expand Down Expand Up @@ -131,7 +131,7 @@ THE SOFTWARE.
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>2161.v114f3cb_78326</version>
<version>2165.vf0266a_2d187f</version>
<scope>test</scope>
<exclusions>
<exclusion>
Expand Down Expand Up @@ -200,7 +200,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>cloudbees-folder</artifactId>
<version>6.901.vb_4c7a_da_75da_3</version>
<version>6.921.vfb_b_224371fb_4</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
176 changes: 176 additions & 0 deletions test/src/test/java/org/kohsuke/stapler/BindTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package org.kohsuke.stapler;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;

import hudson.ExtensionList;
import hudson.model.InvisibleAction;
import hudson.model.RootAction;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.htmlunit.Page;
import org.htmlunit.ScriptException;
import org.htmlunit.html.HtmlPage;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.bind.JavaScriptMethod;
import org.kohsuke.stapler.bind.WithWellKnownURL;

@RunWith(Parameterized.class)
public class BindTest {
@Rule
public JenkinsRule j = new JenkinsRule();

@Parameterized.Parameters
public static List<String> contexts() {
return Arrays.asList("/jenkins", "");
}

public BindTest(String contextPath) {
j.contextPath = contextPath;
}

@Test
public void bindNormal() throws Exception {
final RootActionImpl root = ExtensionList.lookupSingleton(RootActionImpl.class);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
final HtmlPage htmlPage = wc.goTo(root.getUrlName());
final String scriptUrl = htmlPage
.getElementsByTagName("script")
.stream()
.filter(it -> it.getAttribute("src").startsWith(j.contextPath + "/$stapler/bound/script" + j.contextPath + "/$stapler/bound/"))
.findFirst()
.orElseThrow()
.getAttribute("src");

final Page script = wc.goTo(StringUtils.removeStart(scriptUrl, j.contextPath + "/"), "application/javascript");
final String content = script.getWebResponse().getContentAsString();
assertThat(content, startsWith("varname = makeStaplerProxy('" + j.contextPath + "/$stapler/bound/"));
assertThat(content, endsWith("','test',['annotatedJsMethod1','byName1']);"));
}
assertThat(root.invocations, is(1));
}

@Test
public void bindWithWellKnownURL() throws Exception {
final RootActionWithWellKnownURL root = ExtensionList.lookupSingleton(RootActionWithWellKnownURL.class);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
final HtmlPage htmlPage = wc.goTo(root.getUrlName());
final String scriptUrl = htmlPage
.getElementsByTagName("script")
.stream()
.filter(it -> it.getAttribute("src").startsWith(j.contextPath + "/$stapler/bound/script" + j.contextPath + "/theWellKnownRoot?"))
.findFirst()
.orElseThrow()
.getAttribute("src");

final Page script = wc.goTo(StringUtils.removeStart(scriptUrl, j.contextPath + "/"), "application/javascript");
assertThat(script.getWebResponse().getContentAsString(), is("varname = makeStaplerProxy('" + j.contextPath + "/theWellKnownRoot','test',['annotatedJsMethod2','byName2']);"));
}
assertThat(root.invocations, is(1));
}

@Test
public void bindNull() throws Exception {
final RootActionImpl root = ExtensionList.lookupSingleton(RootActionImpl.class);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
final ScriptException exception = assertThrows(ScriptException.class, () -> wc.goTo(root.getUrlName() + "/null"));
assertThat(exception.getFailingLineNumber(), is(2));
assertThat(exception.getFailingColumnNumber(), is(0));
assertThat(exception.getMessage(), containsString("TypeError: Cannot call method \"byName1\" of null"));

final HtmlPage htmlPage = exception.getPage();
final String scriptUrl = htmlPage.getElementsByTagName("script").stream().filter(it -> it.getAttribute("src").equals(j.contextPath + "/$stapler/bound/script/null?var=varname")).findFirst().orElseThrow().getAttribute("src");

final Page script = wc.goTo(StringUtils.removeStart(scriptUrl, j.contextPath + "/"), "application/javascript");
final String content = script.getWebResponse().getContentAsString();
assertThat(content, is("varname = null;"));
}
assertThat(root.invocations, is(0));
}

@Test
public void bindUnsafe() throws Exception {
final RootActionImpl root = ExtensionList.lookupSingleton(RootActionImpl.class);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
final HtmlPage htmlPage = wc.goTo(root.getUrlName() + "/unsafe-var");
final String content = htmlPage
.getElementsByTagName("script")
.stream()
.filter(it -> it.getTextContent().contains("makeStaplerProxy"))
.findFirst()
.orElseThrow()
.getTextContent();

assertThat(content, startsWith("window['varname']=makeStaplerProxy('" + j.contextPath + "/$stapler/bound/"));
assertThat(content, endsWith("','test',['annotatedJsMethod1','byName1']);"));
}
assertThat(root.invocations, is(1));
}

@Test
public void bindInlineNull() throws Exception {
final RootActionImpl root = ExtensionList.lookupSingleton(RootActionImpl.class);
try (JenkinsRule.WebClient wc = j.createWebClient()) {
final HtmlPage htmlPage = wc.goTo(root.getUrlName() + "/inline-null");
final String content = htmlPage
.getElementsByTagName("script")
.stream()
.filter(it -> it.getTextContent().contains("var inline"))
.findFirst()
.orElseThrow()
.getTextContent();

assertThat(content, containsString("var inline = null"));
}
assertThat(root.invocations, is(0));
}

@TestExtension
public static class RootActionImpl extends InvisibleAction implements RootAction {
private int invocations;

@Override
public String getUrlName() {
return "theRoot";
}

@JavaScriptMethod
public void annotatedJsMethod1(String foo) {}

public void jsByName1() {
invocations++;
}
}

@TestExtension
public static class RootActionWithWellKnownURL extends InvisibleAction implements RootAction, WithWellKnownURL {
private int invocations;

@Override
public String getUrlName() {
return "theWellKnownRoot";
}

@Override
public String getWellKnownUrl() {
return "/" + getUrlName();
}

@JavaScriptMethod
public void annotatedJsMethod2(String foo) {}

public void jsByName2() {
invocations++;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-undef
varname.byName1();
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
<l:layout title="The Root">
<l:main-panel>
<h1>Root Action</h1>
<st:bind var="varname" value="${it}"/>
<st:adjunct includes="org.kohsuke.stapler.BindTest.RootActionImpl.adjunct"/>
</l:main-panel>
</l:layout>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
<l:layout title="The Root">
<l:main-panel>
<h1>Root Action</h1>
<script>
var inline = <st:bind value="${null}"/>
</script>
</l:main-panel>
</l:layout>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
<l:layout title="The Root">
<l:main-panel>
<h1>Root Action with null</h1>
<st:bind var="varname" value="${null}"/>
<st:adjunct includes="org.kohsuke.stapler.BindTest.RootActionImpl.adjunct"/>
</l:main-panel>
</l:layout>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
<l:layout title="The Root">
<l:main-panel>
<h1>Root Action</h1>
<st:bind var="window['varname']" value="${it}"/>
<st:adjunct includes="org.kohsuke.stapler.BindTest.RootActionImpl.adjunct"/>
</l:main-panel>
</l:layout>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-undef
varname.byName2();
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
<l:layout title="The Root">
<l:main-panel>
<h1>Root Action</h1>
<st:bind var="varname" value="${it}"/>
<st:adjunct includes="org.kohsuke.stapler.BindTest.RootActionWithWellKnownURL.adjunct"/>
</l:main-panel>
</l:layout>
</j:jelly>
Loading

0 comments on commit 5fd2b74

Please sign in to comment.