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-69917] - Snippetizer/index.jelly javascript un-inlined. #599

Merged
merged 8 commits into from
Dec 7, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
function handlePrototype(url, crumb) {
buildFormTree(document.forms.config);
// TODO JSON.stringify fails in some circumstances: https://gist.github.com/jglick/70ec4b15c1f628fdf2e9 due to Array.prototype.toJSON
// TODO simplify when Prototype.js is removed
const json = Object.toJSON ? Object.toJSON(JSON.parse(document.forms.config.elements.json.value).prototype) : JSON.stringify(JSON.parse(document.forms.config.elements.json.value).prototype);
if (!json) {
return; // just a separator
}

const xhr = new XMLHttpRequest();
Artmorse marked this conversation as resolved.
Show resolved Hide resolved
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Jenkins-Crumb", crumb);

xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
document.getElementById('prototypeText').value = xhr.responseText;
}
}
};

xhr.send("json=" + encodeURIComponent(json));
}


document.addEventListener('DOMContentLoaded', () => {

const generatePipelineScript = document.getElementById("generatePipelineScript");
const url = generatePipelineScript.getAttribute("data-url");
const crumb = generatePipelineScript.getAttribute("data-crumb");
generatePipelineScript.onclick = (_) => {
Comment on lines +33 to +38
Copy link
Member

Choose a reason for hiding this comment

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

Using a class and Behaviour.specify is more conventional I think, but this should be fine as well.

handlePrototype(url, crumb);
return false;
};

});
Original file line number Diff line number Diff line change
Expand Up @@ -67,36 +67,13 @@ THE SOFTWARE.
<f:dropdownListBlock title="${%— Advanced/Deprecated —}"/>
<local:listSteps quasiDescriptors="${it.getQuasiDescriptors(true)}"/>
</f:dropdownList>
<j:set var="id" value="${h.generateId()}"/>
Copy link
Member

Choose a reason for hiding this comment

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

Note that removing generateId and reverting to a hard-coded id loses the ability for this code to exist in multiple places in a page. Not an issue in this case since it exists only in one place in a top-level page. The general approach is to use behaviors and look up elements via relative DOM path.

<f:block>
<input type="button" value="${%Generate Pipeline Script}" onclick="handlePrototype_${id}(); return false" class="submit-button primary"/>
<f:textarea id="prototypeText_${id}" readonly="true" style="margin-top: 10px" />
<script>
function handlePrototype_${id}() {
buildFormTree(document.forms.config);
// TODO JSON.stringify fails in some circumstances: https://gist.github.com/jglick/70ec4b15c1f628fdf2e9 due to Array.prototype.toJSON
// TODO simplify when Prototype.js is removed
var json = Object.toJSON ? Object.toJSON(JSON.parse(document.forms.config.elements.json.value).prototype) : JSON.stringify(JSON.parse(document.forms.config.elements.json.value).prototype);
if (!json) {
return; // just a separator
}
fetch('${rootURL}/${it.GENERATE_URL}', {
method: 'post',
headers: crumb.wrap({
"Content-Type": "application/x-www-form-urlencoded",
}),
body: new URLSearchParams({
json: json,
}),
}).then((rsp) => {
if (rsp.ok) {
rsp.text().then((responseText) => {
document.getElementById('prototypeText_${id}').value = responseText;
});
}
});
}
</script>
<input type="button" id="generatePipelineScript" value="${%Generate Pipeline Script}"
class="submit-button primary"
data-url="${rootURL}/${it.GENERATE_URL}"
data-crumb="${h.getCrumb(request)}"/>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added the jenkins crumb to avoid 403.
That's the easiest way, I found, to pass it to the javascript script.

Copy link
Member

Choose a reason for hiding this comment

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

Could also just add a CrumbExclusion for

public HttpResponse doGenerateSnippet(StaplerRequest req, @QueryParameter String json) throws Exception {
since it takes POST only to handle larger quantities of input but it is in fact read-only so not a CSRF threat. Anyway, this is the straightforward translation of the original.

<f:textarea id="prototypeText" readonly="true" style="margin-top: 10px"/>
<st:adjunct includes="org.jenkinsci.plugins.workflow.cps.Snippetizer.handle-prototype"/>
</f:block>
<f:section title="${%Global Variables}"/>
<f:block>
Expand Down
Loading