Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-57917] Add AddHtmlBadge feature #42

Merged
merged 1 commit into from
Jun 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addHtmlBadge is introduced in 1.3.
There's a security fix in 1.5.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you switch to the latest version?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I consider those definitions for other plugins as requirements rather than dependencies in standard Java projects.

<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 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though tests for AddShortText is not directly related to this request,
I added those tests in this request as the unexpected regression was caused
for there was no test codes for badge-related features.

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