Skip to content

Commit

Permalink
Merge pull request jenkinsci#42 from ikedam/feature/JENKINS-57917_Add…
Browse files Browse the repository at this point in the history
…HtmlBadge

[JENKINS-57917] Add `AddHtmlBadge` feature
  • Loading branch information
ikedam committed Jun 15, 2019
2 parents df90a16 + b5e678a commit 60986ad
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 5 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<properties>
<jenkins.version>2.121.1</jenkins.version>
<java.level>8</java.level>
<badge-plugin.version>1.2</badge-plugin.version>
<badge-plugin.version>1.5</badge-plugin.version>
<workflow-step-api-plugin.version>2.20</workflow-step-api-plugin.version>
<workflow-cps-plugin.version>2.69</workflow-cps-plugin.version>
</properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@
import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext;
import org.jenkinsci.plugins.scriptsecurity.scripts.ClasspathEntry;

import com.jenkinsci.plugins.badge.action.AbstractBadgeAction;
import com.jenkinsci.plugins.badge.action.BadgeAction;
import com.jenkinsci.plugins.badge.action.BadgeSummaryAction;
import com.jenkinsci.plugins.badge.action.HtmlBadgeAction;

/** This class associates {@link BadgeAction}s to a build. */
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -169,6 +171,11 @@ public void addErrorBadge(String text) {
build.addAction(BadgeAction.createErrorBadge(text));
}

@Whitelisted
public void addHtmlBadge(String html) {
build.addAction(HtmlBadgeAction.createHtmlBadge(html));
}

@Whitelisted
public String getResult() {
Result r = build.getResult();
Expand All @@ -177,18 +184,18 @@ public String getResult() {

@Whitelisted
public void removeBadges() {
List<BadgeAction> badgeActions = build.getActions(BadgeAction.class);
for (BadgeAction a : badgeActions) {
List<AbstractBadgeAction> badgeActions = build.getActions(AbstractBadgeAction.class);
for (AbstractBadgeAction a : badgeActions) {
build.removeAction(a);
}
}
@Whitelisted
public void removeBadge(int index) {
List<BadgeAction> badgeActions = build.getActions(BadgeAction.class);
List<AbstractBadgeAction> badgeActions = build.getActions(AbstractBadgeAction.class);
if(index < 0 || index >= badgeActions.size()) {
listener.error("Invalid badge index: " + index + ". Allowed values: 0 .. " + (badgeActions.size()-1));
} else {
BadgeAction action = badgeActions.get(index);
AbstractBadgeAction action = badgeActions.get(index);
build.removeAction(action);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

import org.acegisecurity.Authentication;
import org.apache.commons.lang.StringUtils;
import org.hamcrest.Matchers;
import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript;
import org.jenkinsci.plugins.scriptsecurity.scripts.ClasspathEntry;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
Expand Down Expand Up @@ -501,6 +502,95 @@ public void testBadgeMigration() throws Exception {
}
}

@Test
public void testAddShortText() throws Exception {
FreeStyleProject p = j.createFreeStyleProject();

p.getPublishersList().add(new GroovyPostbuildRecorder(
new SecureGroovyScript(
"manager.addShortText('some-badge-text');",
true, // sandbox
Collections.<ClasspathEntry>emptyList()
),
2, // behavior
false // runForMatrixParent
));

j.assertBuildStatusSuccess(p.scheduleBuild2(0));

assertThat(
j.createWebClient().getPage(p).asText(),
Matchers.containsString("some-badge-text")
);
}

@Test
public void testAddShortTextHtmlIsEscaped() throws Exception {
// This test is to make it clear that
// addShortText() doesn't allow HTMLs
// even though that implementation is
// in badge-plugin.
FreeStyleProject p = j.createFreeStyleProject();

p.getPublishersList().add(new GroovyPostbuildRecorder(
new SecureGroovyScript(
"manager.addShortText('<div id=\"should-be-escaped\">foobar</div>');",
true, // sandbox
Collections.<ClasspathEntry>emptyList()
),
2, // behavior
false // runForMatrixParent
));

assertNull(j.createWebClient().getPage(p).getElementById("should-be-escaped"));
}

@Test
public void testAddHtmlBadge() throws Exception {
FreeStyleProject p = j.createFreeStyleProject();

p.getPublishersList().add(new GroovyPostbuildRecorder(
new SecureGroovyScript(
"manager.addHtmlBadge('<div id=\"added-as-badge\">foobar</div>');",
true, // sandbox
Collections.<ClasspathEntry>emptyList()
),
2, // behavior
false // runForMatrixParent
));

j.assertBuildStatusSuccess(p.scheduleBuild2(0));

assertEquals(
"foobar",
j.createWebClient().getPage(p).getElementById("added-as-badge").getTextContent()
);
}


@Test
public void testAddHtmlBadgeForUnsafeHtml() throws Exception {
// This test is to make it sure that
// addHtmlBadge() doesn't allow danger HTMLs
// even though that implementation is
// in badge-plugin.
FreeStyleProject p = j.createFreeStyleProject();

p.getPublishersList().add(new GroovyPostbuildRecorder(
new SecureGroovyScript(
"manager.addHtmlBadge('<script id=\"should-be-untainted\">alert(\"exploit!\");</script>');",
true, // sandbox
Collections.<ClasspathEntry>emptyList()
),
2, // behavior
false // runForMatrixParent
));

j.assertBuildStatusSuccess(p.scheduleBuild2(0));

assertNull(j.createWebClient().getPage(p).getElementById("should-be-untainted"));
}

@Test
public void testRemoveBadge() throws Exception {
FreeStyleProject p = j.createFreeStyleProject();
Expand Down Expand Up @@ -555,6 +645,38 @@ public void testRemoveBadges() throws Exception {
);
}

@Test
public void testRemoveBadgeForHtmlBadge() throws Exception {
// removeBadge() also removes HtmlBadges
FreeStyleProject p = j.createFreeStyleProject();

p.getPublishersList().add(new GroovyPostbuildRecorder(
new SecureGroovyScript(
"manager.addHtmlBadge('test1');\n"
+ "manager.addShortText('test2');\n"
+ "manager.removeBadge(0);",
true, // sandbox
Collections.<ClasspathEntry>emptyList()
),
2, // behavior
false // runForMatrixParent
));

FreeStyleBuild b = j.assertBuildStatusSuccess(p.scheduleBuild2(0));
assertEquals(
Arrays.asList("test2"),
Lists.transform(
b.getActions(BadgeAction.class),
new Function<BadgeAction, String>() {
@Override
public String apply(BadgeAction badge) {
return badge.getText();
}
}
)
);
}

@Test
public void testRemoveSummary() throws Exception {
String template = "method org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder$BadgeManager %s";
Expand Down

0 comments on commit 60986ad

Please sign in to comment.